Posted on 2011-09-30 09:45
冷锋 阅读(401)
评论(0) 编辑 收藏 引用 所属分类:
linux
ngx_connection_t,抽象的连接,在core模块的ngx_event_process_init 函数中预先分配好。ngx_event_process_init预分配connects,read\write 事件的数组,
并依次初始化,并依次初始化各连接的链表关系,也就是在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,并设置listen的处理函数为 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;
}
}(结构体部分成员)
struct ngx_connection_s {
void *data;
ngx_event_t *read;//读事件处理
ngx_event_t *write;//写事件处理
ngx_socket_t fd;//连接对应的socket
ngx_listening_t *listening;/
ngx_log_t *log;
ngx_pool_t *pool;
//平台相关的读写,对应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
在上层应用(比如HTTP),使用ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)加入读事件。
在ngx_epoll_process_events函数中,
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
如果带有NGX_POST_EVENTS标记,就把事件投递到队列中不立即处理。
在ngx_process_events_and_timers 中,会在每个循环调用ngx_event_process_posted(cycle, &ngx_posted_events);不断取出事件队列进行处理。
NGX_POST_EVENTS是为了进行耗时操作前先释放进程锁,放入队列稍后再处理(用进程锁应该是避免N个进程accept导致的惊群,新版linux已经不会出现这个问题)。
if (ngx_posted_events) {
if (ngx_threaded) {
ngx_wakeup_worker_thread(cycle);
} else {
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}