阻塞模式

  • 发生I/O系统调用如果阻塞,进程会被挂起。
    下面的各种模式都是为了解决阻塞模式带来的CPU消耗等问题

非阻塞模式

  • 发生I/O系统调用如果阻塞,返回 -1errno == EWOULDBLOCK.
    根据 Everything is a fileunix的设计哲学,通过 fcntlfd 操作,设置其为非阻塞模式。

I/O多路复用

  • 具体的实现有( select, epoll, kqueue, etc. )用一个线程对一系列的文件描述符遍历,通过文件操作方法 poll 来获得当前的状态,poll 的实现是由相应的 I/O驱动程序实现的。

    如此就可以获得文件描述符的相应状态了。

epoll 效率高的原因

  • 不需要每次将文件描述符从用户空间复制到内核空间,只需一次。
  • 采用边缘触发模式,每当文件描述符状态发生改变,可以在 O(1) 时间内唤醒相应的回调函数。

水平触发,边缘触发

select 只支持水平触发,epoll 支持水平触发和边缘触发。

水平触发(LT,Level Trigger):当文件描述符就绪时,会触发通知,如果用户程序没有一次性把数据读/写完,下次还会发出可读/可写信号进行通知。

边缘触发(ET,Edge Trigger):仅当描述符从未就绪变为就绪时,通知一次,之后不会再通知。

区别:边缘触发效率更高,减少了事件被重复触发的次数,函数不会返回大量用户程序可能不需要的文件描述符。

  • 但使用边缘触发时一定要使用非阻塞模式,因为处理程序只会被唤醒一次当文件描述符的状态发生改变时,我们需要进行多次读操作来获取完整的数据,如果没有数据时非阻塞模式就会 -1 errno == EWOULDBLOCK ,而阻塞模式就会将线程悬挂。
  • 使用水平触发时如果是非阻塞模式,我们可以循环读数据直到 -1 errno == EWOULDBLOCK ,如果是阻塞模式,就要由 select 等的多路复用来判断文件描述符的状态,以免发生线程悬挂。
  • 材料1
  • 材料2
posted on 2025-03-03 23:27  嗯嗯好傅  阅读(21)  评论(0)    收藏  举报