nginx源代码分析 - 启动(五) 调试后台进程和worker进程

nginx的网络模型是,master进程,即daemon进程,负责listen+bind,所有子进程都监听80端口,注册监听fd的读事件,即accept事件。


多进程调试方法

sudo gdb ./objs/nginx
r -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf

info inferiors
follow-fork-mode  detach-on-fork   说明
parent                   on               只调试主进程(GDB默认)
child                     on               只调试子进程
parent                   off              同时调试两个进程,gdb跟主进程,子进程block在fork位置
child                     off              同时调试两个进程,gdb跟子进程,主进程block在fork位置

set follow-fork-mode child
set detach-on-fork off
catch fork

b ngx_configure_listening_sockets
b ngx_connection.c:794

b ngx_set_inherited_sockets
b ngx_create_listening

b ngx_open_listening_sockets
b ngx_connection.c:591

b ngx_close_listening_sockets
b ngx_event_accept

b ngx_epoll_init
b ngx_epoll_add_event
b ngx_epoll_del_event
b ngx_epoll_add_connection
b ngx_epoll_del_connection
b ngx_epoll_process_events

b ngx_daemon.c:29

程序hang住以后可以通过sudo kill -9 master进程号,然后inferior worker进程号来
终止父进程,开启子进程调试

liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
 6972 pts/6    S+     0:00 sudo gdb ./objs/nginx
 6973 pts/6    S+     0:00 gdb ./objs/nginx
 6981 ?        Ss     0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
 6982 ?        S      0:00 nginx: worker process                                                                                    
 6983 ?        S      0:00 nginx: worker process             
 
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      6982/nginx: worker
tcp        0      0 192.168.235.128:22      192.168.235.1:58019     ESTABLISHED -   

第一个worker listen了80端口

ngx_worker_process_init(cycle, worker);

for (i = 0; cycle->modules[i]; i++) {
    if (cycle->modules[i]->init_process) {
        if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
            /* fatal */
            exit(2);
        }
    }
}

ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler)
    ngx_add_event(ev, event, 0)

ngx_event_module_t  ngx_epoll_module_ctx = {
    &epoll_name,
    ngx_epoll_create_conf,               /* create configuration */
    ngx_epoll_init_conf,                 /* init configuration */

    {
        ngx_epoll_add_event,             /* add an event */
        ngx_epoll_del_event,             /* delete an event */
        ngx_epoll_add_event,             /* enable an event */
        ngx_epoll_del_event,             /* disable an event */
        ngx_epoll_add_connection,        /* add an connection */
        ngx_epoll_del_connection,        /* delete an connection */
#if (NGX_HAVE_EVENTFD)
        ngx_epoll_notify,                /* trigger a notify */
#else
        NULL,                            /* trigger a notify */
#endif
        ngx_epoll_process_events,        /* process the events */
        ngx_epoll_init,                  /* init the events */
        ngx_epoll_done,                  /* done the events */
    }
};

ngx_event_actions = ngx_epoll_module_ctx.actions;

#define ngx_process_events   ngx_event_actions.process_events
#define ngx_done_events      ngx_event_actions.done

#define ngx_add_event        ngx_event_actions.add
#define ngx_del_event        ngx_event_actions.del
#define ngx_add_conn         ngx_event_actions.add_conn
#define ngx_del_conn         ngx_event_actions.del_conn

#define ngx_notify           ngx_event_actions.notify

#define ngx_add_timer        ngx_event_add_timer
#define ngx_del_timer        ngx_event_del_timer

Breakpoint 2, ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
327        epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
(gdb) bt
#0  ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
#1  0x0000000000441f71 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:620
#2  0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3  0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4  0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367

ngx_event_core_module的init_process方法,调用ngx_epoll_module的
module = cycle->modules[m]->ctx;
module->actions.init(cycle, ngx_timer_resolution)

在成为后台进程前
(gdb) bt
#0  ngx_create_listening (cf=0x7fffffffe1e0, sockaddr=0x731f30, socklen=16) at src/core/ngx_connection.c:22
#1  0x00000000004575d0 in ngx_http_add_listening (cf=0x7fffffffe1e0, addr=0x731f30) at src/http/ngx_http.c:1707
#2  0x00000000004574a4 in ngx_http_init_listening (cf=0x7fffffffe1e0, port=0x731ec0) at src/http/ngx_http.c:1658
#3  0x0000000000456c79 in ngx_http_optimize_servers (cf=0x7fffffffe1e0, cmcf=0x730680, ports=0x731e98) at src/http/ngx_http.c:1412
#4  0x0000000000454ab6 in ngx_http_block (cf=0x7fffffffe1e0, cmd=0x6fc4a0 <ngx_http_commands>, conf=0x72e550)
    at src/http/ngx_http.c:333
#5  0x000000000042f262 in ngx_conf_handler (cf=0x7fffffffe1e0, last=1) at src/core/ngx_conf_file.c:427
#6  0x000000000042eda1 in ngx_conf_parse (cf=0x7fffffffe1e0, filename=0x72d6f8) at src/core/ngx_conf_file.c:283
#7  0x000000000042b004 in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:274
#8  0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276

