CMSG - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
CMSG_ALIGN,CMSG_SPACE,CMSG_NXTHDR,CMSG_FIRSTHDR-访问辅助数据
语法
#include <sys/socket.h> struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh); struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg); size_t CMSG_ALIGN(size_t length); size_t CMSG_SPACE(size_t length); size_t CMSG_LEN(size_t length); unsigned char *CMSG_DATA(struct cmsghdr *cmsg);
说明
这些宏用于创建和访问不属于套接字有效负载的控制消息(也称为辅助数据)。此控制信息可能包括接收数据包的接口,各种很少使用的头字段,扩展的错误描述,一组文件描述符或UNIX凭据。例如,控制消息可用于发送其他报头字段,例如IP选项。通过调用sendmsg(2)发送辅助数据,并通过调用recvmsg(2)接收辅助数据。有关更多信息,请参见其手册页。
辅助数据是带有附加数据的一系列cmsghdr结构。有关可用的控制消息类型,请参见特定的协议手册页。可以使用/ proc / sys / net / core / optmem_max设置每个套接字允许的最大辅助缓冲区大小;参见套接字(7)。
cmsghdr结构定义如下:
struct cmsghdr { size_t cmsg_len; /* Data byte count, including header (type is socklen_t in POSIX) */ int cmsg_level; /* Originating protocol */ int cmsg_type; /* Protocol-specific type */ /* followed by unsigned char cmsg_data[]; */ };
cmsghdr结构的序列绝不能直接访问。而是,仅使用以下宏:
- *
- CMSG_FIRSTHDR()返回一个指针,该指针指向与传递的msghdr关联的辅助数据缓冲区中的第一个cmsghdr。如果缓冲区中没有足够的空间可容纳cmsghdr,则返回NULL。
- *
- CMSG_NXTHDR()返回传递的cmsghdr之后的下一个有效cmsghdr。当缓冲区中没有足够的空间时,它将返回NULL。
- 初始化将包含一系列cmsghdr结构的缓冲区时(例如,将通过sendmsg(2)发送),该缓冲区应首先初始化为零以确保CMSG_NXTHDR()的正确操作。
- *
- 给定长度,CMSG_ALIGN()将返回它,包括所需的对齐方式。这是一个常量表达式。
- *
- CMSG_SPACE()返回带有已传递数据长度的有效负载的辅助元素的字节数。这是一个常量表达式。
- *
- CMSG_DATA()返回一个指向cmsghdr的数据部分的指针。返回的指针不能被假定为适当对齐以访问任意有效载荷数据类型。应用程序不应将其强制转换为与有效负载匹配的指针类型,而应使用memcpy(3)将数据复制到适当声明的对象或从适当声明的对象复制数据。
- *
- CMSG_LEN()返回值,该值将存储在cmsghdr结构的cmsg_len成员中,同时考虑到任何必要的对齐方式。它以数据长度为参数。这是一个常量表达式。
若要创建辅助数据,请首先使用控制消息缓冲区的长度初始化msghdr的msg_controllen成员。使用msghdr上的CMSG_FIRSTHDR()获取第一个控制消息,并使用CMSG_NXTHDR()获取所有后续消息。在每个控制消息中,使用CMSG_DATA()初始化CMSG_LEN(使用CMSG_LEN()),其他cmsghdr标头字段和数据部分。最后,应将msghdr的msg_controllen字段设置为缓冲区中所有控制消息的长度的CMSG_SPACE()的总和。有关msghdr的更多信息,请参见recvmsg(2)。
遵循规范
此辅助数据模型符合POSIX.1g草案4.4BSD-Lite,RFC2292和SUSv2中描述的IPv6高级API。在POSIX.1-2008中指定了CMSG_FIRSTHDR(),CMSG_NXTHDR()和CMSG_DATA()。 CMSG_SPACE()和CMSG_LEN()将包含在下一个POSIX版本中(问题8)。
CMSG_ALIGN()是Linux扩展。
备注
为了便于移植,应仅使用此处描述的宏访问辅助数据。 CMSG_ALIGN()是Linux扩展,不应在可移植程序中使用。
在Linux中,CMSG_LEN(),CMSG_DATA()和CMSG_ALIGN()是常量表达式(假设它们的参数为常量),这意味着这些值可用于声明全局变量的大小。但是,这可能不是便携式的。
示例
此代码在收到的辅助缓冲区中查找IP_TTL选项:
struct msghdr msgh; struct cmsghdr *cmsg; int received_ttl; /* Receive auxiliary data in msgh */ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) { memcpy(&receive_ttl, CMSG_DATA(cmsg), sizeof(int)); break; } } if (cmsg == NULL) { /* Error: IP_TTL not enabled or small buffer or I/O error */ }
下面的代码使用SCM_RIGHTS在UNIX域套接字上传递文件描述符数组:
struct msghdr msg = { 0 }; struct cmsghdr *cmsg; int myfds[NUM_FD]; /* Contains the file descriptors to pass */ char iobuf[1]; struct iovec io = { .iov_base = iobuf, .iov_len = sizeof(iobuf) }; 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; msg.msg_iov = &io; msg.msg_iovlen = 1; msg.msg_control = u.buf; msg.msg_controllen = sizeof(u.buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD); memcpy(CMSG_DATA(cmsg), myfds, NUM_FD * sizeof(int));
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。