Nginx source code learning notes (15th) -- ngx_master_process_cycle multi-process (1)

Source: Internet
Author: User
Tags sigint signal

Before learning about the core module, you should also learn about the ngx_start_worker_processes function. Today I will learn more about this method, mainly from http://blog.sina.com.cn/s/blog_677be95b0100iivk.html.

 

The nginx process is started in ngx_master_process_cycle (src/OS/Unix/ngx_process_cycle.c) (a single process is completed through ngx_single_process_cycle. Here, only the multi-process is analyzed ), in ngx_master_process_cycle, multiple sub-processes are created based on the worker_processes value in the configuration file, that is, one master process and multiple worker processes. Processes communicate with each other, processes communicate with each other, and processes communicate with each other through socketpair. socketpair is a full-duplex anonymous socket that can be used as an MTS queue. Unlike pipelines, each socket can be read or written, while the pipeline can only be used for writing or reading. Processes communicate with the outside through signals.

The master process mainly initializes global tasks and manages worker tasks. event processing is performed in worker.

Some important global data will be set during process startup, and the most important is the ngx_processes. Each time the master creates a worker, it puts a set ngx_process_t structure variable into ngx_processes, the length of the process is 1024. The newly created process is stored in the ngx_process_slot position. ngx_last_process is the next position of the last existing process in the Process Table. ngx_process_t is the process abstraction in nginx:

Src/OS/Unix/ngx_process.htypedef void (* ngx_spawn_proc_pt) (ngx_cycle_t * cycle, void * data); typedef struct {ngx_pid_t PID; // process ID int status; // Process status ngx_socket_t channel [2]; // socket handle ngx_spawn_proc_pt proc created by socketpair; // void * Data of the Process execution function; // the char * name parameter of the execution function; // name unsigned respawn: 1; // recreate unsigned just_spawn: 1; // The unsigned detached: 1 created for the first time; // The detached unsigned exiting: 1; // unsigned exited: 1; // exited} ngx_process_t;

 

Inter-process communication uses a pair of sockets created by socketpair. The ngx_channel_t structure variable is transmitted in the communication:

Ypedef struct {ngx_uint_t command; ngx_pid_t PID; // The sender process ID ngx_int_t slot; // The ngx_fd_t FD offset in the sender's progress table; // The handle sent to the recipient} ngx_channel_t; (src/OS/Unix/ngx_channel.h)/* command is the command to be sent. There are five types: # define ngx_rj_open_channel 1 # define ngx_1__close_channel 2 # define ngx_1__quit 3 # define ngx_1__terminate 4 # define ngx_1__reopen 5 */

 

The process of starting a process is an important part. to thoroughly analyze this process, we will use the ngx_master_process_cycle function first, which can be divided into the following steps:

1. The master node sets signals to be processed, including

Sigchld, sigalrm, sigio, SIGINT, ngx_reconfigure_signal (sighup), ngx_reopen_signal (SIGUSR1 ),
Ngx_noaccept_signal (sigwinch), ngx_terminate_signal (sigterm), ngx_shutdown_signal (sigquit ),
Ngx_changebin_signal (sigusr2 );

 

sigemptyset(&set);    sigaddset(&set, SIGCHLD);    sigaddset(&set, SIGALRM);    sigaddset(&set, SIGIO);    sigaddset(&set, SIGINT);    sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));    sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));    sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));    sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));    sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));    sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));

2. Call ngx_setproctilte to set the process title, title = "master process" + ngx_argv [0] +... + ngx_argv [ngx_argc-1];

 

title = ngx_pnalloc(cycle->pool, size);    p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);    for (i = 0; i < ngx_argc; i++) {        *p++ = ' ';        p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);    }    ngx_setproctitle(title);

3. Call ngx_start_worker_processes (cycle, CCF-> worker_processes, ngx_process_respawn) to start the worker process;

 

ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);    ngx_start_worker_processes(cycle, ccf->worker_processes,                               NGX_PROCESS_RESPAWN);

4. Call ngx_start_cache_manager_processes (cycle, 0) to start the File Cache Management process. Some modules need File Cache, such as the FastCGI module. These modules Add the File Cache path to cycle-> paths, the File Cache Management Process regularly calls the File Cache processing hooks of these modules to process the File Cache;

 

