epoll 的边缘触发与水平触发

水平触发

  1. 对于读操作:只要缓冲内容不为空,LT模式返回读就绪。
  2. 对于写操作:只要缓冲区还不满,LT模式会返回写就绪。
#include 
#include 
#include 

int main()
{
     
    int epfd, nfds;
    char buf[256];
    struct epoll_event event, events[5];
    epfd = epoll_create(1);
    event.data.fd = STDIN_FILENO;
    event.events = EPOLLIN;  // LT是默认模式
    epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
    while (1) {
     
        nfds = epoll_wait(epfd, events, 5, -1);
        int i;
        for (i = 0; i < nfds; ++i) {
     
            if (events[i].data.fd == STDIN_FILENO) {
     
                read(STDIN_FILENO, buf, 1);
                printf("hello world\n");
            }
        }
    }
}
# ./a.out 
a
hello world
hello world
ab
hello world
hello world
hello world
abc
hello world
hello world
hello world
hello world

边缘触发

  1. 对于读操作
    (1)当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。
    (2)当有新数据到达时,即缓冲区中的待读数据变多的时候。
    (3)当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。

  2. 对于写操作
    (1)当缓冲区由不可写变为可写时。
    (2)当有旧数据被发送走,即缓冲区中的内容变少的时候。
    (3)当缓冲区有空间可写,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLOUT事件时。

#include 
#include 
#include 

int main()
{
     
    int epfd, nfds;
    struct epoll_event event, events[5];
	char buf[256];

    epfd = epoll_create(1);
    event.data.fd = STDIN_FILENO;
    event.events = EPOLLIN | EPOLLET;
    epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
    while (1) {
     
        nfds = epoll_wait(epfd, events, 5, -1);
        int i;
        for (i = 0; i < nfds; ++i) {
     
            if (events[i].data.fd == STDIN_FILENO) {
     
				read(STDIN_FILENO, buf, 1);
                printf("hello world\n");
            }
        }
    }
}
# ./a.out 
a
hello world
ab
hello world
abc
hello world

浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO_杨氏计算机知识整理-CSDN博客_epoll水平和边缘触发

Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上次没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!

        Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!

猜你喜欢

转载自blog.csdn.net/abc1231987/article/details/121324330