共有メモリを介して、あるプロセスから別のプロセスにソケット (またはその他のファイル記述子) を送信することはできません。ファイル記述子は小さな整数です。この整数を共有メモリに配置して別のプロセスからアクセスしても、同じ整数が自動的に他のプロセスの観点から有効なファイル記述子になるわけではありません。
あるプロセスから別のプロセスにファイル記述子を送信する正しい方法は、2 つのプロセス間の既存のソケット通信チャネルSCM_RIGHTS
を介して補助データとして送信することです。sendmsg()
まず、 のsocketpair()
前に とのコミュニケーション チャネルを作成しますfork()
。次に、親でソケット ペアの一方の端を閉じ、子でもう一方の端を閉じます。sendmsg()
このソケットの一方の端で親から受信しrecvmsg()
、もう一方の端を使用して子で受信できるようになりました。
でメッセージを送信すると、SCM_RIGHTS
次のようになります。
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
char buf[CMSG_SPACE(sizeof(int))];
char dummy[2];
memset(&m, 0, sizeof(m));
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = &buf;
memset(m.msg_control, 0, m.msg_controllen);
cm = CMSG_FIRSTHDR(&m);
cm->cmsg_level = SOL_SOCKET;
cm->cmsg_type = SCM_RIGHTS;
cm->cmsg_len = CMSG_LEN(sizeof(int));
*((int *)CMSG_DATA(cm)) = your_file_descriptor_to_send;
m.msg_iov = &iov;
m.msg_iovlen = 1;
iov.iov_base = dummy;
iov.iov_len = 1;
dummy[0] = 0; /* doesn't matter what data we send */
sendmsg(fd, &m, 0);
でメッセージを受信するとSCM_RIGHTS
、次のようになります。
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
struct dummy[100];
char buf[CMSG_SPACE(sizeof(int))];
ssize_t readlen;
int *fdlist;
iov.iov_base = dummy;
iov.iov_len = sizeof(dummy);
memset(&m, 0, sizeof(m));
m.msg_iov = &iov;
m.msg_iovlen = 1;
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = buf;
readlen = recvmsg(fd, &m, 0);
/* Do your error handling here in case recvmsg fails */
received_file_descriptor = -1; /* Default: none was received */
for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) {
nfds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
fdlist = (int *)CMSG_DATA(cm);
received_file_descriptor = *fdlist;
break;
}
}