IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    nginx模块开发(35)—信号模型(二)

    cjhust发表于 2013-08-16 15:05:27
    love 0

    6、进程通信

    工作原理

    clip_image002[4]

    Kill -WINCH

    image

    备注:向父进程发送kill –WINCH信号的时候,ngx_master_process_cycle父进程通知子进程退出。

    ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)

    static void

    ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)

    {

    ngx_int_t i;

    ngx_err_t err;

    ngx_channel_t ch;

    #if (NGX_BROKEN_SCM_RIGHTS)

    ch.command = 0;

    #else

    switch (signo) {

    case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): //kill -QUIT

    ch.command = NGX_CMD_QUIT;

    break;

    case ngx_signal_value(NGX_TERMINATE_SIGNAL): //CTRL+C

    ch.command = NGX_CMD_TERMINATE;

    break;

    case ngx_signal_value(NGX_REOPEN_SIGNAL): //kill -USR1

    ch.command = NGX_CMD_REOPEN;

    break;

    default:

    ch.command = 0;

    }

    #endif

    ch.fd = -1;

    for (i = 0; i < ngx_last_process; i++) {

    ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0,

    "child: %d %P e:%d t:%d d:%d r:%d j:%d",

    i,

    ngx_processes[i].pid,

    ngx_processes[i].exiting,

    ngx_processes[i].exited,

    ngx_processes[i].detached,

    ngx_processes[i].respawn,

    ngx_processes[i].just_spawn);

    if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {

    continue;

    }

    if (ngx_processes[i].just_spawn) {

    ngx_processes[i].just_spawn = 0;

    continue;

    }

    //子进程退出的时候,会将ngx_processes[i].exiting置为1

    if (ngx_processes[i].exiting

    && signo == ngx_signal_value(NGX_SHUTDOWN_SIGNAL))

    {

    continue;

    }

    if (ch.command) { // NGX_CMD_QUIT

    // ngx_write_channel成功的话,就continue

    //否则 kill 信号到子进程

    if (ngx_write_channel(ngx_processes[i].channel[0],

    &ch;, sizeof(ngx_channel_t), cycle->log)

    == NGX_OK)

    {

    if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {

    ngx_processes[i].exiting = 1;

    }

    continue;

    }

    }

    ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,

    "kill (%P, %d)" , ngx_processes[i].pid, signo);

    if (kill(ngx_processes[i].pid, signo) == -1) {

    err = ngx_errno;

    ngx_log_error(NGX_LOG_ALERT, cycle->log, err,

    "kill(%P, %d) failed", ngx_processes[i].pid, signo);

    if (err == NGX_ESRCH) {

    ngx_processes[i].exited = 1;

    ngx_processes[i].exiting = 0;

    ngx_reap = 1;

    }

    continue;

    }

    if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {

    ngx_processes[i].exiting = 1;

    }

    }

    }

    ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,ngx_log_t *log)

    ngx_int_t

    ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,

    ngx_log_t *log)

    {

    ssize_t n;

    ngx_err_t err;

    struct iovec iov[1];

    struct msghdr msg;

    #if (NGX_HAVE_MSGHDR_MSG_CONTROL)

    union {

    struct cmsghdr cm;

    char space[CMSG_SPACE(sizeof(int))];

    } cmsg;

    if (ch->fd == -1) {

    msg.msg_control = NULL;

    msg.msg_controllen = 0;

    } else { //here

    msg.msg_control = (caddr_t) &cmsg;

    msg.msg_controllen = sizeof(cmsg);

    cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));

    cmsg.cm.cmsg_level = SOL_SOCKET;

    cmsg.cm.cmsg_type = SCM_RIGHTS;

    /*

    * We have to use ngx_memcpy() instead of simple

    * *(int *) CMSG_DATA(&cmsg.cm;) = ch->fd;

    * because some gcc 4.4 with -O2/3/s optimization issues the warning:

    * dereferencing type-punned pointer will break strict-aliasing rules

    *

    * Fortunately, gcc with -O1 compiles this ngx_memcpy()

    * in the same simple assignment as in the code above

    */

    ngx_memcpy(CMSG_DATA(&cmsg.cm;), &ch-;>fd, sizeof(int));

    }

    msg.msg_flags = 0;

    #else

    if (ch->fd == -1) {

    msg.msg_accrights = NULL;

    msg.msg_accrightslen = 0;

    } else {

    msg.msg_accrights = (caddr_t) &ch-;>fd;

    msg.msg_accrightslen = sizeof(int);

    }

    #endif

    iov[0].iov_base = (char *) ch;

    iov[0].iov_len = size;

    msg.msg_name = NULL;

    msg.msg_namelen = 0;

    msg.msg_iov = iov;

    msg.msg_iovlen = 1;

    n = sendmsg(s , &msg;, 0);

    if (n == -1) { //32 ?

    err = ngx_errno;

    if (err == NGX_EAGAIN) {

    return NGX_AGAIN;

    }

    ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");

    return NGX_ERROR;

    }

    return NGX_OK;

    }

    ngx_channel_handler(ngx_event_t *ev)

    image

    image

    static void

    ngx_channel_handler(ngx_event_t *ev)

    {

    ngx_int_t n;

    ngx_channel_t ch;

    ngx_connection_t *c;

    if (ev->timedout) {

    ev->timedout = 0;

    return;

    }

    c = ev->data;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");

    for ( ;; ) {

    n = ngx_read_channel(c->fd, &ch;, sizeof(ngx_channel_t), ev->log);

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);

    if (n == NGX_ERROR) {

    if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {

    ngx_del_conn(c, 0);

    }

    ngx_close_connection(c);

    return;

    }

    if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {

    if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {

    return;

    }

    }

    if (n == NGX_AGAIN) {

    return;

    }

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,

    "channel command: %d", ch.command);

    switch (ch.command) {

    case NGX_CMD_QUIT:

    ngx_quit = 1;

    break;

    case NGX_CMD_TERMINATE:

    ngx_terminate = 1;

    break;

    case NGX_CMD_REOPEN:

    ngx_reopen = 1;

    break;

    case NGX_CMD_OPEN_CHANNEL:

    ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,

    "get channel s:%i pid:%P fd:%d",

    ch.slot, ch.pid, ch.fd);

    ngx_processes[ch.slot].pid = ch.pid;

    ngx_processes[ch.slot].channel[0] = ch.fd;

    break;

    case NGX_CMD_CLOSE_CHANNEL:

    ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,

    "close channel s:%i pid:%P our:%P fd:%d",

    ch.slot, ch.pid, ngx_processes[ch.slot].pid,

    ngx_processes[ch.slot].channel[0]);

    if (close(ngx_processes[ch.slot].channel[0]) == -1) {

    ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,

    "close() channel failed");

    }

    ngx_processes[ch.slot].channel[0] = -1;

    break;

    }

    }

    }

    ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)

    image

    7、示例参考

    信号处理

    #include

    #include

    #include

    void ngx_signal_handler(int signo)

    {

    printf("ngx_signal_handler!\n");

    }

    int main()

    {

    struct sigaction sa;

    memset(&sa;, 0, sizeof(struct sigaction));

    sa.sa_handler = ngx_signal_handler;

    sigemptyset(&sa.sa;_mask);

    if (sigaction(SIGINT, &sa;, NULL) == -1) {

    printf("sigaction() failed\n");

    return -1;

    }

    sigset_t set;

    //注释or不注释,结果是一样的

    //这部分的代码主要是为了验证信号集是否add成功

    /*

    sigemptyset(&set;);

    sigaddset(&set;, SIGINT);

    if (sigprocmask(SIG_BLOCK, &set;, NULL) == -1) {

    printf("sigprocmask() failed\n");

    return -1;

    }

    sigemptyset(&set;);

    */

    int i;

    for (i=0; i<100; i++){

    sleep(1);

    sigsuspend(&set;); //如果没有收到信号,会一直挂起在这里

    printf("i = %d\n", i);

    }

    }



沪ICP备19023445号-2号
友情链接