ngx_epoll_init函数的调用
//(3.2)ngx_epoll_init函数的调用(要在子进程中执行)
//四章,四节 project1.cpp:nginx中创建worker子进程;
//nginx中创建worker子进程
//官方nginx ,一个master进程,创建了多个worker子进程;
// master process ./nginx
// worker process
//(i)ngx_master_process_cycle() //创建子进程等一系列动作
//(i) ngx_setproctitle() //设置进程标题
//(i) ngx_start_worker_processes() //创建worker子进程
//(i) for (i = 0; i < threadnums; i++) //master进程在走这个循环,来创建若干个子进程
//(i) ngx_spawn_process(i,"worker process");
//(i) pid = fork(); //分叉,从原来的一个master进程(一个叉),分成两个叉(原有的master进程,以及一个新fork()出来的worker进程
//(i) //只有子进程这个分叉才会执行ngx_worker_process_cycle()
//(i) ngx_worker_process_cycle(inum,pprocname); //子进程分叉
//(i) ngx_worker_process_init();
//(i) sigemptyset(&set);
//(i) sigprocmask(SIG_SETMASK, &set, NULL); //允许接收所有信号
//(i) g_socket.ngx_epoll_init(); //初始化epoll相关内容,同时 往监听socket上增加监听事件,从而开始让监听端口履行其职责
//(i) m_epollhandle = epoll_create(m_worker_connections);
//(i) ngx_epoll_add_event((*pos)->fd....);
//(i) epoll_ctl(m_epollhandle,eventtype,fd,&ev);
//(i) ngx_setproctitle(pprocname); //重新为子进程设置标题为worker process
//(i) for ( ;; ) {}. .... //子进程开始在这里不断的死循环
//(i) sigemptyset(&set);
//(i) for ( ;; ) {}. //父进程[master进程]会一直在这里循环
ngx_epoll_init 函数内容
#和网络相关
[Net]
#监听的端口数量,一般都是1个,当然如果支持多于一个也是可以的
ListenPortCount = 2
#ListenPort+数字【数字从0开始】,这种ListenPort开头的项有几个,取决于ListenPortCount的数量,
ListenPort0 = 80
ListenPort1 = 443#epoll连接的最大数【是每个worker进程允许连接的客户端数】,实际其中有一些连接要被监听socket使用,实际允许的客户端连接数会比这个数小一些
worker_connections = 1024
//初始化函数【fork()子进程之前干这个事】
//成功返回true,失败返回false
bool CSocekt::Initialize()
{ReadConf(); //读配置项bool reco = ngx_open_listening_sockets(); //打开监听端口return reco;
}//专门用于读各种配置项
void CSocekt::ReadConf()
{CConfig *p_config = CConfig::GetInstance();m_worker_connections = p_config->GetIntDefault("worker_connections",m_worker_connections); //epoll连接的最大项数m_ListenPortCount = p_config->GetIntDefault("ListenPortCount",m_ListenPortCount); //取得要监听的端口数量return;
}
//连接池: 数组,元素数量就是worker_connections【1024】,每个数组元素类型为 ngx_connection_t【结构】; ---结构数组;
//为什么要引入这个数组: 2个监听套接字, 用户连入进来,每个用户多出来一个套接字;
//把 套接字数字跟一块内存捆绑,达到的效果就是将来我通过这个套接字,就能够把这块内存拿出来;
初始化 连接池
当执行完成如下的代码后,参考图
do {i--; //注意i是数字的末尾,从最后遍历,i递减至数组首个元素//好从屁股往前来---------c[i].data = next; //设置连接对象的next指针,注意第一次循环时next = NULL;c[i].fd = -1; //初始化连接,无socket和该连接池中的连接【对象】绑定c[i].instance = 1; //失效标志位设置为1【失效】,此句抄自官方nginx,这句到底有啥用,后续再研究c[i].iCurrsequence = 0; //当前序号统一从0开始//----------------------next = &c[i]; //next指针前移} while (i); //循环直至i为0,即数组首地址m_pfree_connections = next; //设置空闲连接链表头指针,因为现在next指向c[0],注意现在整个链表都是空的m_free_connection_n = m_connection_n; //空闲连接链表长度,因为现在整个链表都是空的,这两个长度相等;
ngx_get_connection()重要函数:从连接池中找空闲连接;注意在这段代码中 应该只是给 监听fd 一个空闲连接对象。
for(pos = m_ListenSocketList.begin(); pos != m_ListenSocketList.end(); ++pos){c = ngx_get_connection((*pos)->fd); //从连接池中获取一个空闲连接对象
理论上,后面应该要给每一个connectfd也要给一个 空闲连接对象。
//c)ngx_epoll_add_event() ************
// epoll_ctl();
//d)ev.data.ptr = (void *)( (uintptr_t)c | c->instance); 把一个指针和一个位 合二为一,塞到一个void *中去,
//后续能够把这两个值全部取出来,如何取,取出来干嘛,后续再说;
//ps -eo pid,ppid,sid,tty,pgrp,comm,stat,cmd | grep -E 'bash|PID|nginx'
//如下命令用root权限执行
//sudo su 获得root权限
//lsof -i:80 列出哪些进程在监听80端口
//netstat -tunlp | grep 80
//总结:
//a)epoll_create();epoll_ctl();
//b)连接池技巧ngx_get_connection(),ngx_free_connection();学习这种编程方法;
//c)同时传递 一个指针和一个二进制数字技巧;
//(3.2)ngx_epoll_init函数的调用(要在子进程中执行)
//四章,四节 project1.cpp:nginx中创建worker子进程;
//nginx中创建worker子进程
//官方nginx ,一个master进程,创建了多个worker子进程;
// master process ./nginx
// worker process
//(i)ngx_master_process_cycle() //创建子进程等一系列动作
//(i) ngx_setproctitle() //设置进程标题
//(i) ngx_start_worker_processes() //创建worker子进程
//(i) for (i = 0; i < threadnums; i++) //master进程在走这个循环,来创建若干个子进程
//(i) ngx_spawn_process(i,"worker process");
//(i) pid = fork(); //分叉,从原来的一个master进程(一个叉),分成两个叉(原有的master进程,以及一个新fork()出来的worker进程
//(i) //只有子进程这个分叉才会执行ngx_worker_process_cycle()
//(i) ngx_worker_process_cycle(inum,pprocname); //子进程分叉
//(i) ngx_worker_process_init();
//(i) sigemptyset(&set);
//(i) sigprocmask(SIG_SETMASK, &set, NULL); //允许接收所有信号
//(i) g_socket.ngx_epoll_init(); //初始化epoll相关内容,同时 往监听socket上增加监听事件,从而开始让监听端口履行其职责
//(i) m_epollhandle = epoll_create(m_worker_connections);
//(i) ngx_epoll_add_event((*pos)->fd....);
//(i) epoll_ctl(m_epollhandle,eventtype,fd,&ev);
//(i) ngx_setproctitle(pprocname); //重新为子进程设置标题为worker process
//(i) for ( ;; ) {}. .... //子进程开始在这里不断的死循环
//(i) sigemptyset(&set);
//(i) for ( ;; ) {}. //父进程[master进程]会一直在这里循环