多进程并发编程----进程间传递文件描述符案例
2016-04-15 17:34
477 查看
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<assert.h> #include<errno.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> #include<sys/socket.h> int send_fd(int fd, void *ptr, size_t nbytes, int sendfd) { struct msghdr msg; struct iovec iov[1]; union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; return(sendmsg(fd, &msg, 0)); } int recv_fd(int sockfd,void *data,size_t size,int *fd){ int num; struct msghdr msg; struct cmsghdr *cmsgptr; struct iovec vec[1]; union{ struct cmsghdr cmsg; char control[CMSG_SPACE(sizeof(int))]; }control_un; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); vec[0].iov_base=data; vec[0].iov_len=size; msg.msg_name=NULL; msg.msg_namelen=0; msg.msg_iov=vec; msg.msg_iovlen=1; if((num=recvmsg(sockfd,&msg,0))==-1){ printf("recvmsg error:%s\n",strerror(errno)); return num; } if((cmsgptr=CMSG_FIRSTHDR(&msg))!= NULL && cmsgptr->cmsg_len==CMSG_LEN(sizeof(int))){ if(cmsgptr->cmsg_level != SOL_SOCKET) printf("control level != SOL_SOCKET\n"); if(cmsgptr->cmsg_type != SCM_RIGHTS) printf("control type != SCM_RIGHTS\n"); *fd=*((int *)CMSG_DATA(cmsgptr)); } else *fd = -1; /* descriptor was not passed */ return num; } int main(){ char filebuf[1024]; char sendbuf[256]; char recvbuf[256]; int sockfd[2]; int pid; int fd; int ret,state,num; ret=socketpair(AF_UNIX,SOCK_STREAM,0,sockfd); assert(ret!=-1); pid=fork(); if(pid==0){ close(sockfd[0]); fd=open("wordexp.c",O_RDONLY,0666); assert(fd!=-1); memset(sendbuf,0,sizeof(sendbuf)); sprintf(sendbuf,"%s","hello,mm"); num=send_fd(sockfd[1],sendbuf,sizeof(sendbuf),fd); close(fd); exit(5); } waitpid(pid,&state,0); if(WIFEXITED(state)){ printf("child is exited,state[%d]\n",WEXITSTATUS(state)); close(sockfd[1]); memset(recvbuf,0,sizeof(recvbuf)); num=recv_fd(sockfd[0],recvbuf,sizeof(recvbuf),&fd); printf("recvbuf:[%s]\n",recvbuf); memset(filebuf,0,sizeof(filebuf)); read(fd,filebuf,sizeof(filebuf)); printf("buf:[%s]\n",filebuf); close(fd); } return 0; }
需要注意的是:
通常接收进程收到的套接字描述符的编号和发送进程的套接字描述符的编号会不一样,但这并没有任何问题。因为传递描述符并不是传递值的本身,而是在接收进程新建一个描述符并指向内核文件表中和发送进程发送的描述符相同的项。
相关文章推荐
- java反射代理学习
- Java中的多线程(五)之死锁演示
- Google Play服务中的条码扫描识别
- 巩固C语言(番外篇)----二级指针
- C#中索引器的作用和实现。
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseDAOFacto
- Spring MVC事务配置
- javaSocket多次传输没有重新初始化的一个对象接收端只会接收到第一个对象的值
- java 1.7之后的Arraylist容量增长机制
- 在ubuntu下使用VIM作为python开发环境
- PHP定时执行任务的实现
- 【QT】:QT中信号与槽详解
- Java学习路线
- 2.Java之if语句及三目运算符
- Python 练习实例14
- php不用递归实现无限分类数据的树形格式化
- Java中参数的引用传递和值传递
- Python之I/O多路复用
- 对于MyEclipse整合git上的maven项目导入
- php加密解密