【问题标题】:Fork before or after accepting connections?在接受连接之前或之后分叉?
【发布时间】:2009-10-14 20:28:35
【问题描述】:

下面的sn-p代码创建了4个进程,都共享同一个监听socket。

这样做有什么危险吗?在接受连接后,我是否应该以传统方式始终有一个侦听进程和分叉?

for (p = 0; p < 3; p++) {
  pid = fork();
  if (pid == 0) break;
}
while (1) { 
  unsigned int clientlen = sizeof(echoclient);
  /* Wait for client connection */
  if ((clientsock = 
       accept(serversock, (struct sockaddr *) &echoclient,
              &clientlen)) < 0) { 
    die("Failed to accept client connection");
  } 
  fprintf(stdout, "Process No. %d - Client connected: %s\n",
                  p,
                  inet_ntoa(echoclient.sin_addr));
  handle_client(clientsock);
}

(我知道在接受后分叉允许程序为每个连接创建一个进程。我正在玩原始线程和各种异步的东西,所以我只是在考虑每个核心有一个进程。)

【问题讨论】:

    标签: c linux unix networking


    【解决方案1】:

    无论哪种方式都可以。

    正如您所注意到的,在接受后分叉是每个客户端/连接一个孩子。在接受之前(但在侦听之后)分叉通常称为预分叉。每个孩子都等待接受,任何孩子获得传入的连接都会处理它。只要接受是由(我认为)任何现代 unix 所做的内核完成的,这是安全的。如果没有,您必须在接受周围放置某种 IPC(互斥锁等)锁。预分叉的优点是您不需要为每个连接花费分叉,因为您已经有一个现有的池。

    【讨论】:

    • 我虽然在 TCP 层中执行接受 tcp 连接(又名树方式句柄抖动)是内核的职责。我确信这里不需要任何 IPC。 SO上的人知道它在哪里吗?
    • 根据 Stevens 的说法,BSD 派生的内核总是这样做的。一些较旧的 SysV 系统在库中实现了接受,并且需要锁定。有人怀疑有人在运行这么旧的生产操作系统,但我想你永远不知道。
    • 如果我们使用 pre-fork,我们在 Linux 上不需要 setsockopt(server_fd, REUSEPORT),对吧?@Duck
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多