您的位置:首页 > 编程语言

多进程并发编程----进程间传递文件描述符案例

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;
}

需要注意的是:

通常接收进程收到的套接字描述符的编号和发送进程的套接字描述符的编号会不一样,但这并没有任何问题。因为传递描述符并不是传递值的本身,而是在接收进程新建一个描述符并指向内核文件表中和发送进程发送的描述符相同的项。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: