/* * 用来测试lighttpd的一些模型。 */
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> #include <errno.h>
#define NUM 5
static volatile sig_atomic_t srv_shutdown = 0; static volatile sig_atomic_t graceful_shutdown = 0; static volatile sig_atomic_t handle_sig_alarm = 1; static volatile sig_atomic_t handle_sig_hup = 0; static volatile sig_atomic_t forwarded_sig_hup = 0;
static void signal_handler(int sig) { switch (sig) { case SIGTERM: srv_shutdown = 1; break; case SIGINT: if (graceful_shutdown) srv_shutdown = 1; else graceful_shutdown = 1; break; case SIGALRM: handle_sig_alarm = 1; break; case SIGHUP: handle_sig_hup = 1; break; case SIGCHLD: break; } }
/* * 该模型是lighttpd的主进程模型。 * * 该模型的主要优点是: * 1)生成一个进程池来为客户端服务 * 2) 若进程池中的某个进程死掉,它会回收该子进程的资源并且继续生成一个新的子进程 * 3) 用进程池来作为服务器模型,最大的好处是,不用每次来一个客户端就重新生成一个子进程为之服务 * 4) 而是有子进程等待在这里,客户端一来,就可以得到响应,该模型是一个很好的模型,可用于对每个客户端进行一样的服务流程的服务器端。 * */
int main(int argc, char *argv[]) { int num_childs = NUM; int child;
/* ignore the SIGPIPE from sendfile() */ signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGALRM, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGINT, signal_handler); if (num_childs > 0) { child = 0; /* * 不是child,而且也没有被关闭,则进入while循环中 */ while (!child && !srv_shutdown && !graceful_shutdown) { if (num_childs > 0) { /* 还可以继续生成子进程 */ fprintf(stderr, "fork child now ...\n"); switch(fork()) { case -1: return -1; case 0: // child
child = 1; break; default: // parent
num_childs--; break; } } else { int status;
// 若有子进程退出,主程序在阻塞在这里回收资源
// 并把num_childs加1,回到循环再生成新的子进程,
// 这样就可以始终保持有NUM个子进程在运行。
fprintf(stderr, "all child ok! waiting child exit. \n"); if (-1 != wait(&status)) { num_childs++; } else { //wait error
switch (errno) { case EINTR: kill(0, SIGHUP); break; default : break; } } } } /* this is parent exit point */ if (!child) { if (graceful_shutdown) kill(0, SIGINT); return 0; } }
/* * 这里由子进程开始我们的工作 */ fprintf(stderr, "ppid = %d, pid = %d, num_child=[%d]\n", getppid(), getpid(), num_childs); if (num_childs == 2) { fprintf(stderr, "I 2 (pid=[%ld]) start work now ...\n", getpid()); sleep(2); } if (num_childs == 3) { fprintf(stderr, "I 3 (pid=[%ld]) start work now ...\n", getpid()); sleep(4); } if (num_childs == 4) { fprintf(stderr, "I 4 (pid=[%ld]) start work now ...\n", getpid()); sleep(8); } if (num_childs == 1) { fprintf(stderr, "I 1 (pid=[%ld]) start work now ...\n", getpid()); sleep(12); }
exit(0); }
|