创建管理进程池
概述:
在编写
socket server
程序时,我们用到进程池的概念,最后我们选用
ACE
作为进程池框架。对于进程池的原理有一定理解后,决定自己实现一个进程池的创建及管理程序。
跟最简单的资源管理一样,进程池技术应该至少包含两部分,管理进程,资源进程。
资源进程,预先创建好的资源进程,管理进程会把工作分发到空闲进程来处理。
管理进程,管理进程负责创建资源进程,把工作交给空闲资源进程处理。管理进程管理资源进程需要实现的功能有:创建资源进程,维护资源进程表,和资源进程通信,唤醒空闲的资源进程开始工作。
本例子用的技术点有,进程,管道,信号。在实际应用中,还会用到消息队列,共享内存等技术。
创建资源进程。
流程描述:
创建管道。
创建子进程。
子进程通过管道将进程
ID
传给主进程。
子进程挂起。
主进程收到子进程传来的信息后,将信息作为函数返回值,返回。
//
主进程返回
0
,子进程返回
1
//cChildPid
,被创建的资源进程的进程
ID
int create_process(char** cChildPid)
{
int i = 0;
int iChildPid = 0;
int iWaitPid = 0;
int m_pipe[2];
//
创建管道
pipe(m_pipe);
//
创建子进程
iChildPid = fork();
if(iChildPid < 0)
{
printf("create process error\n");
exit(-1);
}
if(iChildPid == 0) //
子进程
{
char buf[6];
sprintf(buf, "%ld", getpid());
write(m_pipe[1], buf, 6); //
通过管道将进程
ID
传递给主进程
wait_p(); //
子进程挂起
write_log();
return 1;
}
else //
主进程
{
char buf[6];
read(m_pipe[0], buf, 6); //
读取子进程传送过来的信息
strcpy(cChildPid, buf);
}
return 0;
}
设置信号SIGUSR2动作
使用用户自定义信号
SIGUSR2
作为控制信号。
信号动作函数
void catch_sigusr_2(int signo)
{
printf("save sigusr 2\n");
}
设置信号
void set_sig_action(void)
{
sigset_t sigmask, sigold;
struct sigaction act;
act.sa_handler = catch_sigusr_2;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGUSR2, &act, NULL);
}
挂起资源进程等待事件到来唤醒
void wait_p()
{
sigset_t sigmask, sigold;
set_sig_action();
sigfillset(&sigmask); //
对信号集进行初始化
sigdelset(&sigmask,SIGUSR2); //
将信号
SIGUSR1
从信号集中删除
sigprocmask(SIG_SETMASK, &sigmask, &sigold); //
将指定信号集设置为被阻塞的信号,并将修改之前的信号集保存到
sigold
中
sigsuspend(&sigmask); //
设置进程只能接收
SIGUSR1
信号,并且挂起
sigprocmask(SIG_SETMASK, &sigold, NULL); //
将信号集还原
}
唤醒资源进程
void tell_p(pid_t pid)
{
printf("pid:%d\n", pid);
kill(pid,SIGUSR2); //
向指定进程发送
SIGUSR1
信号
printf("tell_p\n");
}
主控制进程
创建
4
个资源进程,创建完毕后,模拟事件到达,唤醒资源进程进行事件处理。
创建的子进程号保存在一个
2
维数组中。
int main(int argc, char** argv)
{
char cChildPid[4][10];
char sChildPid[10];
int r;
int i;
long lChildPid;
printf("test process pool\n");
memset(cChildPid, 0x00, sizeof(cChildPid));
for(i = 0; i < 4; i++)
{
memset(sChildPid, 0x00, sizeof(sChildPid));
r = create_process((char **)&sChildPid);
if(r == 0)
{
strcpy(cChildPid[i], sChildPid);
printf("cChildPid[%d]:%s\n", i, cChildPid[i]);
}
else
return 0;
}
for(i = 0; i < 4; i++)
{
lChildPid = atol(cChildPid[i]);
printf("i:%d:lChildPid:%d\n", i, lChildPid);
tell_p(lChildPid);
}
wait(NULL);
return 0;
}