Socket

1. 五种 IO 模型的特点以及比较
1.1 阻塞式 IO
1.2 非阻塞式 IO
1.3 信号驱动型 IO
1.4 IO 复用
1.5 异步 IO
1.6 五大 IO 模型的比较

1. 五种IO模型的特点以及比较

IO 模型

一个输入操作通常包含两个阶段:

  • 等待数据准备好
  • 从内核向进程中复制数据

对于一个套接字上的输入操作,第一步通常涉及数据从网络中到达。当所有数据到达时,它被复制到 内核中 的某个缓冲区。第二步就是把数据从 内核缓冲区 复制到 进程缓冲区

1.1阻塞式IO

[外链图片转存失败(img-DWI6UQxq-1564908532128)(https://camo.githubusercontent.com/ea516be001cb380af6b8f841248eca52dcb03ff2/68747470733a2f2f67697465652e636f6d2f437943323031382f43532d4e6f7465732f7261772f6d61737465722f646f63732f706963732f313439323932383431363831325f342e706e67)]
应用进程被阻塞,直到数据从内核缓冲区复制到 应用进程缓冲区 中才返回
应该注意到,在阻塞的过程中,其它应用进程还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其它应用进程还可以执行,所以 不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。

1.2非阻塞式IO

[外链图片转存失败(img-aO6yXVts-1564908532129)(https://camo.githubusercontent.com/4c7b0161f0838856e7f1a8889c4341fbebd5c65d/68747470733a2f2f67697465652e636f6d2f437943323031382f43532d4e6f7465732f7261772f6d61737465722f646f63732f706963732f313439323932393030303336315f352e706e67)]
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为 轮询(polling)。

由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率比较低。

1.3信号驱动型IO

[外链图片转存失败(img-iyYu9XHu-1564908532130)(https://camo.githubusercontent.com/743b17eeab3acfd21ebc14ca6df6e4863dfcdd7b/68747470733a2f2f67697465652e636f6d2f437943323031382f43532d4e6f7465732f7261772f6d61737465722f646f63732f706963732f313439323932393535333635315f372e706e67)]
应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。
相比于非阻塞式 I/O 的轮询方式,信号驱动 I/O 的 CPU 利用率更高

1.4IO复用(select、poll、epoll)

[外链图片转存失败(img-feCyL5Ak-1564908532130)(https://camo.githubusercontent.com/2c9ab066c0b386e4dfbf2e9eaf23229e131b8525/68747470733a2f2f67697465652e636f6d2f437943323031382f43532d4e6f7465732f7261772f6d61737465722f646f63732f706963732f313439323932393434343831385f362e706e67)]
使用 select 或者 poll 等待数据,并且可以等待 多个套接字 中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。
如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。

1.5异步IO

[外链图片转存失败(img-dzvV8K5f-1564908532130)(https://camo.githubusercontent.com/591d617c1458a4f406de6d0cd21ed025d797b5e5/68747470733a2f2f67697465652e636f6d2f437943323031382f43532d4e6f7465732f7261772f6d61737465722f646f63732f706963732f313439323933303234333238365f382e706e67)]
应用进程执行 aio_read 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。

1.6五大IO模型的比较
  • 同步 I/O:将数据从 内核缓冲区 复制到 应用进程缓冲区 的阶段,应用进程会阻塞。
  • 异步 I/O:不会阻塞。

阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O 都是同步 I/O,它们的主要区别在第一个阶段。
非阻塞式 I/O 、信号驱动 I/O 和异步 I/O 在第一阶段不会阻塞。

2. slect、poll、epoll 的原理、比较、以及使用场景;epoll 的水平触发与边缘触发

2.1slect 和 poll 的比较
  1. 功能

    • select 会修改描述符,而 poll 不会;
    • select 的描述符类型使用 数组 实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用 链表 实现,没有描述符数量的限制;
    • poll 提供了更多的 事件类型 ,并且对描述符的重复利用上比 select 高。
    • 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。
  2. 速度(select 和 poll 都比较慢)

    • select 和 poll 每次调用都需要将全部描述符从 应用进程缓冲区 复制到 内核缓冲区
    • select 和 poll 的返回结果中没有声明哪些描述符已经准备好,所以如果返回值大于 0 时,应用进程都需要使用 轮询 的方式来找到 I/O 完成的描述符。
  3. 可移植性

    • 几乎所有的系统都支持 select
    • 只有比较新的系统才支持 poll
2.3epoll

epoll_ctl() 用于向内核注册新的描述符或者是改变某个文件描述符的状态。已注册的描述符在内核中会被维护在一棵 红黑树上,通过回调函数内核会将 I/O 准备好的描述符加入到一个 链表 中管理,进程调用 epoll_wait() 便可以得到事件完成的描述符。
从上面的描述可以看出,epoll 只需要将描述符从 进程缓冲区内核缓冲区 拷贝一次,并且进程 不需要 通过 轮询 来获得事件完成的描述符。
epoll 仅适用于 Linux OS。

2.4 应用场景
select:

select 的 timeout 参数精度为 1ns,而 poll 和 epoll 为 1ms,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。
select 可移植性更好,几乎被所有主流平台所支持。

poll

poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。

epoll

只需要运行在 Linux 平台上,有大量的 描述符 需要同时轮询,并且这些连接最好是 长连接

需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势

需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在 内核 中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。

参考资料

1. CyC2018 大佬的 Github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值