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.