Linux/UNIX系统上常见的服务器套接字模式是在套接字上侦听,接受连接,然后使用fork()
来处理连接。在fork()后关闭监听套接字()
所以,看起来你在accept()
和fork()
之后,一旦你进入了子进程,你就会继承父进程的监听文件描述符。我已经读过,在这一点上,您需要关闭子进程内的侦听套接字文件描述符。
我的问题是,为什么?这是否简单地减少了监听套接字的引用计数?还是这样,子进程本身不会被OS用作路由传入连接的候选者?如果是后者,我有点困惑,原因有两个:
(A)告诉操作系统某个进程是否可以接受某个文件描述符上的连接?这个过程叫做accept()
是事实吗?或者这个过程叫做listen()
? (B)如果这个过程叫做listen()
,那么我们在这里没有竞争条件吗?如果这种情况发生什么:
- 父进程监听套接字S.
- 传入连接转到父进程。
- 父进程叉一个孩子,孩子有插座S
- 的副本之前孩子能够调用
close(S)
,一个秒传入连接进入子进程。 - 子进程永远不会调用
accept()
(因为它不应该),所以进入的连接被丢弃
什么防止上述情况的发生?更一般地说,为什么一个子进程关闭监听套接字?
这不回答这个问题。提问者想知道为什么有必要关闭所有文件描述符,以及如果不这样做会发生什么。 – dbush