操作系统的IO模型有哪些?
- 操作系统中的IO模型
- 逐一拓展
- 同步阻塞IO模型
- 同步非阻塞IO模型
- IO复用模型
- 信号驱动IO模型
- 异步IO模型
操作系统中的IO模型
为了保护操作系统的安全,通过缓存加快系统读写,会将内存分为用户空间和内存空间两个部分。如果用户想要操作内核空间的数据,则需要把数据从内核空间拷贝到用户空间(数据会放到内核空间的page cache中,这种也叫做缓存IO)。
举个栗子:
如果服务器收到了从从客户端过来的请求,并且想要进行处理,那么需要经过这几个步骤:
- 服务器的网络驱动接收到消息之后,向内核申请空间,并在收到完整的数据包(这个过程会产生延时,原因是有可能是通过分组传送过来的)后,将其复制到内核空间;
- 数据从内核空间拷贝到用户空间;
- 用户程序进行处理
我们再详细的探究服务器中的文件读取,对于Linux来说,Linux是一个将所有的外部设备都看作是文件来操作的操作系统,在它看来:everything is a file,那么我们就把对外部设备的操作都看作是对文件进行操作。而且,我们对一个文件进行读写,都需要通过调用内核提供的系统调用。
而在Linux中,一个基本的IO会涉及到两个系统对象:一个是调用这个IO的进程对象(用户进程),另一个是系统内核。也就是说,当一个read操作发生时,将会经历以下阶段:
- 通过read系统调用,向内核发送读请求;
- 内核向硬件发送读指令,并等待读就绪;
- DMA把将要读取的数据复制到指令的内核缓冲区;
- 内核将将数据从内核缓冲区拷贝到用户进程空间中;
正是由于上面的几个阶段,导致了file中的数据被用户进程消费是需要过程的,这也就是延伸出了5中IO方式,分别是同步阻塞型IO模型、同步非阻塞型IO模型、IO复用模型、信号驱动模型、以及异步IO模型。
逐一拓展
通过一个例子来分别说明这五种IO模型:
eg:假设小A需要去社保局柜台办事,拿号排队的例子
同步阻塞IO模型
**从系统调用recv到将数据从内核复制到用户空间并返回,在这段时间内进程始终阻塞。**就相当于,小A想去柜台办理业务,假如现在柜台业务繁忙,他也要排队,直到排到他办理完业务,才能去做别的事情。显然,这个IO模型是同步且阻塞的。
同步非阻塞IO模型
在这里recv不管有没有获得到数据都要返回,如果没有数据的话就过段时间再调用recv来看一看,如此循环。 就像是小A来柜台办理业务,发现柜员休息,挂出来暂停服务的牌子,这个时间小A就离开了,小A出去买了一根火腿肠吃上一吃,吃完小A就又回来看看柜员开始营业了没有,直到终于碰到柜员营业了,这才办理业务。我们可以看到,在小A中间离开的这段时间,他可以做自己的事情。回到正题,但是这个模型只有在检查无数据的时间是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(办理业务),因此它还是同步IO。
IO复用模型
在IO复用模型中,调用recv之前会先调用select或者poll,这两个系统调用都可以在内核准备好数据(网络数据已经到达内核了)时告知用户进程,它准备好了,这个时候再调用recv时是一定有数据的。因此,在这个模型中,进程阻塞于select或者poll,而没有阻塞在recv上。 就相当于,小A来柜台办理业务,大厅保安告诉他,现在没有空闲的柜台,所有柜台都有人在办理业务,等有空位的时间会告诉他。于是小A就等呀等(select或者poll调用中……),过了一会大厅保安告诉他有柜台空闲出来了,可以办理业务了,但是具体是几号柜台,你自己去找一下吧,于是小A就只能挨个柜台找呀找。
信号驱动IO模型
此处会通过调用sigaction注册信号函数,在内核数据准备好的时候,系统就会中断当前程序,执行信号函数(在这里调用recv)。 相当于,小A让大厅保安在柜台有空位的时候通知他(注册信号函数),等没多久大厅保安通知他,因为他是人才,所以专门给他开了一个柜台来办理业务,小A就去特席柜台办理业务了,但即使在等待的过程中是非阻塞的,但在业务办理的过程中依然是同步的。
异步IO模型
调用aio_read指令,内核把数据准备好,并且复制到用户进程空间后执行事先指定好的函数。 也就是说,小A交代大厅保安,我是人才,你把业务给我办理好了再通知我来验收,在这个过程中小A可以去做自己想做的事情。这就是真正的异步IO模型。
我们可以看到,前四种模型都是属于同步IO模型,因为在内核数据复制到用户空间这一个过程都是阻塞的。而最后一种异步IO,是通过将IO操作交给操作系统处理,当前的进程不关心具体IO的实现,后来再通过回调函数,或信号量通知当前进程直接对IO返回结果进行处理。
上一篇介绍: 如何理解select、poll、epoll?