基本概念
I/O执行过程与分类:
用户进程中的一个完整I/O分为 "用户进程空间->内核空间->设备空间(磁盘、网卡)" 这两个阶段。
I/O可以分为内存I/O、网络I/O、磁盘I/O
同步和异步是什么:
1、对于线程的请求调用,同步与异步区别在于是否要等这个请求出最终结果
比如read函数,它就是只有读完了数据,存入到了buf中,才会执行下一步,这就是同步
比如aio_read函数,它就是只发送请求数据,不论是否读完,它都会执行下一步,这就是异步。
2、对于多线程,同步与异步区别在于是否要一致、是否要协调
比如生产者与消费者模型,消费者需要等待生产者生产之后再消费,需要一致,这就是同步。
比如两个线程,各干各的事,这两个事情完全没有联系,这就不需要一致,这就是异步。
3、线程内现后两个函数的调用也是一种同步
现后两个函数的调用的意思是第一个函数执行结束,第二个函数才执行。正常的程序都有这种同步
4、异步就是一个请求返回时一定不知道结果,还需要通过其他机制获取结果。
其他机制主要有主动轮询、被动通知这两种。
阻塞与非阻塞是什么:
阻塞、非阻塞与等待消息通知时线程的状态有关。阻塞的侧重点是等待时的状态,同步的侧重点是数据通知机制。
进程生存周期的五个状态:
新建、就绪、运行、阻塞、死亡
进程进入阻塞态的原因:
1、调用sleep休眠
2、调用一个在I/O上被阻塞的操作
3、获取不到锁时
4、等待触发条件
socket中可能进入阻塞的操作:
输入、输出、接收连接accept、外出连接connect
I/O模型
五种I/O模型:
阻塞I/O、非阻塞I/O、多路复用I/O、信号驱动式I/O、异步I/O
阻塞I/O模型:
以recvfrom函数为例。当进程调用recvfrom函数之后,会进入内核空间,在内核空间中去等待数据,这时是死等,直到数据到达并拷贝完成后,才会返回应用进程,此时应用进程解除阻塞。
注意:阻塞I/O的阻塞点主要指的是等待数据到来时是阻塞的。
非阻塞I/O模型:
以recvfrom函数为例。当进程调用recvfrom函数之后,会进入内核空间:当没有数据时,并不会死等而是返回一个错误信息;当有数据时,会将数据拷贝完成,之后返回应用进程(拷贝为死等)。
注意:非阻塞I/O的非阻塞点主要指的是不去等待数据到来,而拷贝数据时依旧有短暂阻塞。
多路复用I/O模型:
以select-recvfrom为例,多路复用I/O分为 "等待多路数据" 和 "拷贝指定路的数据" 两步。
等待多路数据:当应用进程调用select函数后,进入内核空间,这时select根据所配置的参数可能为阻塞等待,也可能是非阻塞等待数据。当多个通道中,有数据存在时, 会返回一个可读条件,这个条件指定了哪一路的数据是存在的。
拷贝指定路的数据:当recvfrom收到select返回的可读条件后,就会去指定的通道拷贝数据。同样在拷贝数据的过程中有短暂阻塞。拷贝数据结束后返回应用进程。
信号驱动式I/O模型:
以sigaction-recvfrom为例,信号驱动式I/O可以分为 "注册信号" 和 "拷贝数据" 这两步。
注册信号:当应用进程调用sigaction函数后,进入内核空间,将信号处理函数注册到内核中,之后返回到应用空间中。此时进程继续正常执行,直到信号产生,内核会向进程发送信号处理的请求。
拷贝数据:当应用进程接收到信号处理请求后,会调用信号处理函数。假设信号处理函数中有一个recvfrom,这是就会进入内核去拷贝数据,短暂阻塞并拷贝完成后返回应用进程。
注意:信号驱动式I/O是同步的,这是因为在拷贝数据过程中是同步的。即:真正发起I/O操作的过程是同步的。
异步I/O模型:
以aio_read为例,当应用进程调用aio_read后,会向内核发送一个读请求,之后就从内核返回到应用进程。这之后,应用进程正常运行,当有数据时,会在内核中自动拷贝。拷贝结束后,内核向应用进程发起信号,应用进程直接使用拷贝好的数据。
注意:异步I/O异步的点是,真正的I/O操作过程,是内核完成的,于此同时应用进程并没有等待它完成,而是异步的做另一件事情。