为什么父进程中的select()会使子进程中的accept()无法使用?

时间:2012-04-13 14:05:30

标签: python linux sockets process

我有一个父进程,它创建了2个服务器套接字并在其上调用select()以等待新连接。当连接到达时,会在创建服务器套接字后向子进程(使用fork()创建)发送一条消息,以便共享它们。

在这个孩子中,在服务器套接字上调用accept()不起作用。我遇到了EAGAIN错误(非阻塞套接字)。而在主要过程中调用accept()可以很好地工作。

当然,我根本没有在主进程中调用accept(),我只是测试它是否有效,而且确实有效。

为什么我不能在父级accept()之后在子进程中调用select()

编辑:这里的目标是创建固定数量的工作人员(比方说8)来处理客户端连接,就像在prefork模型中一样。这些连接将是长连接,而不是HTTP。目标是对工人之间的连接进行负载平衡。

为此,我使用共享内存变量,该变量包含一个worker,当前连接的客户端数量。我想“询问”具有最少客户端的工作人员来处理新连接。

这就是为什么我在父进程中执行select(),然后向子进程发送消息,因为我想“选择”哪个进程将处理新连接。

服务器侦听多个套接字(一个用于ssl,一个用于ssl),这就是我在子进程中使用select()而不是直接accept()的原因,因为我不能{{1}在我的孩子工作者的多个插座上。

1 个答案:

答案 0 :(得分:3)

事实上,这个问题并不是我最初的想法。以下是我对工作进程之间的连接进行基本负载均衡所做的工作的概述。

  • 主进程(父进程)创建2个服务器套接字,bind()和listen()它们(例如有和没有ssl)
  • 我使用fork()创建了8个子进程,因此它们继承了父进程的套接字
  • 主进程在无限循环中运行select()
  • 当其中一个插槽可用时,它会通过管道向子节点发送消息。通过共享内存值确定子项,该内存值包含“子进程中”的当前客户端数。选择当前处理最少数量客户的流程。
  • 然后,这个子进程在服务器套接字上调用accept()(两者之间使用的套接字在管道中传递,因此子进程知道要调用哪个accept()

问题是我的父进程告诉孩子接受套接字并在之后立即重新进入循环,它再次运行select()。但是,如果孩子尚未接受套接字,则select()将再次返回,以获得相同的连接。这就是我收到EAGAIN错误的原因,实际上我调用accept()两次(或更多取决于速度 - 进程间竞争条件)!

解决方案是等待孩子回答管道上的内容,例如“嘿,我接受了连接,没关系!”,然后返回select()循环。

这完全没问题。 Python中的实现可用于好奇的:https://github.com/thibautd/Kiwi