彻底学会使用epoll(三)——ET的读操作实例分析

news/2024/7/8 3:02:30

首先看程序一,这个程序想要实现的功能是当用户从控制台有任何输入操作时,输出hello world!

程序一

  

点击(此处)折叠或打开

  1. #include unistd.h>
  2. #include iostream>
  3. #include sys/epoll.h>
  4. using namespace std;
  5. int main(void)
  6. {
  7.     int epfd,nfds;
  8.     struct epoll_event ev,events[5];//ev用于注册事件,数组用于返回要处理的事件
  9.     epfd=epoll_create(1);//只需要监听一个描述符——标准输入
  10.     ev.data.fd=STDIN_FILENO;
  11.     ev.events=EPOLLIN|EPOLLET;//监听读状态同时设置ET模式
  12.     epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&ev);//注册epoll事件
  13.     for(;;)
  14.    {
  15.      nfds=epoll_wait(epfd,events,5,-1);
  16.      for(int i=0;infds;i++)
  17.      {
  18.         if(events[i].data.fd==STDIN_FILENO)
  19.            cout"hello world!"endl;
  20.      }
  21.    }
  22. }

运行结果:

程序一中对标准输入的监听使用ET模式,结果实现了我们想要的功能。那么实际原理是如何呢,我们将过程分析一下:

(1) 当用户输入一组字符,这组字符被送入buffer,字符停留在buffer中,又因为buffer由空变为不空,所以ET返回读就绪,输出hello world!

(2) 之后程序再次执行epoll_wait,此时虽然buffer中有内容可读,但是根据我们上节的分析,ET并不返回就绪,导致epoll_wait阻塞。(底层原因是ET下就绪fd的epitem只被放入rdlist一次)。

(3) 用户再次输入一组字符,导致buffer中的内容增多,根据我们上节的分析这将导致fd状态的改变,是对应的epitem再次加入rdlist,从而使epoll_wait返回读就绪,再次输出“hello world!”。

 我们在看看LT的情况如何,将程序以下修改:

    ev.events=EPOLLIN;//默认使用LT模式

运行结果:

结果正如我们所料,程序出现死循环,因为用户输入任意数据后,数据被送入buffer且没有被读出,所以LT模式下每次epoll_wait都认为buffer可读返回读就绪。导致每次都会输出hello world!。下面在看程序二。

程序二


点击(此处)折叠或打开

  1. #include unistd.h>
  2. #include iostream>
  3. #include sys/epoll.h>
  4. using namespace std;
  5. int main(void)
  6. {
  7.     int epfd,nfds;
  8.     char buf[256];
  9.     struct epoll_event ev,events[5];//ev用于注册事件,数组用于返回要处理的事件
  10.     epfd=epoll_create(1);//只需要监听一个描述符——标准输入
  11.     ev.data.fd=STDIN_FILENO;
  12.     ev.events=EPOLLIN;//使用默认LT模式
  13.     epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&ev);//注册epoll事件
  14.     for(;;)
  15.    {
  16.      nfds=epoll_wait(epfd,events,5,-1);
  17.      for(int i=0;infds;i++)
  18.      {
  19.        if(events[i].data.fd==STDIN_FILENO)
  20.        {
  21.           read(STDIN_FILENO,buf,sizeof(buf));//将缓冲中的内容读出
  22.           cout"hello world!"endl;
  23.        }
  24.     }
  25.   }
  26. }

运行结果:

程序二依然使用LT模式,但是每次epoll_wait返回读就绪的时候我们都将buffer(缓冲)中的内容read出来,所以导致buffer再次清空,下次调用epoll_wait就会阻塞。所以能够实现我们所想要的功能——当用户从控制台有任何输入操作时,输出hello world!。我们再来看看程序三。

程序三


