Linux下进程池实现

响马0709 2009-02-06 04:19:21
各位高手:
我现在接手一项工作:用c/c++写一个进程池,要求:
1 客户端只有一个,但是却在不停的发报文,所以服务器端与客户端建立socket长联接,(即服务端只accept客户端联接请求一次,之后就在这个套结字上循环接收,处理客户端的报文,每次收到一个报文,就起一个子进程处理这个报文,因为一秒钟可能收到几百条报文,而处理每条报文需要一段时间,如果不设进程池,就有可能积累过多进程,尽管可以在每个子进程处理完后就结束掉,来了新的报文就起新进程,但是有一种说法认为:每天假设有100万报文,就需要起100万次进程,假设Linux系统关掉每个子进程都回产生一些垃圾,就会导致形系统崩溃,我虽然认为这种看法不必要,因为Linux作为一个成熟的系统,结束一个子进程(exit),怎么会产生垃圾?但不得不按循环利用子进程池方案作:起固定个数子进程后,每个处理报文的子进程 处理完后不结束,而是通知(怎样通知?管道)管理进程自己空闲,等待调用,来了新的报文,由某一管理进程查询哪个子进程空闲,使用之,请问上述循环利用固定数目的进程池怎样实现?
查了包括本论坛在内的好多资料,都是只讲方法,没有代码,给我的做项目时间有限,能否请做过的贴代码上来?多谢!
我已有的通讯代码如下:(没有进程池代码)
recvFrontSock = accept(listenFrontSock, (__SOCKADDR_ARG )&peer , (socklen_t*)&addrlen2);
for (;;)// 循环接收客户端发来的终端报文
{
read_bytes = read(recvFrontSock, buff, received);
if (fork() == 0)// 每次收到客户端发来的报文就起一个子进程处理
{
process(socketToCore, semid, shm_id, shm_field8583id, pid, buff);
// 处理完后如何通知管理进程自己空闲?等待(睡眠等待??)重新调用

}// if (fork() == 0)
}//for (;;)


...全文
3816 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianyapiaozi 2011-11-15
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 guosha 的回复:]
如需要阅读该回复,请登录或注册CSDN!
[/Quote]
怎么看不了
newyibo 2011-05-12
  • 打赏
  • 举报
回复
大家好,我刚学到进程和线程,对进程池很感兴趣。问了一些人,也自己做了一些实验。在这里我有个问题,为什么要用信号来唤醒资源进程呢?为什么不让空闲的资源进程等待消息队列的消息(第一个消息),管理进程只负责给消息队列发消息,资源进程只要有消息就接过来工作。这样不是省了管理进程对空闲进程的检测和分配任务等几个步骤,一切都是自动完成,互不干扰,效率不是更高一点吗?
这是我做的一个网络进程池服务器程序的实验,只是不知道这样在具体的应用上有什么问题,希望能和大家进行交流,谢谢!
zhuxueling 2009-02-15
  • 打赏
  • 举报
回复
如果是进程池,首先要考虑的就是报文传递的方式了,用哪种IPC好.
一个用户,那也是一个read,这么看来,共享内存是一种好的IPC.

那么,这种工作方式就是:

先启动进程池,2就开始工作了.之后循环处理1.

1.收取报文---->报文放入共享内存---->在管道里写上内存指针
2.进程池就是从管道里读指针,读到后,就处理.


lighttpd就是进程池模型吧,很快的.


当然,线程池也不错,只是楼上某位推荐的是boost实现的线程池,你不想装一个boost吧...
(不过公司让用,就用吧,也不错. )

我写过linux下的异步IO和线程池. 不依赖3方库的.
其实,你这个问题,用异步IO加线程池,才是最佳的方案.
现在工作忙,下周准备写一个进程池.


threeleafzerg007 2009-02-15
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zhuxueling 的回复:]
如果是进程池,首先要考虑的就是报文传递的方式了,用哪种IPC好.
一个用户,那也是一个read,这么看来,共享内存是一种好的IPC.

