在讲Nginx的事件驱动之前,得先弄明白ngx_connection_t这个结构。(定义在Ngx_connection.h)他是nginx事件驱动的基础,每一个监听在worker进程中都会为其分配一个connection,每一个监听接收到的连接,worker进程也会用connection来维护它,直到连接的终止,该connection才被回收。
额,由于它的定义实在太长了,所以这里就不列出来了,说几个比较重要的域吧:
void *data; //貌似是用来构成cycle中freeconnections链表用的 ngx_event_t *read; //读事件 ngx_event_t *write; //写事件 ngx_socket_t fd; //socket描述符 ngx_recv_pt recv; ngx_send_pt send; ngx_recv_chain_pt recv_chain; //chain结构,貌似是用来爆粗接收到的数据 ngx_send_chain_pt send_chain; ngx_listening_t *listening; // 监听头结构 off_t sent; ngx_log_t *log; ngx_pool_t *pool; //内存池
data域用来构成链表,这个待会说。raad指的是该连接的读事件,write是写事件,fd则对应当前连接的socket描述符,chain用来保存接受数据,如果这个连接是与监听绑定在一起的,那么listening域将于相应的监听端口绑定。pool则是这个连接的内存池,用来为当前连接分配内存,知道连接中断以后该内存池才会销毁。
在ngx_event_process_init函数中有connection数组的初始化代码:
/*创建一个connection数组,维护所有的connection; 本过程已经是在worker进程中了,所以是每个worker都有自己的 connection数组。 同样每一个worker进程也有自己的cycle */ cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log); if (cycle->connections == NULL) { return NGX_ERROR; } c = cycle->connections; //指向当前worker进程的cycle的connection数组 //创建读事件数组 cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n, cycle->log); if (cycle->read_events == NULL) { return NGX_ERROR; } rev = cycle->read_events; //指向当前worker进程的cycle的读取事件数组 for (i = 0; i < cycle->connection_n; i++) { rev[i].closed = 1; rev[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; //同样是指向当前worker进程的cycle的写事件的数组 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数组,connection数组使用得很是巧妙, 这里类似于一个链表的结构 能够快速的获取释放一个连接结构。下一篇画个图来详细看看 这个connection。 */ do { i--; c[i].data = next; //这里用于将connection串成一个链,好管理 c[i].read = &cycle->read_events[i]; //为当前的connection赋读事件 c[i].write = &cycle->write_events[i]; //为当前的connection赋写事件 c[i].fd = (ngx_socket_t) -1; next = &c[i]; #if (NGX_THREADS) c[i].lock = 0; #endif } while (i);
基本内容注释已经都说的比较清楚了,这里的connection门的组织是按照链表的形式的,并且有一个free域指向空闲connection的头。对于connection数组的重要操作有ngx_get_connection,为该函数传入一个socket描述符,然后函数从空闲connection中为该描述符分配一个connection,并初始化一些基本的信息,好像其他的函数也没什么意思了很简单。。。就不写了。