在讲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,并初始化一些基本的信息,好像其他的函数也没什么意思了很简单。。。就不写了。