那么,这种工作方式就是:

先启动进程池,2就开始工作了.之后循环处理1.

1.收取报文---->报文放入共享内存---->在管道里写上内存指针
2.进程池就是从管道里读指针,读到后,就处理.


lighttpd就是进程池模型吧,很快的.


当然,线程池也不错,只是楼上某位推荐的是boost实现的线程池,你不想装一…
[/Quote]


lighttpd 是线程池模型,httpd才是进程池模式
以前做过 apache 和 lighttpd性能比较工作 从网络性能看, lighttpd 不如 apache
快乐田伯光 2009-02-15
  • 打赏
  • 举报
回复
你说得没有错,我这里也只是一个意思,举个进程池的进程工作完成后如何通知管理进程,这里的实现方式是很多的,你说的问题直接用实时信号就可以解决,你也可以用其它的IPC。反正目的就是一个,通知管理进程我任务已经处理完了,可以进行下一次的工作了,方法有很多!

[Quote=引用 14 楼 threeleafzerg007 的回复:]
引用 4 楼 guosha 的回复:
进程池还没用玩过,下面说说我的想法:
先起100个工作进程,另起一个管理进程,
初始管理进程启动,然后创建100个工作进程,所有工作进程pend在信号SIGUSR1上,管理进程维护一个数据结构记录每个进程都是空闲的。
下面开始工作,
来了一个请求,要传到工作进程去处理,那么就必须使用进程间通讯,比如消息队列,把请求写到一个全局的消息队列里去,管理进程找到一个空闲进程的PID,改这个进程状态…
[/Quote]
threeleafzerg007 2009-02-14
  • 打赏
  • 举报
回复
最好的还是用一些比较成熟的 线程池库 或者 ACE库
threeleafzerg007 2009-02-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 guosha 的回复:]
进程池还没用玩过,下面说说我的想法:
先起100个工作进程,另起一个管理进程,
初始管理进程启动,然后创建100个工作进程,所有工作进程pend在信号SIGUSR1上,管理进程维护一个数据结构记录每个进程都是空闲的。
下面开始工作,
来了一个请求,要传到工作进程去处理,那么就必须使用进程间通讯,比如消息队列,把请求写到一个全局的消息队列里去,管理进程找到一个空闲进程的PID,改这个进程状态的忙,然后发送一个信号如SIGUS…
[/Quote]

你这有个问题, SIGUSR2 发往 父进程组时,可能父进程已经在SIGUSR2处理函数里。 而Linux不保证信号排队,所以。。。 不够完善。。。
Oo_Oo_ 2009-02-14
  • 打赏
  • 举报
回复
3楼的是最佳的方法!
060 2009-02-14
  • 打赏
  • 举报
回复
可以参考 一些大型的HTTP网站的做法。 HTTP协议的特点是,客户端请求、服务器端响应、关闭连接. 如果用多进程实现的话,也需要fork很多子进程。

dai_weitao 2009-02-10
  • 打赏
  • 举报
回复
结构如下:

--阻塞函数(主进程, 含recv)
|
|
----调度函数(主进程, 含查空闲和分派功能)
|
|
-------若干子进程(执行报文)
cnhome 2009-02-08
  • 打赏
  • 举报
回复
为什么不用ACE的框架做呢
快乐田伯光 2009-02-06
  • 打赏
  • 举报
回复
会,异步的嘛,信号处理完后,继续阻塞在recv上.
不过你最还去看看别的进程池框架, 我以前也末接触过进程池,都是猜的. 不过我想大致原理应该是这样的.
响马0709 2009-02-06
  • 打赏
  • 举报
回复
谢谢guosha的热心回答
接收进程就可以是管理进程,那么当工作进程处理完报文后发送一个信号如SIGUSR2到接收/管理的进程时,如果此时恰好接收进程阻塞在recv函数上等待接收报文,还会进到接收/管理的进程的信号的处理函数里把相应进程设为空闲状态吗?
快乐田伯光 2009-02-06
  • 打赏
  • 举报