Breakpoint 9, ngx_open_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:591
591                if (listen(s, ls[i].backlog) == -1) {
(gdb) p s
$2 = 7
(gdb) p i
$3 = 0
(gdb) p ls[i].backlog
$4 = 511
(gdb) bt
#0  ngx_open_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:591
#1  0x000000000042c299 in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:609
#2  0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276


gdb) p ls[i].fd
$6 = 7
(gdb) p ls[i].backlog
$7 = 511
(gdb)
794                if (listen(ls[i].fd, ls[i].backlog) == -1) {
(gdb) bt
#0  ngx_configure_listening_sockets (cycle=0x72d530) at src/core/ngx_connection.c:794
#1  0x000000000042c2be in ngx_init_cycle (old_cycle=0x7fffffffe3b0) at src/core/ngx_cycle.c:614
#2  0x000000000040b6d0 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:276

listen函数被调用了2次,/第二次调用写的注释* change backlog via listen() */

创建daemon线程
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6    S+     0:00 sudo gdb ./objs/nginx
13280 pts/6    S+     0:01 gdb ./objs/nginx
13376 pts/6    t      0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
    父进程
13470 pts/6    t      0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
    子进程
13476 pts/7    S+     0:00 grep --color=auto nginx

liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -               
tcp        0      0 192.168.235.128:22      192.168.235.1:58019     ESTABLISHED -

创建worker进程
(gdb) bt
#0  0x00007ffff7024025 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/x86_64/../fork.c:130
#1  0x000000000044cbfd in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:186
#2  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#3  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#4  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367

liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6    S+     0:00 sudo gdb ./objs/nginx
13280 pts/6    S+     0:02 gdb ./objs/nginx
13376 pts/6    t      0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13470 ?        ts     0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
    daemon进程
13492 ?        t      0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
    
13499 pts/7    S+     0:00 grep --color=auto nginx
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -               
tcp        0      0 192.168.235.128:22      192.168.235.1:58019     ESTABLISHED -

继续运行子进程:
liuwb@ubuntu:~/Desktop/code/nginx-code$ ps ax | grep nginx
13279 pts/6    S      0:00 sudo gdb ./objs/nginx
13280 pts/6    S      0:04 gdb ./objs/nginx
13376 pts/6    t+     0:00 /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13470 ?        ts     0:00 nginx: master process /home/liuwb/Desktop/code/nginx-code/objs/nginx -p /home/liuwb/Desktop/code/nginx-code/ -c conf/nginx.conf
13492 ?        S      0:00 nginx: worker process                                                                                    
13536 pts/7    S+     0:00 grep --color=auto nginx
liuwb@ubuntu:~/Desktop/code/nginx-code$ netstat -antp | grep 80
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      13492/nginx: worker
tcp        0      0 192.168.235.128:22      192.168.235.1:58019     ESTABLISHED -  

liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/13492/status
Name:    nginx
State:    S (sleeping)
Tgid:    13492
Ngid:    0
Pid:    13492
PPid:    13470
TracerPid:    13280
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000

liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/13492/stack
[<ffffffff81230e0c>] ep_poll+0x26c/0x350
[<ffffffff81231ff5>] SyS_epoll_wait+0xb5/0xe0
[<ffffffff817b668d>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff

hung在了epoll_wait,即ngx_epoll_process_events



父进程,挂在信号处理的地方
liuwb@ubuntu:~/Desktop/code/nginx-code$ sudo cat /proc/14206/stack
[<ffffffff81085a1d>] sigsuspend+0x3d/0x80
[<ffffffff81085aa0>] SyS_rt_sigsuspend+0x40/0x60
[<ffffffff817b668d>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff


Breakpoint 14, ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
327        epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
(gdb) bt
#0  ngx_epoll_init (cycle=0x72d530, timer=0) at src/event/modules/ngx_epoll_module.c:327
#1  0x0000000000441f71 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:620
#2  0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3  0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4  0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367

下面是添加listen fd的读事件,触发了才会调用accept
Breakpoint 15, ngx_epoll_add_event (ev=0x799e40, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
587        c = ev->data;
(gdb) bt
#0  ngx_epoll_add_event (ev=0x799e40, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
#1  0x0000000000442985 in ngx_event_process_init (cycle=0x72d530) at src/event/ngx_event.c:857
#2  0x0000000000450bec in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:902
#3  0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4  0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367

ngx_channel = ngx_processes[s].channel[1];
ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT, ngx_channel_handler)
管道注册读事件,和父进程通信
(gdb) bt
#0  ngx_epoll_add_event (ev=0x799ea0, event=8193, flags=0) at src/event/modules/ngx_epoll_module.c:587
#1  0x000000000044c40b in ngx_add_channel_event (cycle=0x72d530, fd=8, event=8193, handler=0x45116a <ngx_channel_handler>)
    at src/os/unix/ngx_channel.c:233
#2  0x0000000000450da2 in ngx_worker_process_init (cycle=0x72d530, worker=0) at src/os/unix/ngx_process_cycle.c:938
#3  0x00000000004503f1 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:734
#4  0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#5  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#6  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#7  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367

子进程准备进入循环,进入循环前,2次到了这里,说明第1次epoll_wait返回了
(gdb) bt
#0  ngx_epoll_process_events (cycle=0x72d530, timer=18446744073709551615, flags=1) at src/event/modules/ngx_epoll_module.c:797
#1  0x00000000004414c8 in ngx_process_events_and_timers (cycle=0x72d530) at src/event/ngx_event.c:242
#2  0x00000000004504a5 in ngx_worker_process_cycle (cycle=0x72d530, data=0x0) at src/os/unix/ngx_process_cycle.c:753
#3  0x000000000044cca6 in ngx_spawn_process (cycle=0x72d530, proc=0x4503b0 <ngx_worker_process_cycle>, data=0x0,
    name=0x4dcfcb "worker process", respawn=-3) at src/os/unix/ngx_process.c:198
#4  0x000000000044f2e1 in ngx_start_worker_processes (cycle=0x72d530, n=2, type=-3) at src/os/unix/ngx_process_cycle.c:358
#5  0x000000000044e894 in ngx_master_process_cycle (cycle=0x72d530) at src/os/unix/ngx_process_cycle.c:130
#6  0x000000000040ba95 in main (argc=5, argv=0x7fffffffe6c8) at src/core/nginx.c:367


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值