父和子代之间的文件描述符共享

在Unixnetworking编程中,有一个Pre-forked服务器的例子,它使用Unix域pipe道上的消息传递来指示subprocess处理一个传入的连接:

for ( ; ; ) { rset = masterset; if (navail <= 0) FD_CLR(listenfd, &rset); /* turn off if no available children */ nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL); /* 4check for new connections */ if (FD_ISSET(listenfd, &rset)) { clilen = addrlen; connfd = Accept(listenfd, cliaddr, &clilen); for (i = 0; i < nchildren; i++) if (cptr[i].child_status == 0) break; /* available */ if (i == nchildren) err_quit("no available children"); cptr[i].child_status = 1; /* mark child as busy */ cptr[i].child_count++; navail--; n = Write_fd(cptr[i].child_pipefd, "", 1, connfd); Close(connfd); if (--nsel == 0) continue; /* all done with select() results */ } 

如您所见,父级将套接字的文件描述符编号写入pipe道,然后调用closures文件描述符。 当preforked的孩子完成sockets,他们也打电话closures描述符。 扔我一个循环的东西是,因为这些孩子preforked我会认为只有文件描述符存在于儿童分叉时将共享。 但是,如果这是真的,那么这个例子将会失败,但它的工作。

有人可以告诉一下, 在fork最终与subprocess共享之后,父进程创build的文件描述符是如何的?

Solutions Collecting From Web of "父和子代之间的文件描述符共享"

看看Write_fd的实现。 它使用类似的东西

 union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; 

也就是说,发送一个类型为SCM_RIGHTS的控制消息是unixes可以共享一个文件描述符和一个未经处理的进程的一种方法。

您可以使用Unix套接字中的FD传递机制将(大部分)任意文件描述符发送到可能不相关的进程。

这通常是一个很少使用的机制,而且很难得到正确的结果 – 两个过程都需要合作。

大多数prefork服务器不这样做,相反,他们有共享侦听套接字上的子进程调用accept(),并以这种方式创建自己的连接套接字。 其他进程不能看到这个连接的套接字,只有一个副本,所以当孩子关闭它,它已经消失了。

一个缺点是,在调用accept之前,进程无法知道客户端要请求什么,所以你不能在不同的孩子中处理不同类型的请求。一旦一个孩子接受(),另一个孩子不能。