IO Model

IO模型归纳

我们暂时只以网络IO为例子; 我们先从硬件层面进行流程分析:

1. 硬件层面

网卡

网卡等于一种可以接收外面数据流的一种设备;

  1. 网卡会先从网线处(或者无线)接收里面的数据
  2. 以某种方式写入到内存

其中涉及DMA,IO通路选择等硬件问题,我们暂时忽略

CPU

接着,我们都知道一般操作系统针对一些比较紧急的操作会进行中断(软,硬),当网卡来数据的时候,明显就是比较紧急的事情(如果忽略不管,就会造成内存爆炸或者数据丢失);

所以,数据从网卡接收到,会立即发送一个信号到CPU,网卡的中断程序就会被调用去处理数据;

操作系统调度

2. 模型选择

同步

  1. 阻塞:

只能有一个I/O操作;

  1. 非阻塞:

指的是 可以同时阻塞多个I/O操作,所以看做是非阻塞的

select:
  • 优点:实现简单,只用单线程执行,占用资源少,不消耗过多CPU,也可以为多客户端提供服务;

  • 缺点:每次调用都都要将fd_set从用户态copy到内核态,消耗过大; 每次调用select都要进行多次轮询; 可以检测到fd数量有限,默认是1024; 因为是水平触发,如果没有完成对一个就绪fd进行IO,下次select也会将这些fd通知到进程(只能算的是特点吧);

  • 可以看到select就是将事件的探测和响应放在一起,一旦响应过大,就会造成问题;

poll

与select区别不大,相同的是

  1. 创建fd_set,设置关注事件
  2. 调用poll(),等待事件发生;

区别:

  1. select要为读、写、异常都分别设置fd_set, poll只需要为fd设置一个即可
  2. poll由链表实现,所以无最大值

缺点: 同select一样,用户态到内核态的copy; 水平触发;

epoll

将fd交给了内核,一旦事件发生,内核负责通知; 其支持水平触发边缘触发,还有多个函数epoll_create,epoll_wait,epoll_ctl 分别为创建epoll句柄,等待事件发生,注册要监听的事件;

优点:

  • 无最大并发连接数目限制
  • 效率提升,只有活跃的fd才会callback
  • 内存是由一块用户态和内核态通过mmap()共享内存,避免频繁copy,保证了整个过程只会copy一次;

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!