2

我有一段代码使用 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);

有什么线索吗?提前致谢

4

1 回答 1

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);
于 2013-08-18T13:17:40.083 回答