簡體   English   中英

Mac OS X:通過Unix域數據報套接字發送FD時,recvmsg返回EMSGSIZE

[英]Mac OS X: recvmsg returns EMSGSIZE when sending fd's via Unix domain datagram socket

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

有什么線索嗎? 提前致謝

您實際上是在使用收到的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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM