说到io模型,就不得不先提一下阻塞与非阻塞,同步与异步了,下面就来聊聊这几个概念。
当系统进行io操作时,一般会涉及两个对象,用户线程(或进程)和操作系统内核,这个操作主要分为两个步骤:
等待数据准备
将数据从系统内核加载到进程中
阻塞与非阻塞的区别主要在数据准备阶段。所谓阻塞就是当用户线程进行数据请求时,如果数据还没准备好,系统并不会立即返回,而是等数据准备好之后再返回。而对于非阻塞而言,用户线程在请求数据时,不管数据有没有准备好,都会直接返回。举个例子,你饿了要去一家店吃饭,点菜打包带走,然后店家就去后厨问饭菜是否已经备好,这个时候你不知道什么时候准备好,只能在这干等着,直到店家把打包好的饭菜给你,这种就是阻塞,你得一直在这等着,直到东西准备好了才会有回复。而非阻塞的不同之处在于,店家去问后厨时,立马就有回复说没准备好呢,这个时候你可以选择继续等,也可以先干干别的事。
同步与异步的区别主要在数据加载阶段。对于同步而言,我要把数据加载到我自己的进程中,不管系统是否立即返回有无数据的回复,都得一直等或者隔一段时间去轮询,直到数据准备好并加载到我的进程中。而异步呢,它只要和系统说我要这份数据,就可以直接去做别的事情了,等到系统将数据准备好并且加载到相应进程中,就会给进程发送一个信号提示数据已准备好并加载到了进程,这时候进程就可以直接处理数据了。接着上面的例子,你要打包一份饭回家吃,你得去等待店家准备好饭菜,然后拿到自己家吃,这是同步。而异步就是你直接和店家说了要的饭菜和地址之后,店家把打包好的饭菜送到你家,给你打个电话提示饭菜已送达。
在linux的网络io操作中主要有5中模型,分别是:
阻塞IO(blocking IO)
非阻塞IO(non-blocking IO)
IO多路复用(IO multiplexing)
信号驱动IO(single driven IO)
异步IO(asynchronous IO)
阻塞IO
在进行IO数据请求时,如果数据没有准备好,就要一直阻塞等待数据准备好,然后再进行加载到进程中。
非阻塞IO
非阻塞IO就是在请求获取数据的时候,不管是否准备好数据,都会直接有返回。但是为了获取到数据,一般还是会采用轮询或者其他方式去询问数据准备情况。一旦数据准备好,就可以直接拷贝到进程中。
IO多路复用
这个和之前有所不同的是,它是用一个进程委托去轮询多个IO请求。当某一个IO已经准备好数据,就会通知相应进程来处理,将其拷贝到进程中。
信号驱动IO
信号驱动IO在请求数据时,系统会立即返回。等到系统准备好数据之后,就会发送信号通知进程,进程接到通知时就可以把数据加载到进程空间中。
异步IO
异步IO就是在请求数据之后,系统立即返回。等到系统准备好数据并加载到进程中之后,就会发送信号通知进程来进行数据处理。
注:信号驱动IO与异步IO的主要区别是,信号驱动IO是在数据准备好就发送信号,异步IO是在数据加载完成后发送信号的。