15.IO多路复用
一,IO模型前戏准备
1,用户空间与内核空间
现在操作系统都采用虚拟存储器,对于32位操作系统来说,它的寻址空间(虚拟存储空间)为4G(2的32次方)
操作系统的核心为内核,独立于普通的应用程序,可以访问搜保护的内存空间,也有访问底层硬件设备的权力
为了保证用户进程不能直接操作内核,将虚拟存储空间分为两个部分,一部分为内核空间,大小为最高的1G字节,供内核使用。一部分为用户空间,大小为较低的3G字节,供各个进程使用。
2,文件描述符:
用于表述指向文件的引用的抽象化概念
在形式上是一个非负整数。实际上他是一个索引值,指向内核为每一个进程所维护的该进程打开文件记录表。
当程序打开一个新文件时,内核向进程返回会一个文件描述符
3,缓存I/O
缓存I/O又被称为标准I/O,大多数文件系统的默认I/O操作都是缓存I/O.
在LINUX的I/O中,系统会将I/O的数据缓存在文件系统的页缓存中,就是说,数据会被拷贝到操作系统内核的缓存区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。因为只有操作系统才有权限去操作硬件设备
四种IO模型:
可以通过setblocking来设置IO的类型
四种io分别为:同步IO,异步IO,阻塞IO,非阻塞IO
一个网络IO会涉及到两个系统对象,一个是调用这个IO的process,另一个就是系统内核
当一个read操作发生时,它会经历两个阶段:
1,等待数据准备
2,将数据从内核拷贝到进程中IO
阻塞IO
在linux中,默认情况下所有的socket都是阻塞
系统调用recvfrom时,一些数据还没准备好,进程就会阻塞等待数据到来,当数据准备好了,就会将数据从系统内核拷贝到进程IO中,此时进程也会进入阻塞续状态,待数据拷贝完毕后,才解除阻塞状态
非阻塞IO(同步IO)
在非阻塞IO下,系统调用recvfrom时,数剧没有准备好,就要去等待数据,这时,进程不会阻塞在这,它去执行其他任务,隔一段时间后,进程发出数据询问数据是否准备好。
如果数据没有准备好,进程继续执行其他任务。如果数据准备好了,进程就会将数据从内核拷贝到进程IO中,这时进程也会进入阻塞状态。
系统每次调用recvfrom之间,cpu的权限还在进程手中,这段时间进程是可以做其他事情的
缺陷:数据准备好后进程可能在处理其他任务,不能及时处理,存在延迟
IO多路复用(同步IO)
在有些地方又被称为事件驱动模型
当某个socket有数据到达了,就通知用户进程,具体方式如下:
当用户进程调用了select,那么整个进程就会被阻塞,同内核时会监听所有select负责的socket,当任何一个socket的中的数据准备好了,select就会返回
进程知道数据已经准备好了,再调用read()操作,将数据从内核拷贝到用户进程,此时进程会再次进入阻塞状态。
特点:可以同时监听多个socket,如果处理的连接数据不是很高那么性能不一定比使用多线程+阻塞IO高,优势在于处理更多的连接
select,poll,epoll都属于IO多路复用,IO多路复用又属于同步范畴,故:epoll只是一个伪异步
select
通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使进程可以获得这些文件描述符从而进行后续的读写操作
采用轮巡监听,查看文件描述符是否发生变化,变化将其返回。没有变化则进入睡眠
因此如果监听的文 件描述符很多,但是实际上发生变化的只有几个,轮巡方式就效率低下,
目前所有平台上支持,监听的文件描述符最大为1024个
当数据存在时,select会一直监测数据,一旦数据被内核拷贝到用户进程,即取走数据,select就停止监测
poll
因为select监听的文件描述符最大只有1024个,超过就无法监听使用select。
poll在select的基础上进行改进你,增加可以监听的文件描述符数目,轮巡方式没有改变
epoll
只告诉进程哪些哪些文件描述符刚刚变成就绪状态
不采用轮巡监听机制,监听的socket中,谁的数据准备好了,就向epoll发送信息,然后epoll直接到该socket获取数据
异步IO
进程发起操作后,就立即去做其他事情了。当数据准备完毕后内核会收到一个数据准备完毕的信息,然后内核立即返回,不会对用户进程产生任何block
然后内核会等待数据准备完成,将数据拷贝到用户内存,完成后,内核给进程发送signal,告诉他read操作完成了。

浙公网安备 33010602011771号