zoukankan      html  css  js  c++  java
  • 进程间传递文件描述符的方法

    UNP讲述了三种传递描述符的方法:

    1.使用ioctl

    2.如果是父子关系进程用socketpair

    3.没关系则使用unix socket

    这里介绍一下第三种,因为相对复杂繁琐:

      UNP里讲述了这个步骤:

      1.创建unix stream socket,其中要有一个是bind且在listen的。

      2.使用sendmsg与recvmsg接口传送描述符

      3.需要注意的是相关的工具宏和struct.具体翻阅14.5节.

    下面我自己写的两个示例代码,图一接收文件描述符并输出hello来验证,图二是要一个临时文件作为参数传入,并发送该文件的套接字给图一的进程.值得注意的是,在发送时,该文件描述符的引用计数会增加,因此关闭进程2并不会导致进程1使用此描述符.

    extern "C"
    {
    #include <unp.h>
    }
    
    int main(int argc, char **argv)
    {
        sockaddr_un seraddr;
        bzero(&seraddr, sizeof(seraddr));
        seraddr.sun_family = AF_UNIX;
        strcpy(seraddr.sun_path, UNIXSTR_PATH);
        int lisfd = socket(AF_UNIX, SOCK_STREAM, 0);
        int on = 1;
        unlink(UNIXSTR_PATH);
        Bind(lisfd, (SA *)&seraddr, sizeof(seraddr));
        Listen(lisfd, LISTENQ);
        sockaddr_un cliaddr;
        socklen_t addrlen;
        int connfd = Accept(lisfd, (SA *)&cliaddr, &addrlen);
        msghdr msg;
        iovec iov;
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        int tmp;
        iov.iov_base = &tmp;
        iov.iov_len = sizeof(int);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        union {
            cmsghdr cm;
            char control[CMSG_SPACE(sizeof(int))];
        } control_un;
        msg.msg_control = control_un.control;
        msg.msg_controllen = sizeof(control_un.control);
        if (recvmsg(connfd, &msg, 0) < 0)
        {
            perror("recvmsg");
        }
        int recvfd = -1;
        auto cmptr = CMSG_FIRSTHDR(&msg);
        if (cmptr == NULL)
        {
            perror("CMSG");
        }
        if (cmptr->cmsg_type != SCM_RIGHTS)
        {
            perror("type");
        }
        recvfd = *((int *)CMSG_DATA(cmptr));
        char buf[] = "hello";
        printf("the fd: %d  ", recvfd);
        Write(recvfd, buf, strlen(buf) + 1);
        exit(0);
    }
    extern "C"
    {
    #include <unp.h>
    }
    
    int main(int argc, char **argv)
    {
        int sndfd = open(argv[1], O_RDWR | O_TRUNC | O_CREAT);
        printf("the fd: %d", sndfd);
        sockaddr_un seraddr;
        bzero(&seraddr, sizeof(seraddr));
        seraddr.sun_family = AF_UNIX;
        strcpy(seraddr.sun_path, UNIXSTR_PATH);
        int connfd = Socket(AF_UNIX, SOCK_STREAM, 0);
        Connect(connfd, (SA *)&seraddr, sizeof(seraddr));
        msghdr msg;
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        iovec iov;
        iov.iov_base = &sndfd;
        iov.iov_len = sizeof(sndfd);
        msg.msg_flags = 0;
        union {
            cmsghdr cm;
            char pad[CMSG_SPACE(sizeof(int))];
        } control;
        msg.msg_control = control.pad;
        msg.msg_controllen = sizeof(control.pad);
        msg.msg_flags = 0;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        auto cmsgptr = CMSG_FIRSTHDR(&msg);
        cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
        cmsgptr->cmsg_level = SOL_SOCKET;
        cmsgptr->cmsg_type = SCM_RIGHTS;
        *(int *)CMSG_DATA(cmsgptr) = sndfd;
        sendmsg(connfd, &msg, 0);
        exit(0);
    }
  • 相关阅读:
    Java Spring AOP用法
    Spring IOC的简单实现
    随机数
    Java 正则表达式
    日期格式转换
    maven settings.xml详解
    JSP与Servlet的关系
    EL表达式学习
    FreeMarker学习2
    FreeMarker学习
  • 原文地址:https://www.cnblogs.com/manch1n/p/11545837.html
Copyright © 2011-2022 走看看