一、I/O基本过程
I/O主要有磁盘I/O和网络I/O,以磁盘I/O为例:
读过程:
进程向内核发起系统调用read(),内核驱动磁盘读入数据至内核空间的buffer(缓冲区)中,再将这些数据拷贝到用户空间的buffer中
写过程:
进程向内核发起系统调用write(),内核将用户空间的数据写入到内核空间缓冲区中,再同步到磁盘上
二、I/O分类和模型
1、I/O分类
按进程调用请求发起之后是否会被挂起:
①阻塞:进程发起I/O调用,未完成之前,进程会被挂起;
②非阻塞:进程发起I/O调用,被调用函数完成不会阻塞当前进程;
按进程发起调用后,被调用者的反应:
③同步:进程发起一个过程调用后,被调用者在准备好结果之前,将不会返回任何提示
④异步:进程发起一个过程调用后,被调用者即使不能立即准备好结果,也会返回一个未完成的提示,结果准备好时,内核会通知进程
2、五种I/O模型
①同步阻塞
这种模式下,所有套接口都是阻塞的,进程调用recvfrom(),该系统调用直到数据准备好并且被拷贝到应用进程空间或发生错误后才返回,在此期间进程被阻塞
②同步非阻塞
与同步阻塞模式不同的地方在于,进程在数据准备阶段不会被阻塞,但它会在数据准备好之前循环调用recvfrom(),也就是“盲等待”。进程在数据拷贝阶段仍是阻塞的
③I/O复用(如web服务进程中的prefork模型)
I/O复用模型会用到select()或者poll(),这两个函数也会使进程阻塞,但是和阻塞I/O所不同的是,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数recvfrom()
④信号驱动I/O(如web服务进程中的event模型)
在此模式中,开启套接口的信号驱动I/O功能,并通过sigaction系统调用安装一个信号处理函数,该系统调用立即返回,进程不会被阻塞。当数据报准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数recvfrom读取数据,进程只会阻塞于数据拷贝的过程
此模式的优点在于进程不用像I/O复用模型中那样阻塞于select()函数对套接口的扫描,因为SIGIO信号中已包含了准备好的数据是属于哪个套接口的信息
⑤异步I/O(只能磁盘I/O能做异步,网络I/O无法做异步)
此模式下,进程调用aio_read(),该系统调用立即返回,进程不会被阻塞,直到数据拷贝到应用进程空间。显然,这得一种最佳模型。
nginx支持异步I/O和信号驱动I/O
五种I/O模型的比较: