【问题标题】:Mac OS X: recvmsg returns EMSGSIZE when sending fd's via Unix domain datagram socketMac OS X:当通过 Unix 域数据报套接字发送 fd 时,recvmsg 返回 EMSGSIZE
【发布时间】:2013-06-20 14:13:13
【问题描述】:

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

我在代码中一次发送一个 fd。在 Mac 上,以这种方式成功发送几个 fd 后,recvmsg() 失败并显示 EMSGSIZE。根据 recvmsg 的联机帮助页,只有在 msg->msg_iovlen = 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);

有什么线索吗? 提前致谢

【问题讨论】:

    标签: linux macos sockets xnu


    【解决方案1】:

    你真的在使用你收到的 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      相关资源
      最近更新 更多