创建管理进程池

创建管理进程池

概述:

       在编写 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;
}

你可能感兴趣的:(职场,创建,休闲,管理进程池)