1 概念说明
在进行解释之前,首先要说明几个概念:
用户空间和内核空间:
1 |
|
进程切换:
1 |
|
从一个进程的运行转到另一个进程上运行,这个过程中经过下面这些变化:
1 2 3 4 5 6 7 8 9 10 11 |
|
进程的阻塞:
1 |
|
文件描述符fd:
1 2 3 |
|
缓存 IO:
1 |
|
缓存 IO 的缺点:
1 |
|
2.IO模型简介
网络IO的本质是socket的读取,socket在linux系统被抽象为流,IO可以理解为对流的操作
。刚才说了,对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间
。所以说,当一个read操作发生时,它会经历两个阶段:
1 2 3 |
|
对于socket流而言:
1 2 3 |
|
网络应用需要处理的无非就是两大类问题,网络IO,数据计算
。相对于后者,网络IO的延迟,给应用带来的性能瓶颈大于后者。网络IO的模型大致有如下几种:
1 2 3 4 5 6 7 8 9 |
|
注:由于signal driven IO在实际中并不常用,所以我这只提及剩下的四种IO Model。
三、 IO模型
1. BIO – 阻塞模式I/O
用户进程从发起请求,到最终拿到数据前,一直挂起等待; 数据会由用户进程完成拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
2. NIO – 非阻塞模式I/O
用户进程发起请求,如果数据没有准备好,那么立刻告知用户进程未准备好;此时用户进程可选择继续发起请求、或者先去做其他事情,稍后再回来继续发请求,直到被告知数据准备完毕,可以开始接收为止; 数据会由用户进程完成拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
3. IO Multiplexing - I/O多路复用模型
类似BIO,只不过找了一个代理,来挂起等待,并能同时监听多个请求; 数据会由用户进程完成拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
IO复用中的三个API(select、poll和epoll)的区别和联系
1 2 3 4 5 6 7 |
|
1.select
select的第一个参数nfds为fdset集合中最大描述符值加1,fdset是一个位数组,其大小限制为__FD_SETSIZE(1024),位数组的每一位代表其对应的描述符是否需要被检查。第二三四参数表示需要关注读、写、错误事件的文件描述符位数组,这些参数既是输入参数也是输出参数,可能会被内核修改用于标示哪些描述符上发生了关注的事件,所以每次调用select前都需要重新初始化fdset。timeout参数为超时时间,该结构会被内核修改,其值为超时剩余的时间
select的调用步骤如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
总结下select的几大缺点:
1 2 3 4 5 |
|
2.poll
1 2 3 |
|
3.epoll
1 2 3 4 5 6 7 8 9 10 |
|
总结:
1 2 3 4 5 |
|
4. AIO – 异步I/O模型
发起请求立刻得到回复,不用挂起等待; 数据会由内核进程主动完成拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
抄自于:http://liuqingzheng.top/python/Python%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/25-IO%E6%A8%A1%E5%9E%8B/