Mac OS X:当通过Unix域数据报套接字发送fd时,recvmsg返回EMSGSIZE

时间:2013-06-24 06:30:46

标签: linux macos sockets xnu

我有一段代码使用Unix域套接字和sendmsg / recvmsg在两个进程之间发送fd。此代码需要在Linux和Mac上运行(两个平台都单独编译)。我正在使用SOCK_DGRAM(数据报)套接字。

我在代码中一次发送一个fd。在Mac上,以这种方式成功发送了几个fd后,recvmsg()失败了EMSGSIZE。根据recvmsg的联机帮助页,只有当msg-> msg_iovlen< = 0或> = Mac上的2048常量时,才会发生这种情况。在我的代码中,我总是将msg_iovlen固定为1,我在发送器和接收器上验证了这一点,并且在recvmsg()故障之后立即读取了消息头。这个代码在Linux上运行良好。

从查看XNU内核源代码的另一种可能性是,接收器可能已经用完了fd,但是我在错误发生之前只发送了4或5个fd,因此应该有足够的fd。

如果我不发送fd并且只发送数据,则不会发生此错误。

以下是打包控制消息的代码:

// *obj is the fd, objSize is sizeof(*obj)
// cmsg was allocated earlier as a 512 byte buffer

cmsgLength = CMSG_LEN(objSize);

cmsgSpace = CMSG_SPACE(objSize);

cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = cmsgLength;

memcpy(CMSG_DATA(cmsg), obj, objSize);

msg->msg_control = cmsg;
msg->msg_controllen = cmsgSpace;

这是接收者:

msg = (struct msghdr *)pipe->msg;
iov = msg->msg_iov;
iov->iov_base = buf;
iov->iov_len = size;

// msg->msg_control was set earlier
msg->msg_controllen = 512;

return recvmsg(sockFd, msg, 0);

任何线索? 提前致谢

1 个答案:

答案 0 :(得分:0)

你真的在使用你收到的cmsg东西吗?我注意到你将msg_controllen设置为512.你有什么设置msg_flags?

您是否可以通过以下添加尝试同样的事情。

msg = (struct msghdr *)pipe->msg;

memset (msg, 0, sizeof(msghdr)); /* added this */

iov = msg->msg_iov;
iov->iov_base = buf;
iov->iov_len = size;

// msg->msg_control was set earlier
msg->msg_controllen = 512;

return recvmsg(sockFd, msg, 0);