epoll精粹一 - Linux C++网络编程(二十三)

epoll中有两种触发模式,分别为
1、水平触发
水平触发为Level Triggered,简称LT。
水平触发关心的是缓冲区的状态,当缓冲区可读的时候,就会发出通知,也就是当缓冲区中只要有数据就会发出通知。

2、边缘触发
边缘触发为Edge Triggered,简称ET。
边缘触发关心的是缓冲区状态的变化,当缓冲区状态发生变化的时候才会发出通知,比如缓冲区中来了新的数据。

从上述表述可能不太看得出他们之间的区别,我们设想这样一个场景,当一次read()读取没有读取完缓冲区中的数据时,LT和ET的区别:
1、LT,此时缓冲区中还有数据,会继续发通知

2、ET,此时缓冲区状态并没有发生变化,并没有来新的数据,就不会发通知,在新数据到来之前,之前剩余的数据就无法取出。

所以在ET模式下,当读取数据的时候,一定要循环读取数据,直到缓冲区中的数据全部读取完成,一次性将数据取出。

一:一个更正,一个注意

更正:kqueue

注意:即将进入最重要,最核心的内容讲解;

戒骄戒躁,代码精华。简单,容易理解;大家要认真学习老师给出来的代码;

二:配置文件的修改

增加worker_connections项

三:epoll函数实战

epoll_create(),epoll_ctl(),epoll_wait();系统提供的函数调用

(3.1)ngx_epoll_init函数内容

epoll_create():创建一个epoll对象,创建了一个红黑树,还创建了一个双向链表;

连接池: 数组,元素数量就是worker_connections【1024】,每个数组元素类型为 ngx_connection_t【结构】; ---结构数组;

    为什么要引入这个数组:  2个监听套接字, 用户连入进来,每个用户多出来一个套接字;

    把 套接字数字跟一块内存捆绑,达到的效果就是将来我通过这个套接字,就能够把这块内存拿出来;

ngx_get_connection()重要函数:从连接池中找空闲连接;

a)epoll_create()  *****************

b)连接池(找空闲连接)

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进程]会一直在这里循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值