前言:
1.在计算机系统中,操作系统充当着IO操作等这个硬件相关的功能具体实现的基本角色之一。而我们所开
发的应用程序中所涉及到硬件相关的操作时,本质上是通过调用操作系统给我们提供的函数来实现的。
2.概念介绍
用户态和系统态:
用户态:当cpu执行的指令处在用户层时,此时程序处于用户态。
系统态:当cpu执行的指令处在系统层时,此时程序处于系统态。
阻塞和非阻塞:
阻塞:某个事件执行过程中,发出执行操作的请求,而该请求操作需要的条件不满足,那么就会一
直在那等待,直至条件满足。在IO操作中即为系统调用发起到IO执行开始这一段过程。
非阻塞:当某个事件执行过程中,发出执行操作的请求,而该请求操作需要的条件不满足,会立即
返回一个标志信息告知条件不满足,发起者就不会一直在那等待。在IO操作中即为系统调用
发起,若不满足执行IO操作时,系统层向用户层返回信息,用户层就不会等待。
同步和异步:
同步:某个事件的发生,就必须逐个顺序地进行,从而会导致整个流程的暂时等待,事件外的事件
没有办法并发地执行。在IO操作中表现为当IO操作发生时,用户层的其他流程无法执行(站在
用户层程序的角度看,IO操作发生时,我程序的其他部分无法执行了)。
异步:某个事件的发生,不会导致整个流程的暂时等待,事件外的事件可以并发地执行。在IO操作
中表现为当IO操作发生时,用户层的其他流程照样执行(在用户层程序来看)。
IO操作主要流程:
1.用户程序调用系统IO函数。
2.系统等待数据就绪。
3.将IO数据由系统内存空间拷贝到用户内存空间。
4.用户程序操作IO函数调用返回的数据。
操作系统IO模型:
1.目前操作系统的IO模型有5中:阻塞IO/非阻塞IO/IO复用/事件驱动IO/异步IO
第一阶段是指磁盘把数据装载到内核的内存中空间中。
第二阶段是指内核的内存空间的数据copy到用户的内存空间(这个才是真实I/O操作)。
1.2.非阻塞式IO
每隔一段时间,询问系统数据是否准备完成,在用户层上则表现为需不断while循环调用询问数据是
否就绪。
1.3.IO复用
1.需使用两个系统调用(上图标注1和2),1中的系统调用为操作系统提供的一种机制(linux提供了
select和poll两中实现),称为复用器。
2.IO复用流程介绍:a)select/poll机制主要功能时帮助调用者寻找在其上注册过切就绪的设备(就
是非阻塞IO中将由用户层来判断是否数据已就绪的功能交给系统来做,并且
可以判断多个IO设备),用户层程序调用后会被阻塞。
b)当有设备数据就绪时,通知调用者。
c)调用者即可进行IO数据的系统调用
3.好处:只需启动一个线程不断去轮询复用器上注册IO设备的状态即可,避免了一个线程对应一
个IO设备的情况,减少了资源占用。
1.4.事件驱动IO
1.采用回调的方式,给相应IO设备事件注册事件处理函数,用户层程序继续往下执行由系统来关
注数据是否就绪,并通过发生信号来通知用户层程序来调用事件处理函数。
2.好处:等待数据准备好这段时间,用户层程序不会处于阻塞状态中。
3.如果一个事件通知一个进程,进程正在忙的,提供一下两种机制处理
水平触发机制: 内核通知进程来读取数据,进程没来读取数据,内核需要一次一次的通知进程。
边缘触发机制: 内核只通知一次让进程来取数据,进程在超时时间内,随时可以来取数据,把这个事
件信息状态发给进程,好比发个短息给进程( nginx默认采用了该机制)。
1.5.异步IO
1.不同于以上的IO模型,当IO数据就绪后,也是由系统负责将数据拷贝到用户层中,再通过信号
通知用户层程序后,用户层程序就直接可以操作IO调用后返回的数据了(用户层程序无需发起读
取数据的系统调用了)。
总结:
1.我们可以看出IO操作的功能实现逐步移至系统层,避免用户层到系统层上下文的切换。