ngx_connection_t,抽象的連接,在core模塊的ngx_event_process_init 函數(shù)中預(yù)先分配好。ngx_event_process_init預(yù)分配connects,read\write 事件的數(shù)組,
并依次初始化,并依次初始化各連接的鏈表關(guān)系,也就是在data上存下一個connection的指針
cycle->connections =
ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
if (cycle->connections == NULL) {
return NGX_ERROR;
}
.
c = cycle->connections;
.
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;
//初始化linsten socket,并設(shè)置listen的處理函數(shù)為 rev->handler = ngx_event_acceptex;
Rev->accept=1;
for (i = 0; i < cycle->listening.nelts; i++) {
c = ngx_get_connection(ls[i].fd, cycle->log);
if (c == NULL) {
return NGX_ERROR;
}
}(結(jié)構(gòu)體部分成員)
cycle->connections =
ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
if (cycle->connections == NULL) {
return NGX_ERROR;
}
.
c = cycle->connections;
.
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;
//初始化linsten socket,并設(shè)置listen的處理函數(shù)為 rev->handler = ngx_event_acceptex;
Rev->accept=1;
for (i = 0; i < cycle->listening.nelts; i++) {
c = ngx_get_connection(ls[i].fd, cycle->log);
if (c == NULL) {
return NGX_ERROR;
}
}(結(jié)構(gòu)體部分成員)
struct ngx_connection_s {
void *data;
ngx_event_t *read;//讀事件處理
ngx_event_t *write;//寫事件處理
ngx_socket_t fd;//連接對應(yīng)的socket
ngx_listening_t *listening;/
ngx_log_t *log;
ngx_pool_t *pool;
//平臺相關(guān)的讀寫,對應(yīng)socket的send,recv
ngx_recv_pt recv;
ngx_send_pt send;
struct sockaddr *sockaddr;//地址
socklen_t socklen;
ngx_str_t addr_text;
}
void *data;
ngx_event_t *read;//讀事件處理
ngx_event_t *write;//寫事件處理
ngx_socket_t fd;//連接對應(yīng)的socket
ngx_listening_t *listening;/
ngx_log_t *log;
ngx_pool_t *pool;
//平臺相關(guān)的讀寫,對應(yīng)socket的send,recv
ngx_recv_pt recv;
ngx_send_pt send;
struct sockaddr *sockaddr;//地址
socklen_t socklen;
ngx_str_t addr_text;
}
ngx_get_connection:從freeconnect隊頭取出一個connection,并將socket綁定此connection
在上層應(yīng)用(比如HTTP),使用ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)加入讀事件。
在ngx_epoll_process_events函數(shù)中,
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
如果帶有NGX_POST_EVENTS標(biāo)記,就把事件投遞到隊列中不立即處理。
在ngx_process_events_and_timers 中,會在每個循環(huán)調(diào)用ngx_event_process_posted(cycle, &ngx_posted_events);不斷取出事件隊列進行處理。
NGX_POST_EVENTS是為了進行耗時操作前先釋放進程鎖,放入隊列稍后再處理(用進程鎖應(yīng)該是避免N個進程accept導(dǎo)致的驚群,新版linux已經(jīng)不會出現(xiàn)這個問題)。
if (ngx_posted_events) {
if (ngx_threaded) {
ngx_wakeup_worker_thread(cycle);
} else {
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
如果帶有NGX_POST_EVENTS標(biāo)記,就把事件投遞到隊列中不立即處理。
在ngx_process_events_and_timers 中,會在每個循環(huán)調(diào)用ngx_event_process_posted(cycle, &ngx_posted_events);不斷取出事件隊列進行處理。
NGX_POST_EVENTS是為了進行耗時操作前先釋放進程鎖,放入隊列稍后再處理(用進程鎖應(yīng)該是避免N個進程accept導(dǎo)致的驚群,新版linux已經(jīng)不會出現(xiàn)這個問題)。
if (ngx_posted_events) {
if (ngx_threaded) {
ngx_wakeup_worker_thread(cycle);
} else {
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}