Nginx source code learning notes (17) -- ngx_worker_process_cycle sub-process execution

Source: Internet
Author: User
Tags set socket

The previous section describes how to enable a sub-process for a master process and operations performed by the master process. This section describes the sub-process processing function ngx_worker_process_cycle.

Src/OS/Unix/strongswan (ngx_cycle_t * cycle, void * Data) {ngx_uint_t I; ngx_connection_t * C; // In the master, ngx_process is set to ngx_process_master ngx_process = cycle; // initialize ngx_worker_process_init (cycle, 1); ngx_setproctitle ("Worker Process"); # If (ngx_threads) // do not explain the thread Code # endif (;;) {// if the process exits, close all connections if (ngx_exiting) {c = Cycle-> connections; (I = 0; I <cycle-> connection_n; I ++) {/* thread: Lock */If (C [I]. FD! =-1 & C [I]. idle) {C [I]. close = 1; C [I]. read-> handler (C [I]. read) ;}} if (condition = condition) {ngx_log_error (ngx_log_notice, cycle-> log, 0, "exiting"); cycle (cycle) ;}} ngx_log_debug0 (ngx_log_debug_event, cycle-> log, 0, "worker cycle"); // processing time and timing ngx_process_events_and_timers (cycle); // receives the ngx_cmd_terminate command if (ngx_terminate) {ngx_l Og_error (ngx_log_notice, cycle-> log, 0, "exiting"); // After cleaning, the process exits and calls the hook exit_process ngx_worker_process_exit (cycle) of all modules );} // receives the ngx_cmd_quit command if (ngx_quit) {ngx_quit = 0; ngx_log_error (ngx_log_notice, cycle-> log, 0, "gracefully shutting down "); ngx_setproctitle ("Worker Process is shutting down"); // if the process is not "exiting" If (! Ngx_exiting) {// close the listening socket and set to exit the ngx_close_listening_sockets (cycle); ngx_exiting = 1 ;}// receive the ngx_cmd_reopen command and re-open the log if (ngx_reopen) {ngx_reopen = 0; ngx_log_error (ngx_log_notice, cycle-> log, 0, "reopening logs"); ngx_reopen_files (cycle,-1 );}}}


 

Next let's take a look at the initialization operation of the process:

1. Global settings: Set the execution environment, priority, restriction, setgid, setuid, and signal initialization based on global configuration information;

2. Call the hook init_process of all modules;

src/os/unix/ngx_process_cycle.cfor (i = 0; ngx_modules[i]; i++) {    if (ngx_modules[i]->init_process) {        if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {            /* fatal */            exit(2);        }    }}

 

3. disable the socket that is not used. Disable the channel [0] handle of the current worker and the Channel [1] Handle of other workers. The current worker uses the channel [0] Handle of other workers to send messages, use the channel [1] handle of the current worker to listen for readable events:

Src/OS/Unix/ngx_process_cycle.cfor (n = 0; n <ngx_last_process; n ++) {// traverse all worker processes if (ngx_processes [N]. PID =-1) {continue;} If (n = ngx_process_slot) {if it is your own continue;} If (ngx_processes [N]. channel [1] =-1) {continue;} // close all other worker process channel [1] handle (for listening) if (close (ngx_processes [N]. channel [1]) =-1) {ngx_log_error (ngx_log_alert, cycle-> log, ngx_errno, "close () channel failed ");}} // close your own channel [0] handle (for sending information) if (close (ngx_processes [ngx_process_slot]. channel [0]) =-1) {ngx_log_error (ngx_log_alert, cycle-> log, ngx_errno, "close () channel failed");} // that's why, use the channel [0] Handle of another worker to send a message // use the channel [1] handle of the current worker to listen for the readable time

 

4. Listen for readable events in the Channel [1] handle of the current worker:

if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,                          ngx_channel_handler)    == NGX_ERROR){    /* fatal */    exit(2);}

 

Ngx_add_channel_event adds the readable event of the Connection established on the ngx_channel (Channel [1] of the current worker) to the event monitoring queue. The event processing function is ngx_channel_hanlder (ngx_event_t * eV ). When there is a readable event, ngx_channel_handler is responsible for processing the message. For specific code, you can view src/OS/Unix/ngx_channel.c. The process is as follows:

Src/OS/Unix/ngx_process_cycle.cstatic voidngx_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"); (;;) {// read the message n = ngx_read_channel (c-> FD, & Ch, sizeof (ngx_channel_t), ev-> log) from Channel [1]; 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); // The 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: Quit, 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_pai_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 ;}}}

 

Conclusion: I want to read the content and code of this section and the previous section to my students:

This conclusion comes from http://blog.csdn.net/lu_ming/article/details/5151930 thanks to the author for his selfless dedication

