epoll 边沿触发(ET 模式)和水平触发(LT 模式)

(1)应用 ET 模式的目的:改变 epoll_wait 的默认属性,可以减少调用 epoll_wait 函数的调用次数。
(2)思想由来:模拟电路的高低电频的思想。
epoll 边沿触发(ET 模式)和水平触发(LT 模式)_第1张图片
水平触发: 持续的 1 持续的 0
边沿触发: 0 ->1 ;1 -> 0
(3)场景:
用 epoll 实现一个服务器,调用 epoll_wait 函数进行监听,此时 client 给 epoll 发送了 100 字节的数据,而 server 使用 read 函数读走 50 字节,剩余 50 字节,问题:epoll_wait 函数还触发么?
对于水平触发来说应该触发: 因为缓存区内还有数据没读完,你需要一直告知我。
2对于边沿触发来说不应该触发:因为 epoll_wait 的职责是告知 server 是否有读事件发生,我已经告知一次了,但是你有没有读完,你的事,我不管 。
(4)使用:默认是水平触发,若设置边沿触发,需要对监听事件的基础上加宏 EPOLLET。
(5)边沿触发实例:

#include 
#include 
#include 
#include 
#include 
#define MAXLINE 10
int main(int argc, char *argv[])
{
 int efd, i; // efd -- epoll树根,i -- 循环因子
 char buf[MAXLINE], ch = 'a';
 int pfd[2]; pipe(pfd); // 创建管道 pfd[0]--读 pfd[1]--写
 pid_t pid = fork();
 if (pid == 0) // 子进程 写操作(模拟一个客户端的操作)
{ 
    close(pfd[0]); // 关闭读端
    while (1) 
   { 
       for (i = 0; i < MAXLINE/2; i++)
       buf[i] = ch; // buf -- aaaaa
       buf[i-1] = '\n'; // buf -- aaaa\n
       ch++; // 'a'--'b'
       for (; i < MAXLINE; i++) // 从 buf[5]开始
       buf[i] = ch; //buf -- aaaa\nbbbbb
       buf[i-1] = '\n'; //buf -- aaaa\nbbbb\n
       ch++; // 'b'--'c
       write(pfd[1], buf, sizeof(buf)); // 将buf写入 管道 --- aaaa\nbbbb\n
       sleep(5);
    } // 周期的向管道内写,再写就是 cccc\ndddd\n
 close(pfd[1]);
}
else if (pid > 0) // 父进程读操作 (模拟一个服务器的操作)
{ 
 struct epoll_event event;
 struct epoll_event resevent[10]; // epoll_wait就绪返回event
 int res, len;
 close(pfd[1]); // 关闭写端
 efd = epoll_create(10); // 创建epoll红黑树根
 event.events = EPOLLIN | EPOLLET; // ET 边沿触发 -- epoll_wait只告知server一次
 // 注意:event.events = EPOLLIN; // LT 水平触发 (默认)
 event.data.fd = pfd[0];
 epoll_ctl(efd, EPOLL_CTL_ADD, pfd[0], &event); // 上树
     while (1) 
    {
         res = epoll_wait(efd, resevent, 10, -1); // 监测读端
         if (resevent[0].data.fd == pfd[0]) { // 如果管道里有数据需要读
         len = read(pfd[0], buf, MAXLINE/2); // 边沿:只读取一半 // 如果是水平触发,则全读 
         write(STDOUT_FILENO, buf, len);
    }
}
 close(pfd[0]); // 父进程读结束,关闭读端
 close(efd); // 关闭树根
} 
else 
{
 perror("fork");
 exit(-1);
 }
 return 0;
}

结果:
水平触发结果:
epoll 边沿触发(ET 模式)和水平触发(LT 模式)_第2张图片
父进程 epoll_wait 阻塞(epollt 认为没数据才是读事件结束,没有次数限制)。
epoll 边沿触发(ET 模式)和水平触发(LT 模式)_第3张图片
父进程 epoll_wait 阻塞。
边沿触发结果:
epoll 边沿触发(ET 模式)和水平触发(LT 模式)_第4张图片
父进程 epoll_wait 阻塞(epollt 认为每读一次就是读事件结束)。
epoll 边沿触发(ET 模式)和水平触发(LT 模式)_第5张图片
父进程 epoll_wait 阻塞。

你可能感兴趣的:(Linux笔记,计算机网络,网络编程,epoll,ET模式,LT模式)