io多路复用

什么是io多路复用

单线程或者单进程同时检测多个文件描述符是否可以执行io操作的能力了

解决什么问题

应用程序往往要处理多条事件流的事件,而cpu单核在同一时间只能做一件事,一种解决方式就是将cpu进行时分复用。在计算机系统中,我们用线程和进程来表示一条执行流,通过不同的线程和进程在操作系统内部的调度,来做到对cpu的时分复用。
线程/进程有几个成本

  1. 线程/进程创建成本
  2. cpu切换不同的线程/进程成本
  3. 多线程的资源竞争
    io多路复用的解决本质就是用更少的资源完成更多的事

linux的io处理模型

  1. 阻塞io
  2. 非阻塞io
  3. io多路复用
  4. 信号驱动io
  5. 异步io

阻塞io

这是最常用的简单的io模型。阻塞io意味着当我们发起一次io操作后,要一直等待成功或者失败后才返回,在这期间程序不能做任何其他的事情。阻塞io只能对单个文件描述符进行操作,如read和write。

非阻塞io

我们发起io时,通过对文件描述符设置O_NONBLOCKE flag来指定该文件描述符的io操作为非阻塞。非阻塞io通常发生在一个for虚幻中,,因为每次进行io操作时,要么io操作成功,要不io操作会阻塞时返回错误EWOULDBLOCK/EAGAIN,然后再根据需要进行下一次for循环操作,这种类似轮询的方式会浪费很多不必要的cpu资源。和阻塞io一样,非阻塞io也是通过read和write来进行操作的,也只能对单个描述符进行操作

IO多路复用

有三种方式selelct/poll/epoll,他们的共同点:首先都会对一组文件描述符进行相关事件的注册,然后阻塞以等待某些事件发生或者等待超时。对于三种机制而言,不同数量的文件描述符对性能的影响是不同的

信号驱动io

信号驱动io是利用信号机制,让内核告诉应用程序文件描述符的相关事件。但在网络环境中 ,和socket相关的读写事件太多了,我们没有办法在sigio对应的信号处理函数中区分不同的事件,sigio只能在io事件单一的情况下使用,比如监听端口的socket,因为只有客户端发起新的链接的时候才会产生sigio信号

异步io

异步io和信号驱动io差不多,不一样的地方是:它相比较信号驱动io需要在程序中完成数据从用户态到内核态(或者反方向)的copy,异步io把copy这一步完成后,再通知应用程序。我们使用的事aio_read和aio_write
同步io和异步io

  1. 同步io指的是程序会一直阻塞程序到io操作如read或者write完成
  2. 异步io指的是哦操作不会当前程序的继续执行

io多路复用的方案

select

select的方法有select pselect FD_CLR FD_ISSET FD_SET FD_ZERO
select的调用会阻塞到有文件描述符可以进行io操作或者被信号打断或者超时才会返回
select将监听三种不同的需要进行的io操作。readfds是需要进行读操作的文件描述符,writefds是需要进行写操作的文件描述符,exceptfds是需要进行异常处理的文件描述符。这三个参数通过返回null来表示不需要监听
当select返回的时候,都会进行select过滤,只会留下需要进行io的文件描述符
FD_XX 系列的函数是用来操作文件描述符组合文件描述符的关系
FD_ZERO 用来清空文件描述符组,每次调用select都需要清空一次
FD_SET 用来将一个文件添加到文件描述符组里
FD_CLR 用来将一个文件描述符移除文件描述符组
FD_ISSET 检测一个文件描述符是否在组中,用来检测那些文件描述符可以进行io操作
select 可同时监听的文件描述符数量可以通过FS_SETSIZE来限制的,在linux中是1024,但是是可以设置的,但随着这个数的增加,效率会降低.pselect 和select 大体是一样的,有些细节上的区别

poll

poll的函数有 poll/ppoll/pollfd(fd, events, revents)
和select的三组文件描述符组不同的是,poll只有一个pollfd数组,每个元素都表示一个需要监听io操作事件的文件描述符。events是我们需要关心的事件,revents是内核检测到的事件。

epoll

epoll的函数有 epoll_create/epoll_create1/epoll_ctl/epoll_wait/epoll_pwait
epoll_create/epoll_create1 用来创建一个epoll实例,epoll_ctl用来添删改要检测的文件描述符,epoll_wait用来阻塞等待可以执行的io直到超时

level-triggerd and edge-triggerd

level-triggerd表示只要有io操作可以进行,比如某个文件描述符有数据可读,每次调用epoll_wait都会通知程序可以进行io操作
edge-triggerd表示只有文件描述符发生状态变化的时候,调用epoll_wait,会通知应用程序可以进行io操作,如果第一次没有全部读完数据,第二次没有新数据进入,则不会返回可读。
select和poll都是level-trigger , epoll是两种可选

原文

https://gocn.vip/topics/10090

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值