通过本地套接字来传输msghdr结构体实现子进程共享父进程文件对象

本文介绍了如何通过本地套接字和socketpair方法建立父子进程间的全双工通信。重点讲解了在C语言环境下,如何使用fork创建子进程,并利用struct msghdr结构体进行消息传递,实现子进程共享父进程的文件对象。

利用socketpair创建类全双工管道进行父子进程通信

fork的使用

struct msghdr hdr;赋值操作需要熟练掌握

//实现父进程传输文件对象给子进程
int sendfd(int Wpipefd,int fdtosend)
{
    
    struct msghdr hdr;
    bzero(&hdr,sizeof(hdr));//一定要记得初始化hdr
    //进行正文信息的打包  正文部分一定要写
    char buf1[]="hello";
    char buf2[]="world";        
    struct iovec iov[2];
    iov[0].iov_base=buf1;
    iov[0].iov_len=5;
    iov[1].iov_base=buf2;
    iov[1].iov_len=5;
    hdr.msg_iov=iov;
    hdr.msg_iovlen=2;
    //进行控制信息的打包  这次我们的data是要进行传输的文件描述符
    struct cmsghdr *pcmsghdr;//可变长结构体一定要通过结构体指针指向calloc分配的堆区
    pcmsghdr = (struct cmsghdr *)calloc(1,CMSG_LEN(sizeof(int)));
    pcmsghdr->cmsg_len=CMSG_LEN(sizeof(int));//fdsize=4B;
    pcmsghdr->cmsg_level=SOL_SOCKET;
    pcmsghdr->cmsg_type=SCM_RIGHTS;//类型说明了要传递的是一个文件对象
    *(int *)CMSG_DATA(pcmsghdr)=fdtosend;//先获取data区域的首地址然后强转成int* 再接引用然后赋值
    hdr.msg_control=pcmsghdr;
    hdr.msg_controllen=CMSG_LEN(sizeof(int));
    //两部分打包好后 剩下的就是通过socketpair搞出来的管道 传递hdr大结构体
    int ret=sendmsg(Wpipefd,&hdr,0);
    ERROR_CHECK(ret,-1,"sendmsg");
    return 0;

}
int recvfd(int Rpipefd,int *pfdtosend)
{

    struct msghdr hdr;
    bzero(&hdr,sizeof(hdr));//一定要记得初始化hdr
    ////进行正文信息的打包  正文部分一定要写
    char buf1[6]={0};
    char buf2[6]={0};
    struct iovec iov[2];
    iov[0].iov_base=buf1;
    iov[0].iov_len=5;
    iov[1].iov_base=buf2;
    iov[1].iov_len=5;
    hdr.msg_iov=iov;
    hdr.msg_iovlen=2;
    //进行控制信息的打包  这次我们的data是要进行传输的文件描述符
    struct cmsghdr*pcmsghdr=(struct cmsghdr*)calloc(1,CMSG_LEN(sizeof(int)));
    pcmsghdr->cmsg_len=CMSG_LEN(sizeof(int));
    pcmsghdr->cmsg_level=SOL_SOCKET;
    pcmsghdr->cmsg_type=SCM_RIGHTS;
    hdr.msg_control=pcmsghdr;
    hdr.msg_controllen=CMSG_LEN(sizeof(int));
    int ret=recvmsg(Rpipefd,&hdr,0);
    //把从管道接收到的hdr结构体中的信息打印出来
    printf("%s\n",(char *)hdr.msg_iov[0].iov_base);
    printf("%s\n",(char *)hdr.msg_iov[1].iov_base);
    printf("recvfdFunc:filefd=%d\n",*(int*)CMSG_DATA(pcmsghdr));
    *pfdtosend=*(int*)CMSG_DATA(pcmsghdr);
    return 0;


}
int main()
{
    int pipefd[2]={0};
    int ret;
    ret=socketpair(AF_LOCAL,SOCK_STREAM,0,pipefd);
    ERROR_CHECK(ret,-1,"socketpair");
    //pipefd[0] for reading and pipefd[1] for writing
    if(0==fork())//return value is 0 standing for child process
    {
        //usleep(1000);
        puts("I am child process");
        close(pipefd[1]);
        int filefd;
        recvfd(pipefd[0],&filefd);
        ret=write(filefd,"Fanbing Wu",11);
        ERROR_CHECK(ret,-1,"ChildP:write");
        
        printf("child:filefd=%d\n",filefd);
        exit(0);
    }
    else//main process
    {
        int filefd=open("file",O_RDWR|O_CREAT,0666);
        ret=write(filefd,"Yujie Lai",10);     
        ERROR_CHECK(ret,-1,"MainP:write");   
        sendfd(pipefd[1],filefd);
        printf("Main:filefd=%d\n",filefd);
        wait(NULL);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值