Unix五种I/O模型
前言
最近阅读《Unix网络编程卷1:套接字联网API》、《Linux内核完全注释》一书,阅读涉及到其中的I/O,弄清楚三个I/O复用函数select、poll、epoll的区别,也将涉及到的用户态or内核态、文件描述符fd、上下文切换,so 把知识点做一次总结记录。
内核态&用户态
- 内核态:当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态,此时处理器处于特权级最高(0级)内核代码中执行。当进程处于内核态时,执行的内核态代码会使用当前进程的内核栈,每个进程都有自己的内核栈。
- 用户态:当进程在执行用户自己的代码时,则称处于用户运行态(用户态)。此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而被中断程序中断时,则用户程序也可以象征性地处于进程的内核态,因为中断处理程序将使用当前进程的内核栈。
上下文切换
在《Linux内核完全注释》一书中有一段比较通俗易懂介绍上下文知识。
- 当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。
- 当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便再次执行该进程时,能够必得到切换时的状态执行下去。
- 在Linux中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被这中断进程的上下文中,在内核态下执行中断服务例程,但也会保留所需要的资源,以便在中断服务结束时能恢复被中断进程的执行。
文件描述符
摘自维基百科
文件描述符形式是一个非负整数,一个用于表述指向文件的引用的抽象化概念。它实际是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。
I/O模型
阻塞I/O模型
在用户空间进程调用recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。进程在从调用recvfrom开始到它返回的整段时间内是被阻塞的。非阻塞I/O模型
在用户空间进程调用recvfrom系统调用之后,进程并没有被阻塞,内核马上返回给进程。在数据还没有准备好时,轮询recvfrom系统调用没有数据可返回,内核转而立即返回一个EWOULDBLOCK错误。
当调用recvfrom时已有一个数据准备好,它被复制到应用进程缓冲区,这一个过程仍然是阻塞的过程。I/O复用模型
在Linux中通过有select、poll、epoll方法,进程将一个或多个fd传递给select、poll、epoll系统调用,在select、poll通过遍历fd集合方式判断是否可读;epoll则基于事件驱动方式代替扫描;后通知应用进0程recvfrom系统调用把所读数据报复制到应用进程缓冲区中。信号驱动式I/O模型
首先开启套接字的信号驱动I/O功能,并通过sigaction系统调用安装一个信号处理函数(系统调用立即返回,没有被阻塞)。当数据准备好读取时,内核就为该进程产生一个SIGIO信号,通过信号回调通知应用程序调用recvfrom来读取数据并通知主循环处理读取数据报。异步I/O模型
告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核复制到进程自己的缓冲区)通知应用进程。
相对比与信号驱动模型:信号驱动式I/O是由内核通知应用进程何时启动一个I/O操作,而异步则是由内核通知应用进程I/O操作何时完成。
参考文章:Unix 网络 IO 模型及 Linux 的 IO 多路复用模型
Unix 网络 IO 模型及 Linux 的 IO 多路复用模型