文章目录

  • 什么是LT和ET?
    • LT(Level Trigger)模式:
    • ET(Edge Trigger)模式:
    • 得出结论,ET模式的工作效率要比LT高,因为ET模式降低了同一事件被重复触发的次数
      • 实验代码:
      • 实验结果
          • 客户端通过telnet连接服务器端
        • LT工作模式
        • ET工作模式
        • 验证结论
        • makefile 代码

什么是LT和ET?

LT(Level Trigger)模式:

LT模式是默认的一个工作模式,在这种模式下epoll相当与一个效率较高的poll。当epoll_wait检测到有事件发生时,并将此事件通知给应用程序去处理,此时应用程序可以选择不处理该事件,而未被处理完全的事件epoll_wait重复通告应用程序,直至应用程序被处理。

ET(Edge Trigger)模式:

ET模式则是epoll的高效工作模式,在此模式下,ET模式则和LT模式相反,epoll_wait检测到有事件发生时,并将此事件通知给应用程序,此时应用程序必须处理该事件,因为ET模式下的epoll_wait很傲娇,只会将是将通知应用程序一次,而不会像LT模式那样反复提醒。如果ET模式应用程序不处理该事件的话,则该事件的数据日后就处理不到了

得出结论,ET模式的工作效率要比LT高,因为ET模式降低了同一事件被重复触发的次数

