sendmmsg返回-1(无缓冲区可用),memset为何解决?结构体成员是否为诱因?
问题解答
首先直接给结论:问题确实出在未初始化的msg_control和msg_controllen成员上,msg_flags正如手册所说不会影响发送过程。下面详细拆解原因:
为什么未初始化的
struct mmsghdr会导致ENOBUFS错误当你声明一个局部的
struct mmsghdr变量却不初始化时,它的所有成员都会保留栈内存里的随机垃圾值:- 如果
msg_controllen被垃圾值设为一个非零的数值(甚至是很大的数),内核会认为你打算发送辅助控制数据(比如IP选项、套接字权限这类信息)。 - 但此时
msg_control大概率是一个野指针,或者指向的内存根本不是你准备好的有效缓冲区。内核在尝试处理这些“虚假”的控制数据时,要么无法找到合法的缓冲区,要么尝试为这个异常大的msg_controllen分配内存失败,最终就会返回ENOBUFS(也就是你看到的“no buffer space available”)错误。
- 如果
为什么
memset能解决问题memset(&Msgs, 0, sizeof(struct mmsghdr))会把整个结构体的所有成员都清零:- 这会将
msg_controllen设为0,内核看到这个值就知道你没有要发送的辅助控制数据,会直接忽略msg_control字段,不会去执行任何控制数据的处理逻辑,自然就不会触发之前的错误了。
- 这会将
关于
msg_flags的补充正如你查阅的手册所述,
sendmmsg()在发送消息时会完全忽略mmsghdr中的msg_flags字段——这个字段的作用是在接收消息(比如recvmsg/recvmmsg)时,返回内核处理消息时的标志状态,所以它确实不是导致你这次问题的原因。
内容的提问来源于stack exchange,提问作者imoc
相关产品推荐
相关产品推荐

