Unix ドメイン ソケットと sendmsg/recvmsg を使用して 2 つのプロセス間で fd を送信するコードがあります。このコードは、Linux と Mac の両方で実行する必要があります (両方のプラットフォームで個別にコンパイルされます)。SOCK_DGRAM (データグラム) ソケットを使用しています。
コードで一度に 1 つの 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);
手がかりはありますか?前もって感謝します