浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO

本文深入探讨了Linux epoll中Level_triggered(水平触发)与Edge_triggered(边缘触发)两种模式的区别。详细阐述了在不同场景下,这两种模式如何影响程序效率,以及阻塞IO与非阻塞IO的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本概念

我们通俗一点讲:

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

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

  • 阻塞IO:
    当你去读一个阻塞的文件描述符时,如果在该文件描述符上没有数据可读,那么它会一直阻塞(通俗一点就是一直卡在调用函数那里),直到有数据可读。当你去写一个阻塞的文件描述符时,如果在该文件描述符上没有空间(通常是缓冲区)可写,那么它会一直阻塞,直到有空间可写。以上的读和写我们统一指在某个文件描述符进行的操作,不单单指真正的读数据,写数据,还包括接收连接accept(),发起连接connect()等操作…

  • 非阻塞IO:
    当你去读写一个非阻塞的文件描述符时,不管可不可以读写,它都会立即返回,返回成功说明读写操作完成了,返回失败会设置相应errno状态码,根据这个errno可以进一步执行其他处理。它不会像阻塞IO那样,卡在那里不动!!!

设置非阻塞:

298 /*设置socket连接为非阻塞模式*/
299 void setnonblocking(int sockfd)
300 {
301     int opts = fcntl(sockfd,F_GETFL);
302     if(opts < 0)
303     {
304         perror("fcntl(sockfd,F_GETFL)\n");
305         exit(1);
306     }
307 
308     opts = (opts | O_NONBLOCK);
309     if(fcntl(sockfd,F_SETFL,opts) < 0)
310     {
311         perror("fcntl(sockfd,F_SETFL)\n");
312         exit(1);
313     }
314 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值