当前位置: 技术问答>linux和unix
Linux下进程池实现
来源: 互联网 发布时间:2017-01-17
本文导语: 各位高手: 我现在接手一项工作:用c/c++写一个进程池,要求: 1 客户端只有一个,但是却在不停的发报文,所以服务器端与客户端建立socket长联接,(即服务端只accept客户端联接请求一次,之后就在这个...
各位高手:
我现在接手一项工作:用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 (;;)
我现在接手一项工作:用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 (;;)
|
进程池还没用玩过,下面说说我的想法:
先起100个工作进程,另起一个管理进程,
初始管理进程启动,然后创建100个工作进程,所有工作进程pend在信号SIGUSR1上,管理进程维护一个数据结构记录每个进程都是空闲的。
下面开始工作,
来了一个请求,要传到工作进程去处理,那么就必须使用进程间通讯,比如消息队列,把请求写到一个全局的消息队列里去,管理进程找到一个空闲进程的PID,改这个进程状态的忙,然后发送一个信号如SIGUSR1到工作进程, 工作进程pend在SIGUSR1上,当工作进程收到SIGUSR1后从消息队列里读出请求进行处理,处理完成后发送一个信号如SIGUSR2通知自己已经处理完了,然后继续pend在SIGUSR1上,管理进程收到信号SIGUSR2后再把这个工作进程置为空闲,供以后使用。
以上是我的想法,应该跟标准备的进程池技术一样。如果楼主还是觉得代码来提快,我建议还是先把基础打好,就像一个人在成为作家之前必须先学会写字一样。
先起100个工作进程,另起一个管理进程,
初始管理进程启动,然后创建100个工作进程,所有工作进程pend在信号SIGUSR1上,管理进程维护一个数据结构记录每个进程都是空闲的。
下面开始工作,
来了一个请求,要传到工作进程去处理,那么就必须使用进程间通讯,比如消息队列,把请求写到一个全局的消息队列里去,管理进程找到一个空闲进程的PID,改这个进程状态的忙,然后发送一个信号如SIGUSR1到工作进程, 工作进程pend在SIGUSR1上,当工作进程收到SIGUSR1后从消息队列里读出请求进行处理,处理完成后发送一个信号如SIGUSR2通知自己已经处理完了,然后继续pend在SIGUSR1上,管理进程收到信号SIGUSR2后再把这个工作进程置为空闲,供以后使用。
以上是我的想法,应该跟标准备的进程池技术一样。如果楼主还是觉得代码来提快,我建议还是先把基础打好,就像一个人在成为作家之前必须先学会写字一样。
|
你这有个问题, SIGUSR2 发往 父进程组时,可能父进程已经在SIGUSR2处理函数里。 而Linux不保证信号排队,所以。。。 不够完善。。。
|
如果是进程池,首先要考虑的就是报文传递的方式了,用哪种IPC好.
一个用户,那也是一个read,这么看来,共享内存是一种好的IPC.
那么,这种工作方式就是:
先启动进程池,2就开始工作了.之后循环处理1.
1.收取报文---->报文放入共享内存---->在管道里写上内存指针
2.进程池就是从管道里读指针,读到后,就处理.
lighttpd就是进程池模型吧,很快的.
当然,线程池也不错,只是楼上某位推荐的是boost实现的线程池,你不想装一个boost吧...
(不过公司让用,就用吧,也不错. )
我写过linux下的异步IO和线程池. 不依赖3方库的.
其实,你这个问题,用异步IO加线程池,才是最佳的方案.
现在工作忙,下周准备写一个进程池.
一个用户,那也是一个read,这么看来,共享内存是一种好的IPC.
那么,这种工作方式就是:
先启动进程池,2就开始工作了.之后循环处理1.
1.收取报文---->报文放入共享内存---->在管道里写上内存指针
2.进程池就是从管道里读指针,读到后,就处理.
lighttpd就是进程池模型吧,很快的.
当然,线程池也不错,只是楼上某位推荐的是boost实现的线程池,你不想装一个boost吧...
(不过公司让用,就用吧,也不错. )
我写过linux下的异步IO和线程池. 不依赖3方库的.
其实,你这个问题,用异步IO加线程池,才是最佳的方案.
现在工作忙,下周准备写一个进程池.