lighttpd1.4.49 之二 wachter worker模型

1.函数执行过程

server.c----->main------->rc = server_main(srv, argc, argv);---->

概述

Lighttpd采用多进程网络服务模型。

进程分两种:监控进程watcher 和 工作进程 workers。

监控进程:fork工作进程并监视工作进程的数目,一旦有工作进程退出,监控进程立即fork新的工作进程。

工作进程:接收客户端请求并做出服务响应。

一般情况下,存在一个监控进程和多个工作进程。

max-worker值默认为0时,没有监控进程,只有一个工作进程。

关于初始化:Lighttpd很多地方内存申请都是采用calloc,malloc()和calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能。

主流程入口文件:server.c

2、如何转化为wachter和worker 转化代码

/* start watcher and workers */
    num_childs = srv->srvconf.max_worker;
/*存放最大的子进程的数目*/
    if (num_childs > 0) {
        pid_t pids[num_childs];
        pid_t pid;
        const int npids = num_childs;
        int child = 0;
/*child变量用于标记是否为子进程,0代表父进程,1代表子进程*/
        unsigned int timer = 0;
        for (int n = 0; n < npids; ++n) pids[n] = -1;
        while (!child && !srv_shutdown && !graceful_shutdown) {

/*子进程不可进入,srv_shutdown=1 或 graceful_shutdown=1时父进程跳出*/

/*重点注释,child=1表示子进程的child值为1而父进程中的child仍然为0,所以子进程不会再执行此循环进入下一段程序,但是主进程watcher仍然停留在此循环中*/
            if (num_childs > 0) {
                switch ((pid = fork())) {
/*创建子进程*/
                case -1:
                    return -1;
                case 0:
                    child = 1;/*重点注释,
子进程标记 child=1表示子进程的child值为1而父进程中的child仍然为0*/
                    alarm(0);
                    break;
                default:
                    num_childs--;
/*父进程*/
                    for (int n = 0; n < npids; ++n) {

                       /*    

  1. 在父进程中,fork返回新创建子进程的进程ID;
  2. 在子进程中,fork返回0;
  3. 如果出现错误,fork返回一个负值;

                      */
                        if (-1 == pids[n]) {
                            pids[n] = pid;
                            break;
                        }
                    }
                    break;
                }
            } else {
//子进程产生完毕
                int status;//保存子进程退出状态

                if (-1 != (pid = wait(&status))) {//阻塞等待子进程退出,收尸
                    srv->cur_ts = time(NULL);
                    if (plugins_call_handle_waitpid(srv, pid, status) != HANDLER_GO_ON) {
                        if (!timer) alarm((timer = 5));
                        continue;
                    }
                    switch (fdevent_reaped_logger_pipe(pid)) {
                      default: break;
                      case -1: if (!timer) alarm((timer = 5));
                           /* fall through */
                      case  1: continue;
                    }
                    /** 
                     * check if one of our workers went away
                     */
                    for (int n = 0; n < npids; ++n) {
                        if (pid == pids[n]) {
                            pids[n] = -1;
                            num_childs++;
//表示可以再产生新的子进程
                            break;
                        }
                    }
                } else {
                    switch (errno) {

                    case EINTR://发生中断
                        srv->cur_ts = time(NULL);
                        /**
                         * if we receive a SIGHUP we have to close our logs ourself as we don't 
                         * have the mainloop who can help us here
                         */
                        if (handle_sig_hup) {
                            handle_sig_hup = 0;

                            log_error_cycle(srv);//重新打开日志文件

                            /* forward SIGHUP to workers */
                            for (int n = 0; n < npids; ++n) {
                                if (pids[n] > 0) kill(pids[n], SIGHUP);
                            }
                        }
                        if (handle_sig_alarm) {
                            handle_sig_alarm = 0;
                            timer = 0;
                            plugins_call_handle_trigger(srv);
//通知组内所有进程
                            fdevent_restart_logger_pipes(srv->cur_ts);
                        }
                        break;
                    default:
                        break;
                    }
                }
            }
        }

        /**
         * for the parent this is the exit-point 
         */
        if (!child) { /*重点注释,child=1表示子进程的child值为1 而父进程中的child仍然为0,子进程不执行此程序,进入下一步*/
            /** 
//父进程的退出点,关闭所以工作进程,做一些清理工作(关闭日志,连接的网络资源,插件,内存等)。
             * kill all children too 
             */
            if (graceful_shutdown || graceful_restart) {
                /* flag to ignore one SIGINT if graceful_restart */
                if (graceful_restart) graceful_restart = 2;
                kill(0, SIGINT);
                server_graceful_state(srv);
            } else if (srv_shutdown) {
                kill(0, SIGTERM);
            }

            return 0;
        }

后面的程序下期分享,后面的程序都是worker进程在执行

3、如何转化为wachter和worker 伪代码

è¿éåå¾çæè¿°

4、如何转化为wachter和worker 流程图

 

5 Lighttpd工作进程处理模型

 

参考文档:Lighttpd源码分析_高群凯

下载地址:https://download.csdn.net/download/caofengtao1314/10576306

参考网站:https://blog.csdn.net/jiange_zh/article/details/50483099

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值