在父子进程间用管道传递文件描述符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>

#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)

void send_fd(int sock_fd, int fd);
int recv_fd(const int sock_fd);

int main(int argc, const char *argv[])
{
    int fds[2];
    socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
    pid_t pid;
    pid = fork();
    if(pid < 0)
        ERR_EXIT("fork");
    else if(pid == 0){
        close(fds[1]);
        int fd = open("test.txt", O_RDONLY);
        if(fd == -1)
            ERR_EXIT("open");
        send_fd(fds[0], fd);
    }else{
        sleep(1);
        close(fds[0]);
        int fd = recv_fd(fds[1]);
        char buffer[1024] = {0};
        read(fd, buffer, 1024);
        printf("Recv msg: %s\n", buffer);
    }
    return 0;
}

void send_fd(int sock_fd, int fd)
{
        int ret;
        struct msghdr msg;
        struct cmsghdr *p_cmsg;
        struct iovec vec;
        char cmsgbuf[CMSG_SPACE(sizeof(fd))];
        int *p_fds;
        char sendchar = 0;
        msg.msg_control = cmsgbuf;
        msg.msg_controllen = sizeof(cmsgbuf);
        p_cmsg = CMSG_FIRSTHDR(&msg);
        p_cmsg->cmsg_level = SOL_SOCKET;
        p_cmsg->cmsg_type = SCM_RIGHTS;
        p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
        p_fds = (int*)CMSG_DATA(p_cmsg);
        *p_fds = fd;

        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        msg.msg_iov = &vec;
        msg.msg_iovlen = 1;
        msg.msg_flags = 0;

        vec.iov_base = &sendchar;
        vec.iov_len = sizeof(sendchar);
        ret = sendmsg(sock_fd, &msg, 0);
        if (ret != 1)
                ERR_EXIT("sendmsg");
}

int recv_fd(const int sock_fd)
{
        int ret;
        struct msghdr msg;
        char recvchar;
        struct iovec vec;
        int recv_fd;
        char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))];
        struct cmsghdr *p_cmsg;
        int *p_fd;
        vec.iov_base = &recvchar;
        vec.iov_len = sizeof(recvchar);
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        msg.msg_iov = &vec;
        msg.msg_iovlen = 1;
        msg.msg_control = cmsgbuf;
        msg.msg_controllen = sizeof(cmsgbuf);
        msg.msg_flags = 0;

        p_fd = (int*)CMSG_DATA(CMSG_FIRSTHDR(&msg));
        *p_fd = -1;
        ret = recvmsg(sock_fd, &msg, 0);
        if (ret != 1)
                ERR_EXIT("recvmsg");

        p_cmsg = CMSG_FIRSTHDR(&msg);
        if (p_cmsg == NULL)
                ERR_EXIT("no passed fd");

        p_fd = (int*)CMSG_DATA(p_cmsg);
        recv_fd = *p_fd;
        if (recv_fd == -1)
                ERR_EXIT("no passed fd");

        return recv_fd;
}

时间: 2025-02-01 14:41:48

在父子进程间用管道传递文件描述符的相关文章

在进程间传递文件描述符

由于fork调用之后,父进程中打开的文件描述符在子进程中仍然保持打开,所以文件描述符可以很方便地从父进程传递到子进程.需要注意的是,传递一个文件描述符并不是传递一个文件描述符的值,而是要在接收进程中创建一个新的文件描述符,并且该文件描述符和发送进程中被传递的文件描述符指向内核中相同的文件表项. 在Linux下,我们可以利用UNIX城socket在进程间传递特殊的辅助数据,以实现文件描述符的传递,它在子进程中打开一个文件描述符,然后将它传递给父进程,父进程则通过读取该文件描述符来获得文件的内容.

进程间传递文件描述符

下面的实例展示了如何使用Unix域套接字在进程间传递文件描述符 参考文献:1) <Unix网络编程> 2)  http://book.51cto.com/art/200912/168560.htm 最近学习了使用Unix域套接字在进程间传递文件描述符,仿照参考资料,自己也写了简单的程序来实践这种技术. 其他不多说了,具体理论知识参见参考资料,开始我自己的程序介绍(在OpenSolaris 2009.06平台上测试): 1  程序作用说明:父进程,子进程以及另外一个进程向同一个文件的文件描述符向

进程间传递文件描述符——sendmsg和recvmsg函数

先引入一个例子,该程序的目的是子进程向父进程传递文件描述符,并通过该文件描述符读取buf. #include <func.h> int main(){ int fds[2]; pipe(fds); if(!fork()){ close(fds[1]); int fd; read(fds[0], &fd, sizeof(fd)); printf("child fd = %d\n", fd); char buf[128] = {0}; read(fd, buf, siz

0707 父子进程之间传递文件描述符

1 /************************************************************************* 2 > File Name: pass_fd.c 3 > Author:Monica 4 > Mail:[email protected] 5 > Created Time: Mon 07 Jul 2014 09:52:49 PM CST 6 ********************************************

UNIX进程之间传递文件描述符recvmsg与sendmsg

socketpair: 功能:创建一个全双工的流管道 原型 int socketpair(int domain, int type, int protocol, int sv[2]); 参数 domain: 协议家族 type: 套接字类型 protocol: 协议类型 sv: 返回套接字对 返回值:成功返回0:失败返回-1 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int

通过UNIX域套接字传递文件描述符

传送文件描述符是高并发网络服务编程的一种常见实现方式.Nebula 高性能通用网络框架即采用了UNIX域套接字传递文件描述符设计和实现.本文详细说明一下传送文件描述符的应用. 1. TCP服务器程序设计范式 ??开发一个服务器程序,有较多的的程序设计范式可供选择,不同范式有其自身的特点和实用范围,明了不同范式的特性有助于我们服务器程序的开发.常见的TCP服务器程序设计范式有以下几种: 迭代服务器 并发服务器,每个客户请求fork一个子进程 预先派生子进程,每个子进程无保护地调用accept 预先

python进程间传递文件描述符扩展库

由于python本身的线程基本上比较残废,所以为了利用机器的cpu,就不得不用上多进程... 在游戏服务器的设计中,最为常见的方式是: 挂一个前端服务器,专门来维护与客户端的连接,然后将客户端的请求数据转发给后端服务器... 上面的方式是现在最为正统的... 但是自己因为环境的限制,需要做到对客户端透明,然后将后端的服务器转换成为多进程的...所以这里就只有用一点比较别扭的方法了,首先处理登录等一些常规的逻辑放在前端服务器,当进入放进进行匹配战斗之后,将客户端的socket连接直接交给后端服务器

提高linux对最大进程数和最大打开文件描述符数的限制

打开/etc/security/limits.conf文件 在下面加入如下两行,其中wacos是用户名,*可以代表所有用户 wacos           -       nproc           20000 wacos           -       nofile          65536 noproc代表最大进程数 nofile代表最大文件打开数 然后在命令行输入:ulimit -a 查看,发现已经改变了. 另外,可以在普通用户的.profile文件中加入ulimit -n 1

服务器编程中的文件描述符

linux系统下一切皆文件,通过虚拟文件系统(VFS)的机制将所有底层屏蔽掉,用户可以通过统一的接口来实现对不同驱动的操作,对于每一个文件需要一个引用来指示,此时文件描述符应用而生,文件描述符类似于widows下的handle,对于文件的大部分操作都是通过这个描述符来操作的,例如read,write.对于每一个文件描述符,内核使用三种数据结构来管理. (1)  每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项.与每个文件描述符相关联的是