首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在多个进程之间共享套接字的accept() (基于Apache preforking)

在多个进程之间共享套接字的accept() (基于Apache preforking)
EN

Stack Overflow用户
提问于 2009-08-18 12:55:47
回答 1查看 5.8K关注 0票数 16

我正在编写一些模仿Apache的MPM prefork服务器的Python代码。与其说我是一名网络程序员,不如说我是一名应用程序程序员,而且我已经10年没有读过史蒂文斯的书了,所以我正在努力提高理解代码的速度。

我找到了对how Apache's prefork code works, by Sander Temme的简短描述。

通常以根用户身份运行的父进程绑定到套接字(通常是端口80或443)。它产生子代,这些子代继承套接字的打开文件描述符,并将uid和gid更改为非特权用户和组。子节点构造一个监听器文件描述符的轮询集(如果有多个监听器的话),并监视其上的活动。如果找到活动,子进程调用活动套接字上的accept()并处理连接。完成此操作后,它将返回到监视轮询集(或侦听器文件描述符)。

由于多个子进程处于活动状态,并且它们都继承了相同的套接字文件描述符,因此它们将监视相同的轮询集。接受互斥锁只允许单个子进程实际监视轮询集,一旦找到活动套接字,它将解锁互斥锁,以便下一个子进程可以开始监视轮询集。如果只有一个侦听器,则不使用接受互斥锁,且所有子级都将挂起接受()。

这是我看到的代码的工作方式,但我不理解一些事情。

1)“孩子”和“听众”有什么区别?我认为每个孩子都是一个监听器,这对于我正在查看的代码来说是正确的,但是在Temme的描述中可以有“一个监听器”和“孩子”。一个孩子什么时候会有多个监听器?

2) (与1相关)这是每进程互斥锁还是系统互斥锁?就此而言,为什么要有互斥锁呢?不接受(2)在所有监听器上执行自己的互斥?我的研究表明我确实需要一个互斥锁,而且互斥锁必须跨整个系统。(群集、信号量等)

Temme接着说:

子代在共享内存区(记分板)中记录他们上次处理请求的时间。父进程可能会杀死空闲子进程以满足MaxSpareServers的要求。如果空闲的子进程太少,父进程将生成子进程以满足MinSpareServers的要求。

3)这个实现有没有很好的参考代码(最好是用Python)?我找到了Perl的Net::Server::Prefork,它使用管道代替共享内存作为记分板。我发现了Randal Schwartz的一篇文章,它只做预分叉,而不做记分板。

pre-fork example from the Perl Cookbook没有任何关于select的锁定,Chris Siebenmann's Python example说它是基于Apache的,但它使用配对的套接字作为记分板,而不是共享内存,并将套接字用于控件,将给定子控件包含到‘a’‘ccept。这与Apache的描述一点也不匹配。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-10-18 22:32:48

对于(1),侦听器仅仅是对套接字的存在的引用,在套接字上接受连接。由于Apache可以同时接受多个套接字上的连接,例如80/443,因此存在多个监听套接字。到时候,每个子进程都需要监听所有这些套接字。因为一次只能在一个套接字上执行accept(),所以在它之前有轮询/选择,所以知道应该在哪个侦听器套接字上执行接受。

关于(2),它是一个全局或跨进程互斥。也就是说,锁定它的一个进程将阻止其他试图获取相同锁的进程。尽管accept()将在技术上序列化进程,但多个侦听器套接字的存在意味着您不能依赖它,因为您事先不知道在哪个套接字上执行accept。即使只有一个监听程序套接字,使用接受互斥锁的原因也是因为如果有大量的进程在处理请求,那么如果操作系统唤醒所有进程来查看哪个进程为它返回了accept(),那么这将是非常昂贵的。由于预派生模式下的Apache可能有100+进程,这可能会导致问题。

因此,如果您只有一个监听程序套接字,并且知道只有几个进程想要执行accept()调用,那么您可以取消跨进程接受互斥锁。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1293652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档