lighttpd源码主程序架构分析及其应用

jackxiang 2010-12-1 10:38 | |


/*
* 用来测试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);
}

来源:http://blog.chinaunix.net/u/28197/showart_2401528.html

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/3807/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!

评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]