ngx_start_cache_manager_processes(cycle, 0);

Code annotation analysis. 5. The master processes semaphores cyclically.

Src/OS/Unix/ngx_process_cycle.cdelay = 0; sigio = 0; live = 1; for (;) {// delay is used to set the time to wait for the worker to launch, after the Master accepts the exit signal, // first sends the exit signal to the worker. However, it takes some time for the worker to exit if (Delay) {If (ngx_sigalrm) {sigio = 0; delay * = 2; ngx_sigalrm = 0;} ngx_log_debug1 (ngx_log_debug_event, cycle-> log, 0, "termination cycle: % d", delay); ITV. it_interval. TV _sec = 0; ITV. it_interval. TV _usec = 0; ITV. it_value. TV _sec = delay/ 1000; it V. it_value. TV _usec = (delay % 1000) * 1000; // set the timer // calculate based on the actual system time and send the sigalrm signal if (setitimer (itimer_real, & ITV, null) =-1) {ngx_log_error (ngx_log_alert, cycle-> log, ngx_errno, "setimer () failed");} ngx_log_debug0 (cycle, cycle-> log, 0, "sigsuspend"); // wait for the semaphore sigsuspend (& set); ngx_time_update (); ngx_log_debug1 (ngx_log_debug_event, cycle-> log, 0, "Wake up, sigio % I ", sigio); // receive The sigchld signal is generated, and worker exits (ngx_reap = 1) if (ngx_reap) {ngx_reap = 0; ngx_log_debug0 (ngx_log_debug_event, cycle-> log, 0, "reap children "); // process all workers. If a worker exits abnormally, restart the worker. If all workers exit, 0 live = ngx_reap_children (cycle) is returned );} // If worker exits // and receives the ngx_termin_terminate command, sigterm signal, or SIGINT signal (ngx_terminate = 1) // or the ngx_rj_quit command or sigquit signal (ngx_quit = 1), The Master exits if (! Live & (ngx_terminate | ngx_quit) {ngx_master_process_exit (cycle);} // receives the ngx_cmd_terminate command, sigterm signal, or SIGINT signal (ngx_terminate = 1) // notify all workers to exit and wait for the worker to exit if (ngx_terminate) {If (delay = 0) {// sets the latency delay = 50;} If (sigio) {sigio --; continue;} sigio = CCF-> worker_processes + 2/* cache processes */; If (delay> 1000) {// The latency has reached, send a sigkill signal to all workers to force the worker ngx_signal_worker_processe to be killed. S (cycle, sigkill);} else {// send a sigterm signal to all workers to notify worker to exit ngx_signal_worker_processes (cycle, ngx_signal_value (ngx_terminate_signal);} continue ;} // ngx_rj_quit command or sigquit signal (ngx_quit = 1) if (ngx_quit) {// send the sigquit signal cycle (cycle, ngx_signal_value (ngx_shutdown_signal) to all workers )); // close all listening socket ls = Cycle-> listening. ELTs; For (n = 0; n <cycle-> listening. nelts; n ++) {I F (ngx_close_socket (LS [N]. FD) =-1) {ngx_log_error (ngx_log_emerg, cycle-> log, ngx_socket_errno, ngx_close_socket_n "% v failed", & LS [N]. addr_text) ;}} cycle-> listening. nelts = 0; continue;} // receives the sighup signal if (ngx_reconfigure) {ngx_reconfigure = 0; // the code has been replaced and the worker is restarted without re-initializing the configuration. If (ngx_new_binary) {cycle (cycle, CCF-> worker_processes, errors); cycle (cycle, 0); ngx_noaccepting = 0; continue;} ngx_log_error (ngx_log_notice, cycle-> log, 0, "Recycling"); // re-Initialize cycle = ngx_init_cycle (cycle); If (cycle = NULL) {cycle = (ngx_cycle_t *) ngx_cycle; continue ;} // restart worker ngx_cycle = cycle; CCF = (ngx_core_conf_t *) ngx_get_conf (cycle-> conf_ctx, ngx_core_module); cycle (cycle, CCF-> worker_processes, cycle); cycle (cycle, 1); live = 1; cycle (cycle, ngx_signal_value (ngx_shutdown_signal);} // when ngx_noaccepting = 1, ngx_restart is set to 1, and worker if (ngx_restart) is restarted) {ngx_restart = 0; ngx_start_worker_processes (cycle, CCF-> worker_processes, ngx_process_respawn); cycle (cycle, 0); live = 1;} // receives the SIGUSR1 signal, re-open the log file if (ngx_reopen) {ngx_reopen = 0; ngx_log_error (ngx_log_notice, cycle-> log, 0, "reopening logs"); ngx_reopen_files (cycle, CCF-> User ); cycle (cycle, ngx_signal_value (cycle);} // when siguser2 is received, the hot code replaces if (ngx_change_binary) {ngx_change_binary = 0; ngx_log_error (ngx_log_notice, cycle-> log, 0, "Changing binary"); ngx_new_binary = ngx_exec_new_binary (cycle, ngx_argv);} // If (ngx_noaccept) the master node does not exit if (ngx_noaccept) {ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes (cycle, ngx_signal_value (ngx_shutdown_signal ));}}

 

Below is a summary. I hope you can read the above Code comments before reading the summary (at least once !!!

This conclusion comes from http://blog.csdn.net/lu_ming/article/details/5144427 and is very grateful to the author for his selfless dedication.

Ngx_master_process_cycle ()Function, which starts the worker process to work and processes the semaphores, killing or creating new processes.

A) blocking all signals of nginx concern;

B) set the title of the process (if you use PS-Aux to view the title, you can distinguish the master and worker processes. This is the role of the title .);

