在来自freebsd
的ping的源代码中,当代码处理来自timestamp
套接字选项的SO_TIMESTAMP
的控制数据时,我注意到了这一点:
这里的例子:
#ifdef SO_TIMESTAMP
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
/* Copy to avoid alignment problems: */
memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
tv = &now;
}
#endif
作者想到的对齐问题是什么,为什么只保存指向CMSG_DATA(cmsg)
的指针是不够的?
在处理相同情况时,我自己复制辅助数据是否重要?
完整的源代码在这里:(See docs)
答案 0 :(得分:2)
cmsg
是struct cmsghdr
,它是一个可变长度结构,由开头的几个字段组成,后跟从cmsg_data
开始的任意字节。由于在编译时不知道任意字节的结构,因此字节开始的位置可能无法使结构中的字段正确对齐。 (有关背景信息,请参阅http://en.wikipedia.org/wiki/Data_structure_alignment。)
所以这里发生的事情是if
语句中的表达式是在运行时检查任意字节实际上是什么类型的数据。如果级别,类型和长度指示数据是struct timeval
,则将字节(通过CMSG_DATA
宏)复制到堆栈上正确对齐的结构中。