从Linux套接字发送/接收数据包后访问辅助数据时,msg_controllen在哪些情况下可以为0?

从Linux套接字发送/接收数据包后访问辅助数据时,msg_controllen在哪些情况下可以为0?,c,linux,sockets,linux-kernel,timestamp,C,Linux,Sockets,Linux Kernel,Timestamp,我正在开发一个非常复杂的C程序,该程序设计为在Linux下运行,它在很大程度上依赖于来自套接字的辅助数据 我实际上遇到了一个奇怪的行为,顺便说一句,这似乎只发生在我的程序上(其他示例代码,如,工作正常)。 我通过定义以下内容来使用辅助数据: struct msghdr mhdr; struct iovec iov; struct cmsghdr *cmsg = NULL; struct sockaddr_ll addrll; socklen_t addrllLen=sizeof(addrll);

我正在开发一个非常复杂的C程序,该程序设计为在Linux下运行,它在很大程度上依赖于来自套接字的辅助数据

我实际上遇到了一个奇怪的行为,顺便说一句,这似乎只发生在我的程序上(其他示例代码,如,工作正常)。 我通过定义以下内容来使用辅助数据:

struct msghdr mhdr;
struct iovec iov;
struct cmsghdr *cmsg = NULL;
struct sockaddr_ll addrll;
socklen_t addrllLen=sizeof(addrll);
unsigned char packet[PACKET_SIZE_MAX];
char ctrlBuf[CMSG_SPACE(sizeof(struct scm_timestamping))]; // For example, in order to retrieve timestamps
然后,通过设置:

    memset(&mhdr,0,sizeof(mhdr));

    iov.iov_base=packet;
    iov.iov_len=sizeof(packet);

    mhdr.msg_name=&(addrll); // This is a raw socket
    mhdr.msg_namelen=addrllLen; // This is a raw socket

    mhdr.msg_control=ctrlBuf;
    mhdr.msg_controllen=sizeof(ctrlBuf);

    mhdr.msg_iov=&iov;
    mhdr.msg_iovlen=1;

    mhdr.msg_flags=0;
然后,我使用
sendto()
recvmsg()
发送和接收数据,然后设置一些套接字选项以检索有用的辅助数据(例如,通过设置
SO\u时间戳
)来发送和接收软件或硬件时间戳)。我能够验证我打开的套接字是否支持这些选项

当我尝试使用如下代码提取辅助数据时,有时会出现问题,例如,使用发送/接收时间戳提取
struct scm\u时间戳

for(cmsg=CMSG_FIRSTHDR(&mhdr);cmsg!=NULL;cmsg=CMSG_NXTHDR(&mhdr, cmsg)) {
    if(cmsg->cmsg_level==SOL_SOCKET && cmsg->cmsg_type==SO_TIMESTAMPING) {
        hw_ts=*((struct scm_timestamping *)CMSG_DATA(cmsg));
    }
}
有时,
CMSG\u FIRSTHDR(&mhdr)
返回一个空指针,返回的
mhdr.msg\u controllen
0
,这样我就无法提取任何时间戳。 其他时候,在同一台PC上,使用同一个NIC,一切都很好


因此,我的问题是:在什么情况下,返回的
mhdr.msg_controllen
通常是
0
?这是否是由于结构msghdr的定义有问题造成的?或者这是由于某种内核问题造成的?

您的控制消息缓冲区可能尺寸过小,因为它没有对齐,并且第一个对齐边界以下的部分将不可用。我不确定设置缓冲区的正确惯用方法是什么(严格来说,使用
malloc
可能是避免由于对齐和有效类型/别名冲突而导致代码无效的唯一方法),但添加
\u Alignof(max\u align\u t)
(或
sizeof(max\u align\u t)
)调整缓冲区大小可能是一种解决方案。不过,我想知道公认的“正确”方法是什么

政府似乎建议建立一个联盟来保持一致:


谢谢你的回复!我试图迫使一些人结盟,但不幸的是,这并没有解决问题,因为情况没有改变。除了发送CSMG数据(如您报告的示例所示),接收CSMG数据(应分配缓冲区,但实际上由
recvmsg()
填充和管理,如我的情况)是否也需要对齐?即使我尝试过大我的缓冲区,当问题发生时,结果也是一样的:
mhdr.msg_controllen
0
,我无法提取任何辅助数据。
      union {         /* Ancillary data buffer, wrapped in a union
                         in order to ensure it is suitably aligned */
          char buf[CMSG_SPACE(sizeof(myfds))];
          struct cmsghdr align;
      } u;