Chinaunix首页 | 论坛 | 博客
  • 博客访问: 836673
  • 博文数量: 91
  • 博客积分: 2544
  • 博客等级: 少校
  • 技术积分: 1885
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-12 09:08
文章存档

2016年(10)

2014年(2)

2013年(4)

2012年(23)

2011年(23)

2010年(13)

2009年(14)

2007年(2)

分类: LINUX

2010-11-20 11:47:32

 

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


阅读(4183) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-11-22 17:56:28

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com