C 如何确定linux控制消息中多个辅助消息的大小

C 如何确定linux控制消息中多个辅助消息的大小,c,linux,posix,C,Linux,Posix,我尝试通过unix套接字一次发送多个文件描述符。对于单个插座来说,这没有问题。虽然当我尝试用CMSG\u NXTHDR附加另一个时,我得到一个空指针,指示我的缓冲区太短。对于一个文件描述符,我使用CMSG_SPACE计算了缓冲区大小,并假设我只需要将其相乘。尽管这似乎还不够。 我编写了一个简短的测试程序来检查这一点: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <

我尝试通过unix套接字一次发送多个文件描述符。对于单个插座来说,这没有问题。虽然当我尝试用
CMSG\u 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;
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
结构msghdr msg;
如果(argc!=2){
返回1;
}
联合{
结构cmsghdr-cmsghdr;
字符控制[CMSG_空间(sizeof(int))*atoi(argv[1]);
}cmsgu;
结构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\U电平=SOL\U插座;
cmsg->cmsg\U类型=SCM\U权限;
*((int*)CMSG_数据(CMSG))=-1;
cmsg=cmsg_NXTHDR(&msg,cmsg);
fprintf(标准字符,“%p\n”,cmsg);
返回0;
}
当我用1调用它时,它会输出一个预期的空指针。尽管我的期望是,如果使用2
CMSG\u NXTHDR
调用它,它将返回一个有效指针。第一个工作值为5(因此额外增加120字节)。我想
CMSG\u SPACE
会处理好的。有没有办法计算所需的空间?或者是否有更直接的方法在一条消息中发送多个文件描述符?

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

但是(为了回答第二个问题),如果要传递多个文件描述符,可以使用包含int数组的单个
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)手册页中的示例基本相同。

谢谢,这正是我所寻找的解决方案!