点击(此处)折叠或打开

  1. int main(void)
  2. {
  3.     int epfd,nfds;
  4.     struct epoll_event ev,events[5];//ev用于注册事件,数组用于返回要处理的事件
  5.     epfd=epoll_create(1);//只需要监听一个描述符——标准输入
  6.     ev.data.fd=STDIN_FILENO;
  7.     ev.events=EPOLLIN|EPOLLET;//使用默认LT模式
  8.     epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&ev);//注册epoll事件
  9.     for(;;)
  10.    {
  11.      nfds=epoll_wait(epfd,events,5,-1);
  12.      for(int i=0;infds;i++)
  13.      {
  14.        if(events[i].data.fd==STDIN_FILENO)
  15.         {
  16.           cout"hello world!"endl;
  17.           ev.data.fd=STDIN_FILENO;
  18.           ev.events=EPOLLIN|EPOLLET;//使用默认LT模式
  19.           epoll_ctl(epfd,EPOLL_CTL_MOD,STDIN_FILENO,&ev);//重新MOD事件(ADD无效)
  20.         }
  21.      }
  22.    }
  23. }

程序三依然使用ET,但是每次读就绪后都主动的再次MOD IN事件,我们发现程序再次出现死循环,也就是每次返回读就绪。这就验证了上一节讨论ET读就绪的第三种情况。但是注意,如果我们将MOD改为ADD,将不会产生任何影响。别忘了每次ADD一个描述符都会在epitem组成的红黑树中添加一个项,我们之前已经ADD过一次,再次ADD将阻止添加,所以在次调用ADD IN事件不会有任何影响。


http://www.niftyadmin.cn/n/3497434.html

相关文章

WitKey(威客)将是SaaS的一个重要分支 -

SaaS的未来将是Service as a Software,将‘服务’产品化。 WitKey(威客)理论聚集于‘知识’这一特殊的‘服务’类型,而目前互联网尚未给予‘知识服务’以充分的‘价格’特性,严重忽视了其价值。 而事实上,仅…

jvm间歇性崩溃分析

http://www.cnblogs.com/LBSer/p/4417148.html 1 问题描述 某服务有两台机器,每隔几天会报警load高,一开始看监控发现gc时间抖动很大,以为是发生了fullgc引起卡顿而未加注意,之后登入线上机器查看日志发现是jvm崩溃导致了服务…

oracle自治事务的写法_Oracle自治事务实际用例

如下,新建两个存储过程:在主自治事务中,我们插入一条记录,然后在自治事务中,查看表中行数,然后尝试插入三条记录,查看行数,最后rollback 查看行数,最后返回主事务&#x…

2021年10月记录(原生sql分页)

1.[转]C# 中的.pdb/ .vshost.exe/ .vshost.exe.manifest文件讨论[转]C# 中的.pdb/ .vshost.exe/ .vshost.exe.manifest文件讨论 - 紫痕o - 博客园 pdb文件: 英文全称:Program Database File 中文全称:程序数据库 文件 Debug里的PDB是full…

iOS presentViewController 跳转黑屏现象解析

在利用stroyboard开发,有时候利用 TestViewController *control[[TestViewController alloc]init]; [self presentModalViewController:control animated:YES];来进行跳转的时候,有时候跳过去是黑屏,但是传输过去的数据可以通过log打印出来&a…

最近发生了真多不可思意的事情

先是最近最热门的“三鹿奶粉事件”让人感觉一些企业的没有良知,然而万万没有想到的是,居然会牵扯出全国上上下下的奶粉企业,甚至包括猛牛、伊利、雅士利这样的牌子,而且还称之为"行业规则“!而每每想到自己从小吃…

一招解决OFFICE word各种崩溃问题

%appdata%\microsoft\templates 有的时候点击miscrosoft office word的时候会出现错误,之后提示安全模式打开等等情况,打不开是因为“normal.dot”这个文件在作怪,有时候你去网上搜,人家会告诉你把这个文件删掉,之后给…

mongodb数据库扩展名_MongoDB数据库

MongoDBMongoDB是一款强大、灵活、且易于扩展的通用型数据库。1、易用性MongoDB是一个面向文档(document-oriented)的数据库,而不是关系型数据库。不采用关系型主要是为了获得更好得扩展性。当然还有一些其他好处,与关系数据库相比,面向文档的…