实验代码:

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include<stdlib.h>
#include<sys/epoll.h>
#include<stdbool.h>
#include <libgen.h>
#define MAX_EVENT_NUMBER 1024 //可注册的事件最大数量
#define BUFFER_SIZE 10 //socket缓冲区的大小,可以调整
//设置文件描述符是非阻塞的
int setnonblocking(int fd){int old_option = fcntl(fd,F_GETFL);int new_option=old_option|O_NONBLOCK;fcntl(fd,F_SETFL,new_option);return old_option;
}
//将文件描述符fd上的EPOLLIN注册到epollfd指示的epoll内核事件表中
void addfd(int epollfd,int fd,bool enable_et){struct epoll_event event;// epoll_event事件结构体event.data.fd=fd;event.events= EPOLLIN; if(enable_et){event.events|=EPOLLET;//注册EPOLLET事件}epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);//注册语句setnonblocking(fd);//设置文件描述符是非阻塞的
}
//LT模式的具体工作流程
void lt(struct epoll_event* events,int number,int epollfd,int listenedfd){char buf[BUFFER_SIZE];//用户接收区for(int i=0;i<number;i++){//遍历epll_event取出触发的事件int sockfd=events[i].data.fd;//每一个事件都绑定了一个文件描述符,详细请查看epoll_event结构体if(sockfd==listenedfd){//若事件文件描述符是监听socket,意味着有连接请求,那么将连接文件描述符注册到epoll事件表中struct sockaddr_in client_address;socklen_t client_addrlength=sizeof(client_address);int connfd=accept(listenedfd,(struct sockaddr*)&client_address,&client_addrlength);addfd(epollfd,connfd,false);//该连接文件描述符使用LT模式}else if(events[i].events&EPOLLIN){//LT模式核心代码//只要sockfd上的数据没有被完全读出,那么这段代码就会被重复触发,直到数据被读完后关闭sockfdprintf("event trigger once\n");memset(buf,'\0',BUFFER_SIZE-1);int ret = recv(sockfd,buf,BUFFER_SIZE-1,0);//从缓冲区接受数据if(ret<=0){//无数据了可以关闭连接文件描述符close(sockfd);continue;}  printf("get %d bytes of content :%s\n",ret,buf);}else{printf("something else happened\n");}}
}
//ET模式具体工作流程
void et(struct epoll_event* events,int number,int epollfd,int listenfd){char buf[BUFFER_SIZE];for(int i=0;i<number;i++){//遍历epoll_event数组int sockfd = events[i].data.fd;if(sockfd==listenfd){struct sockaddr_in client_address;socklen_t client_addrlength=sizeof(client_address);int connfd = accept(listenfd,(struct sockaddr*)& client_address,&client_addrlength);addfd(epollfd,connfd,true);//将连接文件描述符上的EPOLLIN注册到epoll指示的epoll内核时间表中,true表示开启ET模式}else if(events[i].events&EPOLLIN){printf("event trigger once\n");while(1){//ET核心代码//该段代码只会触发一次,因此需要循环读入数据保证socket读缓冲区的数据全部被读出,不然数据会丢失memset(buf,'\0',BUFFER_SIZE);int ret = recv(sockfd,buf,BUFFER_SIZE-1,0);  if(ret<0){//该条件说明数据被全部读出,此后epoll就能再次触发EPOLLIN事件,以驱动下一次读操作if((errno==EAGAIN)||(errno==EWOULDBLOCK)){printf("read later\n");break; }close(sockfd);break;                   }else if(ret==0){close(sockfd);}else{printf("get %d bytes of content: %s\n",ret,buf);} }}else{printf("something else happpened \n");}}
}int main(int argc,char* argv[]){if(argc<=2){printf("usae: %s ip_address port_number\n",basename(argv[0]));return 1;}
/*建立socket服务器 创建->命名->监听*/const char* ip = argv[1];int port = atoi(argv[2]);/*创建socket号(ip地址+端口号)*/int ret=0;struct sockaddr_in address;address.sin_family=AF_INET;inet_pton(AF_INET,ip,&address.sin_addr);address.sin_port=htons(port);/*创建socket*/int listened = socket(PF_INET,SOCK_STREAM,0);assert(listened>=0);/*命名为socket绑定socket号*/ret=bind(listened,(struct sockaddr*)&address,sizeof(address));assert(ret!=-1);/*监听socket*/ret=listen(listened,5);assert(ret!=-1);
/*建立socket服务器 创建->命名->监听*/struct epoll_event events[MAX_EVENT_NUMBER];//存储事件的数组int epollfd=epoll_create(5);//创建epoll注册表assert(epollfd!=-1);addfd(epollfd,listened,true);//注册文件描述符上发生的EPOLLIN事件到内核事件表中,true表示启动ET模式while(1){int ret = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);//调用epoll_wait等待事件发生,ret为返回事件的个数,events为存储触发事件的数组if(ret<0){printf("epooll failure\n");break;    }lt(events,ret,epollfd,listened);//使用lt工作模式//et(events,ret,epollfd,listened);//使用et工作模式 }close(listened);return 0;
}

实验结果

客户端通过telnet连接服务器端

LT工作模式

ET工作模式

验证结论

通过实验结果可以看到,两个模式处理相同字节的数据包,ET模式触发两次,LT模式触发了六次,ET模式确实比LT模式效率高,我认为效率高的原因是因为ET模式使得应用程序当天事情当天做,不给应用程序拖延症

makefile 代码

main:test.ogcc test1.o -o main -std=c99;
test.o:test1.cgcc -c test1.c -std=c99;
clean:rm -rvf ./*.o main;

操作文件操作符的工作模式:LT(电平触发)ET(边缘触发)实验对比相关推荐

  1. 移除类名没有触发transition_epoll边缘触发模式

    epoll(kqueue),支持两种事件触发模式.水平触发以及边缘触发. epoll实际可以监听多种描述符,下文主要以套接字介绍,并且假设同时注册了读/写. 水平触发:只要套接字可读/可写epollw ...

  2. epoll哪些触发模式_5.epoll的水平触发和边缘触发

    本篇是多路复用的第五篇,主要来讲解epoll的水平触发和边缘触发是怎么回事. 一.概念介绍 EPOLL事件有两种模型,水平出发和边缘触发,如下所示: 1. Level Triggered (LT) 水 ...

  3. 外部中断----高低电平触发,(边沿触发)上升沿触发和下降沿触发区别

    外部中断可以分为电平触发和边缘触发两种,那么这两种中断有什么区别,我们今天讲解下 1什么是中断 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生): CPU暂时中断当前的工作, ...

  4. 高低电平触发,(边沿触发)上升沿触发和下降沿触发 中断区别

    外部中断可以分为电平触发和边缘触发两种,那么这两种中断有什么区别.中断基本概念是: CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生): CPU暂时中断当前的工作,转去处理事件 ...

  5. 五种高级IO | select poll epoll 水平触发模式 边缘触发模式 惊群问题

    一.高级IO 在介绍多路复用IO之前,先介绍一下其它四种高级IO: 阻塞IO: 在内核将数据准备好之前,系统调用会一直等待.所以的套集字默认是阻塞方式. 非阻塞IO: 在内核还未将数据准备好,则系统调 ...

  6. 边沿触发是什么意思_epoll边缘触发模式

    epoll(kqueue),支持两种事件触发模式.水平触发以及边缘触发. epoll实际可以监听多种描述符,下文主要以套接字介绍,并且假设同时注册了读/写.水平触发:只要套接字可读/可写epollwa ...

  7. seaweedfs上传文件为什么要先申请文件号?(/dir/assign)(两种工作模式:Volume模式与Filer模式)(seaweed上传文件)

    文章目录 SeaweedFS两种工作模式 Volume模式 Filer模式 总结 SeaweedFS两种工作模式 SeaweedFS是一个分布式文件系统,它有两种模式:Volume模式和Filer模式 ...

  8. linux文件编辑器的三种模式,Linux中文本编辑器三种工作模式切换及vi编辑器三种工作模式下命令详解...

    文本编辑器的作用 创建或修改文本文件 维护Linux系统中的各种配置文件 Linux中最常用的文本编辑器 Linux中最常用的文本编辑器 vi:类UNIX操作系统的默认文本编辑器 vim:vim时vi ...

  9. 【Vim】学习笔记四 多文件编辑、可视模式、视窗操作

    文章目录 1. 多文件编辑 (1) 使用vim编辑多个文件 (2) 进入vim后打开新文件 (3) 恢复文件 2. 可视模式命令简介 3. 视窗操作 (1) 视窗操作简介 4. 创建加密文档 5. 在 ...

最新文章

  1. dpi shell命令 安卓_android 中 dumpsys 命令使用
  2. 20 个 jQuery 超酷视觉效果构建教程推荐
  3. 快速排序的实现及优化
  4. 报告分析|2021移动社交行业有哪些新风向?
  5. Vue进行格式化时间Y-m-d h:m:s
  6. 安卓JNI使用C++类
  7. 【转】C#运算符重载**
  8. 深度学习基础 | 超详细逐步图解 Transformer
  9. 虚拟机才是 Kubernetes 的未来?
  10. react 打包体积过大_解决 webpack 打包文件体积过大
  11. 解决安卓手机上软键盘弹出挤压背景的问题
  12. Ionic系列——调用系统电话
  13. 时间字符串以及时间戳解析
  14. Java项目中使用OpenOffice转PDF
  15. chrome浏览器安装包点击无反应
  16. auc是ROC曲线面积的直观理解
  17. BUG记录:org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is no
  18. 汇编语言必看书籍推荐
  19. .Net框架设计(Yanlz+Unity+XR+C#+.Net+框架+框架设计+设计模式+工具可视化+SOA+立钻哥哥+==)
  20. IOS 音乐播放器 (附源码)

热门文章

  1. Java学习之正则表达式篇
  2. TexturePacker破解版
  3. 【分享】成功将Thinkpad E40 0578M59更换无线网卡AR9280
  4. 安装MinGW-w64
  5. 国内各类 WebShell 密码大全 爆破、社工用 webshell-password
  6. 关于Unity3d 2020所有国外版本下载(2020.3.0f1以前)
  7. windows电脑系统优化
  8. 解决:RuntimeError: Expected object of scalar type Int but got scalar type Double
  9. Excel根据内容自动调整行高和列宽
  10. 使用STM32F4浮点运算(FPU)功能开启+使用DSP库