【问题标题】:How to determine size for multiple ancillary messages in linux control messages如何确定 linux 控制消息中多个辅助消息的大小
【发布时间】:2020-01-07 09:49:01
【问题描述】:

我尝试一次通过 unix 套接字发送多个文件描述符。这对于单个套接字来说是没有问题的。虽然当我尝试用CMSG_NXTHDR 附加另一个时,我得到一个空指针,表明我的缓冲区太短。对于一个文件描述符,我用CMSG_SPACE 计算了缓冲区大小,我假设我只需要乘以它。虽然这似乎还不够。 我写了一个简短的测试程序来检查这个:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    struct msghdr msg;

    if(argc != 2){
        return 1;
    }

    union {
        struct cmsghdr cmsghdr;
        char control[CMSG_SPACE(sizeof(int)) * atoi(argv[1])];
    } cmsgu;
    struct cmsghdr *cmsg;

    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = 0;
    msg.msg_iovlen = 0;

    msg.msg_control = cmsgu.control;
    msg.msg_controllen = sizeof(cmsgu.control);

    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    *((int *)CMSG_DATA(cmsg)) = -1;

    cmsg = CMSG_NXTHDR(&msg, cmsg);
    fprintf(stderr, "%p\n", cmsg);
    return 0;
}

当我用 1 调用它时,它会输出一个预期的空指针。尽管我的期望是,如果用 2 CMSG_NXTHDR 调用它会返回一个有效的指针。第一个工作值是 5(所以额外的 120 个字节)。我以为CMSG_SPACE 会解决这个问题。有没有办法去计算所需的空间?还是有更直接的方法可以在一条消息中发送多个文件描述符?

【问题讨论】:

    标签: c linux posix


    【解决方案1】:

    请参阅this question 并回答。如果您将 memset() cmsgu 设置为 0s,您的代码应该可以工作。

    但是(并回答您的第二个问题),如果您想传递多个文件描述符,您可以使用包含整数数组的单个 cmsghdr。修改你的例子,

        int n = atoi(argv[1]);
        int myfds[n]; // use this later
    
        union {
            struct cmsghdr cmsghdr; // for alignment
            char control[CMSG_SPACE(sizeof(int) * n)]; // space for one message
        } cmsgu;
        struct cmsghdr *cmsg;
    
        memset(&cmsgu, 0, sizeof(cmsgu)); // as noted
    
        msg.msg_name = 0;
        msg.msg_namelen = 0;
        msg.msg_iov = 0;
        msg.msg_iovlen = 0;
    
        msg.msg_control = cmsgu.control;
        msg.msg_controllen = sizeof(cmsgu.control);
    
        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n);
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
    
        int *fdptr = (int *) CMSG_DATA(cmsg);
        memcpy(fdptr, myfds, sizeof(int) * n);
    

    这与 cmsg(3) 手册页中的示例基本相同。

    【讨论】:

    • 谢谢,这正是我正在寻找的解决方案!
    猜你喜欢
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2011-10-22
    • 2011-06-11
    • 1970-01-01
    相关资源
    最近更新 更多