After reading the previous study notes, I believe that I have a certain understanding of the startup process of nginx. From this section on, we want to go deep into each module and learn the main operations within each module.
This article comes from: http://blog.csdn.net/lengzijian/article/details/7598996
Today we will learn about the event module. In the previous startup, we mentioned calling each module many times. The hook function of
This method mainly creates an ngx_event_conf_t structure and allocates memory space.
2. Read the configuration file:
For example, the read file has the following lines:
[cpp] view
plaincopyprint?
events
{
use epoll;
- worker_connections 10240; }
- The events in this place are a block instruction. Many instructions can be configured within the brackets. These instructions are defined in src/event/ngx_event.c
-
[cpp] view
plaincopyprint?
static
ngx_command_t ngx_event_core_commands[] = {
{ ngx_string(
"worker_ connections"-
), NGX_EVENT_CONF|NGX_CONF_TAKE1,
-
ngx_event_connections,
-
0, 0,
-
NULL },
-
...(omitted here)
-
-
NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_connections, 0, - 0,
NULL }, {ngx_string(- "use" ),
NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_use, 0, - 0,
NULL }, ngx_null_command }; -
-
When events are parsed, the following function will be called back:
[cpp] view
plaincopyprint?
-
- src/event/ngx_event.c
- static char *
- ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
- {
- char *rv;
- void ***ctx;
- ngx_uint_t i;
- ngx_conf_t pcf;
- ngx_event_module_t *m;
-
- /* count the number of the event modules and set up their indices */
- //计算event模块数量,并且记录
- ngx_event_max_module = 0;
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
- continue;
- }
-
- ngx_modules[i]->ctx_index = ngx_event_max_module++;
- }
-
- ctx = ngx_pcalloc(cf->pool, sizeof(void *));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
- //为每一个event模块分配空间,用来保存响应配置结构的地址
- //共分配了ngx_event_max_module个空间
- *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
- if (*ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *(void **) conf = ctx;
-
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
- continue;
- }
-
- m = ngx_modules[i]->ctx;
-
if -
(m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
-
((*ctx)[ngx_modules[i]->ctx_index] == NULL) { -
-
pcf = *cf; cf->ctx = ctx;
-
cf->module_type = NGX_EVENT_MODULE;
-
cf->cmd_type = NGX_EVENT_CONF;
-
//Since events is a block instruction, many other instructions can be configured in the events domain, -
-
//For example, the use mentioned before, etc., now start to parse the instructions in the events block and complete the initialization Work. -
-
rv = ngx_conf_parse(cf, NULL);
-
-
*cf = pcf;
- if (rv != NGX_CONF_OK)
-
- if(ngx_modules[i]-> ;type != NGX_EVENT_MODULE) {
m = ngx_modules[i]->ctx; -
//Loop to execute each event The init_conf function of the module, the initialization configuration structure
-
- (m-& gt; init_conf) {
-
RV = m-& gt; init_conf (CF-& GT; cycle, (*ctx) [ngx_modules[i]->ctx_index]); return
- rv;
- }
- return
NGX_CONF_OK;
- }
The most important process in the ngx_events_block() function is to call ngx_conf_parse(cf, NULL). The function of calling ngx_conf_parse() here is to complete the parsing of the events{} block in the configuration file, thereby calling all configurations under it. The callback function of the instruction completes the initialization of parsing the configuration file. But here I have a personal question. After asking the seniors, I will specify the question and answer******.
2. Initialize conf (init_conf)
ngx_event_init_conf()
This method mainly initializes the ngx_event_conf_t structure.
3.ngx_event_module_init
As the name suggests, it is the initialization operation of the module, but looking at the source code of each module, it is found that many modules do not have init callback functions. I am also struggling with why here, hoping to find the answer after learning all the code.
[cpp] view
plaincopyprint?
- src/event/ngx_event.c
- static ngx_int_t
- ngx_event_module_init(ngx_cycle_t *cycle)
- {
- void ***cf;
- u_char *shared;
- size_t size, cl;
- ngx_shm_t shm;
- ngx_time_t *tp;
- ngx_core_conf_t *ccf;
- ngx_event_conf_t *ecf;
-
- //判断ngx_events_module是否调用过初始化conf操作
- cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);
-
- if (cf == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
- "no "events" section in configuration");
- return NGX_ERROR;
- }
-
- //获取ngx_event_core_module模块的配置结构
- ecf = (*cf)[ngx_event_core_module.ctx_index];
-
- //查看是否是event中的模块,例如use 。。。。
- if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
- ngx_log_error(NGX _LOG_NOTICE, cycle->log, 0,
- "event method", ecf->name);
- }
- //Get the configuration structure of the ngx_core_module module
- ccf = (ngx_core_conf_t *) ngx_get_conf(cycle- >conf_ctx, ngx_core_module);
-
- //Get the timer_resolution parameter from the configuration structure of the ngx_core_module module ngx_timer_resolution = ccf->timer_resolution;
- #if !(NGX_WIN32)
-
- { ngx_int_t limit;
-
rlimit rlmt;
- //Get the ability of the current process The maximum number of open files man getrlimit
- (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { x_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- else{
- _The maximum number of connections to a module is unlimited
- / /Or ngx_event_core_module connection is greater than ngx_core_module maximum number of connections
- (ECF-& GT; Connections & GT; (ngx_uint_t) rlmt.rlim_cur
- (ccf-& gt; _NOFILE == ngx_conf_unset
limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ? ( ngx_int_t) rlmt.rlim_cur: ccf- & gt; rlimit_nofile; -
-
" open file resource limit: %i" ); endif /* !(NGX_WIN32) */-
-
-
//If the master process is closed, return -
- //Because closing the master process means single-process work Method,
-
//The subsequent operations create shared memory to implement locks and other work, which is not required for a single process.
- if (ccf->master == 0) {
-
NGX_OK; }
-
-
// If the accept mutex already exists, there is no need to create it again. -
NGX_OK;
-
}
-
- /* cl should be equal or bigger than cache line size */
-
cl = 128; -
//Create size here Shared memory, this shared memory will be divided into three equal segments
size = cl + cl - ,
- shm.size = size;
- shm.name.len = sizeof("nginx_shared_zone"
); - shm.name.data = (u_char *) "nginx_share d_zone"
; - shm.log = cycle->log;
-
- (ngx_shm_alloc(&shm) ! = NGX_OK) { NGX_ERROR;
NGX_ERROR; -
- shared = shm.addr;
- //Accept mutex gets the first cl size memory of shared memory
- ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; ngx_accept_mutex.spin = (ngx_uint_t) -1;
- /*Create accept mutex
- The implementation of accept mutex depends on whether it supports atomic operations, if there are corresponding atomic operations;
That’s it Use the obtained shared memory to implement the accept mutex; otherwise, the file lock will be used to implement the accept mutex. -
The function of the accept mutex is to avoid panic groups and achieve load balancing of worker processes.
ngx_accept_mutex, shared, cycle->lock_file.data) != NGX_OK)
//Get the cl-sized address of the second segment of memory
ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
(void
) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle- >log, 0,
x_connection_counter); //Get the size of the third segment of memory cl Address
ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
tp = ngx_timeofday() ;
ngx_random_number = (tp-> ;msec << 16) + ngx_pid; return
NGX_OK; 4.ngx_event_process_init in the previous worker process As mentioned in the analysis, when a worker process is created, the worker process will first initialize the process, and at this time the ngx_event_process_init function will be called. [cpp] view
plaincopyprint?
- src/event/ngx_event.c
- staticngx_int_t
- ngx_event_process_init(ngx_cycle_t *cycle)
- {
- ngx_uint_t m, i;
- ngx_event_t *rev, *wev;
- ngx_listening_t *ls;
- ngx_connection_t *c, *next, *old;
- ngx_core_conf_t *ccf;
- ngx_event_conf_t *ecf;
- ngx_event_module_t *module;
-
- //As before, get the configuration structure of the response module
- ccf = (ngx_core_conf_t *) ngx_get_conf( cycle->conf_ctx, ngx_core_module);
- ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
-
- //Master process is open, worker process is greater than 1, accept_mutex has been created
- //cai Open the accept mutex
- if (ccf->master &&ccf->worker_processes > 1 &&ecf->accept_mutex) {
- ngx_use_accept_mutex = 1; / /Use mutex
- ngx_accept_mutex_held = 0; //Whether to get accept mutex
- ngx_accept_mutex_delay = ecf->accept_mutex_delay;//After failure to compete for the mutex , waiting for the next scramble time interval
-
- } else {
- ngx_use_accept_mutex = 0 ;
- }
-
- #if (NGX_THREADS)
- //Threads aside
- #endif
- //Initialize counter, a red will be created here Black Tree, to maintain the timer, will explain in detail later
- if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
- return NGX_ERROR;
} - for (m = 0; ngx_modules[m]; m++) {
- //As mentioned here before, skip non-NGX_EVENT_MODULE modules
- }
- // Modules specified by non-use configuration instructions are skipped, Linux default epoll ->use) { module = ngx_modules[m]->ctx;
- /*Call the init function of the specific time module ( These modules are located in the src/event/modules directory), so nginx A layer of abstraction has been made to the time module, which makes it easier for different systems to use different event models and expands new time models. Our focus should be on epoll.
- The init callback here actually calls the ngx_epoll_init function. The module->actions structure encapsulates all interface functions of epoll. nginx registers epoll into the event abstraction layer through the actions structure.
The type of actions is ngx_event_action_t, located in src/event/ngx_event.h
-
These specific contents will be explained in the next section.
- module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
- *fatal */
- exit(2); break
; - }
- //Omitted here Part of the content
- //Create a global ngx_connection_t array to save all connections
- //Since this process is executed in each worker process, each worker has Own connection array
- cycle->connections = ngx_alloc(sizeof
(ngx_connection_t) *cycle->connection_n, cycle->log); - if
(cycle->connections == NULL) { -
- c = cycle->connections;
- //Create an array of read events
- cycle->read_events = ngx_alloc(sizeof
- (ngx_event_t) * cycle->connection_n, ;log);
-
if
- (cycle->read_events == NULL) {
- NGX_ERROR;
-
}
-
rev = cycle->read_events;
- for (i = 0; i < cycle->connection_n; i++) {
-
rev[i].closed = 1 ;
- [i].instance = 1;
#if (NGX_THREADS)-
rev[i].lock = &c[i].lock;
-
rev[i].own_lock = &c[i].lock;
#endif-
- }
- //创建一个写事件数组
- cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
- cycle->log);
- if (cycle->write_events == NULL) {
- return NGX_ERROR;
- }
-
- wev = cycle->write_events;
- for (i = 0; i < cycle->connection_n; i++) {
- wev[i].closed = 1;
- #if (NGX_THREADS)
- wev[i].lock = &c[i].lock;
- wev[i].own_lock = &c[i].lock;
- #endif
- }
-
- i = cycle->connection_n;
- next = NULL;
- //初始化整个connection数组
- do {
- i--;
-
- c[i].data = next;
- c[i].read = &cycle->read_events[i];
- c[i].write = &cycle->write_events[i];
- c[i].fd = (ngx_socket_t) -1;
-
- next = &c[i];
-
- #if (NGX_THREADS)
- c[i].lock = 0;
- #endif
- }while (i);
-
- cycle->free_connections = next;
- cycle->free_connection_n = cycle-> connection_n;
-
- /* for each listening socket */
- //Assign a connection from the connection array for each listening socket, that is, a slot
- ls = cycle->listening .els; Connect to solt
- _ C = ngx_get_connection (ls [i] .fd, cycle-& gt; log); NGX_ERROR; }
-
- c->log = &ls[i].log;
-
- c->listening = &ls[i];
- ls[i].connection = c;
-
- rev = c->read;
-
- rev->log = c->log;
- rev->accept = 1; //读时间发生,调用accept
-
- #if (NGX_HAVE_DEFERRED_ACCEPT)
- //省略
- #endif
-
- if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
- if (ls[i].previous) {
-
- /*
- * delete the old accept events that were bound to
- * the old cycle read events array
- */
-
- old = ls[i].previous->connection;
-
- if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- old->fd = (ngx_socket_t) -1;
- }
- }
-
- //Register the callback function ngx_event_accept
- rev->handler = ngx_even t_accept;
- , do not put the listening socket into epoll for the time being, but
-
{
-
- }
- } else{
- //If the accept mutex is not used, then put this listening socket into epoll.
-
- #endif
- }
-
return
- NGX_OK;
- }
-
Until now , event-driven initialization has been completed.
The above introduces the nginx source code study notes (20) - event module 1 - initialization, including IOC and counter content. I hope it will be helpful to friends who are interested in PHP tutorials. -