1. ngx_start_worker_processes () function. This function calls ngx_worker_process_cycle () to create a work process and initialize relevant resources and properties with the ngx_worker_process_cycle () function as the parameter; the execution function ngx_worker_process_cycle of the execution sub-process. It broadcasts information about the currently created worker process to all the previously created workers. Each process opens a channel (ngx_pass_open_channel ()).
The main logic of the ngx_start_worker_processes () function is as follows:

A) the respawn parameter has two meanings: type, that is, the method for creating new programs, such as ngx_process_respawn, ngx_process_just_respawn ..., It is a negative value; the other is the subscript of the process information table, which is not negative;
B) find an empty entry in the ngx_processes [] process information table;
C) if it is not a separate sub-process (respawn! = Ngx_process_detached ),
I) create a pair of connected anonymous sockets;
Ii) set socket (Channel [0] and channel [1]) to non-blocking mode;
Iii) Enable the message-driven Io of Channel [0;
Iv) set the owner of Channel [0] and control the sigio signal of Channel [0] to be sent only to this process;
V) set the fd_cloexec attribute of Channel [0] and channel [1] (the process closes the socket after executing Exec );
Vi) obtain the socket (ngx_channel = ngx_processes [s]. Channel [1];) for listening to readable events;
D) ngx_processes [s]. Channel [0] =-1;
Ngx_processes [s]. Channel [1] =-1;
E) set the table entry index of the current sub-process; ngx_process_slot = s;
F) create a sub-process;
G) in the sub-process formula, set the process ID of the current sub-process and run the execution function;
H) When respawn> = 0, the PID is directly returned;
I) set other table entry fields;
Ngx_processes [s]. Proc = proc;
Ngx_processes [s]. Data = data;
Ngx_processes [s]. Name = Name;
Ngx_processes [s]. exiting = 0;
J) set table items according to the respawn type.

Create socketpair for inter-process communication. The master process creates a socket for each worker. The master process space opens the handles at both ends of the channel [0] and channel [1] of all socketpair. When a worker is created, the worker inherits all the socketpair files created and opened by the master. This worker is initialized (ngx_worker_process_init is called) the channel [0] corresponding to the socketpair of this process and the Channel [1] corresponding to other workers will be disabled. keep the channel [1] corresponding to socketpair of the current process and the Channel [0] corresponding to other workers open, and listen to the readable events of the channel [1] corresponding to socketpair of the current process. In this way, each worker has the channel [0] of other workers and can sendmsg (Channel [0],
...) Send messages to other workers.
 
The worker created before the current worker obtains its channel [0] through inheritance, but how to obtain the channel [0] of the created process? The answer is above (ngx_start_worker_processes) after a worker is created and started, the master will call ngx_pass_open_channel to broadcast the worker channel [0] and process ID, and the offset slot in the Process Table (ngx_write_channel ()) this way, after creating all the processes, each worker obtains the channel [0] Of all the other workers.
 
The ngx_worker_process_cycle () function is the actual work content of each process. This function first calls ngx_create_thread () to initialize each thread. We know that each thread has a start handler function. The nginx thread handler function is ngx_worker_thread_cycle (). The most important thing in the internal process is the call to the ngx_event_thread_process_posted () function, used to process each request.
 
After the initialization thread ends, call the ngx_process_events_and_timers () function. This function continues to call the ngx_process_events interface to listen to events. Generally, the corresponding function is ngx_epoll_process_events (), if I/O models of other classes are used, the corresponding actual functions should be implemented. This interface is used to ship the event to the ngx_posted_events event queue and process it in the ngx_event_thread_process_posted () function.

 

2. ngx_start_cache_manager_processes () function. This function is in the path array of the ngx_cycle Global Object and checks whether there are manager and loader functions. There are manage functions, creating buffer management processes, opening corresponding channels, responsible for management; loader functions, creating buffer management processes, opening corresponding channels, responsible for loading.

3. ngx_pass_open_channel () function. In the global ngx_processes array, this function opens a channel for all processes whose PID is not-1 and channel [0] is not-1. That is, to open a channel for each created work process and send a message (ngx_write_channel () to the work process.

4. ngx_signal_worker_processes () function, which sends a signal to each work process. For the ngx_signal_value (ngx_reopen_signal) signal, set the mark exiting in ngx_processes to 1.

5. ngx_reap_children () function, which clears the process to be exited. Each item in the ngx_processes array stores the signal of the corresponding process, such as PID, status, and channel. If a sub-process has not exited exiting or! Detached, set live to 1.

Ngx_master_process_exit () function. This function deletes the PID file, calls the exit_master hook function in the module, and destroys the memory pool.

 

 

 

 

 

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.