C) Start several work processes according to the number of worker_processes in ngx_core_conf_t;

D) Start a buffer management process;

E) initialize several flag: ngx_new_binary = 0; delay = 0; live = 1;

F) The next loop processes different States, most of which are different signals received by the process. The following is a detailed explanation of each process:

A) The delay value is not 0. If the sigalrm signal ngx_sigalrm is set to 1, multiply the delay time by 2. Finally, set a real-time timer;

B) suspend the current process. When there is a signal, it will exit from the pending status and continue to execute;

C) after exiting the pending state, update the current time based on the operating system time;

D) The ngx_reap is 1 (receives the sigchld Signal,A worker exits (ngx_reap = 1) and calls ngx_reap_children () to recycle the child process;

E) If all sub-processes exit (! Live) and the current process receives the ngx_signal_value (ngx_shutdown_signal) or ngx_signal_value (ngx_terminate_signal) signal, this process exits (ngx_master_process_exit (); Exit Processing first deletes the PID file, then, exit the hook from the process that calls all modules and destroy the memory pool object;

F) If ngx_terminate is 1 and delay is 0, it is set to 50. If delay> 1000, The sigkill signal is sent to the work process; otherwise, the ngx_signal_value (ngx_terminate_signal) signal is sent to the work process;

G) If ngx_quit is 1, The ngx_signal_value (ngx_shutdown_signal) signal is sent to the work process, and all sockets in global listening are closed; continue;

H) If ngx_reconfigure is 1 (ngx_signal_value (ngx_reconfigure_signal), read the config file again, create and initialize the ngx_cycle object, start the work process, and start the buffer management process, set live to 1 and call ngx_signal_worker_processes () to send the ngx_signal_value (ngx_shutdown_signal) signal;

I) ngx_new_binary is 1 (indicating a newly started process), starts the work process, starts the buffer management process, and then sets ngx_noaccepting to 0; continue;

J) If ngx_restart is 1 (ngx_restart is set to 1 when ngx_noaccepting is set to 1 and worker is restarted), start the work process, start the buffer management process, and set live to 1;

K) If ngx_reopen is 1 (ngx_signal_value (ngx_reopen_signal), open the log file again and call ngx_signal_worker_processes () to send the ngx_signal_value (ngx_reopen_signal) signal;

L) If ngx_change_binary is 1 (ngx_signal_value (ngx_changebin_signal), call ngx_exec_new_binary () to execute the new process;

M) If ngx_noaccept is 1 (ngx_signal_value (ngx_noaccept_signal), set ngx_noaccepting to 1, call notify () to send the ngx_signal_value (ngx_shutdown_signal) signal.

 

Next, let's continue with the sub-process creation and operations.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.