回复
你需要的是理解意思, 对你说的第一个问题, 接收进程就可以是管理进程,接收进程收到一个请求包以后就找空闲进程处理. 第二个问题,不知你说的冲突是由哪里产生的.管理进程提交请求到工作进程处理前先标识该进程为已不空闲.回收工作完成的工作进程是异步的,只需要发送一个信号到管理进程,管理进程在信号的处理函数里把相应进程设为空闲状态.

[Quote=引用 5 楼 xiang_ma 的回复:]
谢谢所有回答的高人!!!

guosha, 有个问题:注意到我的接收客户端报文的recv也是一个进程,那你所说的管理进程和接收报文的进程怎么通信?即:接收进程收到报文后,先把报文写到全局消息对列里,再通知管理进程找空闲进程ID?(用什么方式通知管理进程?)当管理进程正在找空闲在进程时,如果有某工作进程处理完成后发送一个信号如SIGUSR2通知自己已经处理完了,会有什么结果?(即会不会冲突?)

sorry,有些问题可能很…
[/Quote]
响马0709 2009-02-06
  • 打赏
  • 举报
回复
同理:当管理进程正在找空闲在进程时,和接收进程通知它可以找空闲进程的某种通信方式会不会冲突?
响马0709 2009-02-06
  • 打赏
  • 举报
回复
谢谢所有回答的高人!!!

guosha, 有个问题:注意到我的接收客户端报文的recv也是一个进程,那你所说的管理进程和接收报文的进程怎么通信?即:接收进程收到报文后,先把报文写到全局消息对列里,再通知管理进程找空闲进程ID?(用什么方式通知管理进程?)当管理进程正在找空闲在进程时,如果有某工作进程处理完成后发送一个信号如SIGUSR2通知自己已经处理完了,会有什么结果?(即会不会冲突?)

sorry,有些问题可能很弱!
快乐田伯光 2009-02-06
  • 打赏
  • 举报
回复
进程池还没用玩过,下面说说我的想法:
先起100个工作进程,另起一个管理进程,
初始管理进程启动,然后创建100个工作进程,所有工作进程pend在信号SIGUSR1上,管理进程维护一个数据结构记录每个进程都是空闲的。
下面开始工作,
来了一个请求,要传到工作进程去处理,那么就必须使用进程间通讯,比如消息队列,把请求写到一个全局的消息队列里去,管理进程找到一个空闲进程的PID,改这个进程状态的忙,然后发送一个信号如SIGUSR1到工作进程, 工作进程pend在SIGUSR1上,当工作进程收到SIGUSR1后从消息队列里读出请求进行处理,处理完成后发送一个信号如SIGUSR2通知自己已经处理完了,然后继续pend在SIGUSR1上,管理进程收到信号SIGUSR2后再把这个工作进程置为空闲,供以后使用。

以上是我的想法,应该跟标准备的进程池技术一样。如果楼主还是觉得代码来提快,我建议还是先把基础打好,就像一个人在成为作家之前必须先学会写字一样。
pottichu 2009-02-06
  • 打赏
  • 举报
回复

为什么不用线程池呢?
另外,你并不需要每accept一个客户端就建立一个进程啊,另外使用进程池需要考虑进程间数据共享和同步等问题,也很麻烦。
线程就相对要方便很多。
举个例子:

你可以建立一个任务队列,将新accept的socket 投入到队列A中去。
然后线程池A里的线程去队列A里取socket,收发数据, 将需要处理的数据投入到队列B中去。
接着线程池B里的线程去队列B中取出数据进行处理。

作为通信服务器,这样的处理效率比使用进程去处理是要高很多的。
linaxing 2009-02-06
  • 打赏
  • 举报
回复
改用线程池吧,下面有现成的线程池的实现。
http://threadpool.sourceforge.net/
响马0709 2009-02-06
  • 打赏
  • 举报
回复
查了包括本论坛在内的好多资料,都是只讲方法,没有代码,给我的做项目的时间有限,能否请做过的贴代码上来?多谢!

23,124

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