Unix IO
Unix IO
Unix IO模型简介
一个输入操作通常包括两个阶段:
- 等待数据准备好
- 从内核向进程复制数据
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
Unix IO有以下五种I/O模型
- 阻塞式I/O
- 非阻塞式I/O
- I/O复用(select/poll)
- 信号驱动式I/O(SIGIO)
- 异步I/O(AIO)
阻塞式I/O
应用程序被阻塞,直到数据复制到应用进程缓冲区才返回
应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的执行效率会比较高。
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
非阻塞式I/O
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。
由于 CPU 要处理更多的系统调用,因此这种模型是比较低效的。
I/O复用
I/O复用(I/O Multiplexing)是一种允许单个进程或线程监视多个文件描述符(如网络套接字、管道、文件等)的技术,以便在任何一个文件描述符准备好进行I/O操作时得到通知。I/O复用的主要目的是提高程序的效率和响应性,特别是在处理大量并发连接时。
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读,这一过程会被阻塞,当某一个套接字可读时返回。之后再使用 recvfrom 把数据从内核复制到进程中。
它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O(事件驱动 I/O)。
如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。并且相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。
信号驱动I/O
应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。
相比于非阻塞式 I/O 的轮询方式,信号驱动 I/O 的 CPU 利用率更高。
异步I/O
进行 aio_read 系统调用会立即返回,应用进程继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。
I/O模型比较
同步I/O与异步I/O
- 同步I/O:应用进程在调用recvfrom操作时会阻塞
- 异步I/O:不会阻塞
阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O 都是同步 I/O,虽然非阻塞式 I/O 和信号驱动 I/O 在等待数据阶段不会阻塞,但是在之后的将数据从内核复制到应用进程这个操作会阻塞。
五大I/O模型的比较
- 阻塞I/O(Blocking I/O)
- 特点:应用程序发起I/O请求后,线程会被阻塞,直到I/O操作完成。
- 优点:简单易用,适合处理简单的I/O操作。
- 缺点:线程在等待I/O操作完成时无法执行其他任务,导致资源浪费。
- 适用场景:I/O操作较少且对响应时间要求不高的场景。
- 非阻塞I/O(Non-blocking I/O)
- 特点:应用程序发起I/O请求后,如果数据未准备好,会立即返回一个错误码,线程不会被阻塞。
- 优点:线程不会被阻塞,可以继续执行其他任务。
- 缺点:需要不断轮询检查I/O操作是否完成,效率较低。
- 适用场景:需要处理大量I/O操作且对响应时间要求较高的场景。
- I/O复用(I/O Multiplexing)
- 特点:应用程序通过一个系统调用(如
select
、poll
、epoll
)监视多个文件描述符,当任何一个文件描述符准备好I/O操作时,系统调用返回。 - 优点:可以同时监视多个文件描述符,提高效率。
- 缺点:应用程序仍然需要阻塞在系统调用上,直到有文件描述符准备好I/O操作。
- 适用场景:需要处理大量并发连接的场景,如网络服务器。
- 特点:应用程序通过一个系统调用(如
- 信号驱动I/O(Signal-driven I/O)
- 特点:应用程序发起I/O请求后,内核会通过信号通知应用程序I/O操作已经准备好。
- 优点:应用程序不需要阻塞等待I/O操作完成,可以继续执行其他任务。
- 缺点:信号处理函数的执行时间较短,不适合处理复杂的I/O操作。
- 适用场景:需要处理大量I/O操作且对响应时间要求较高的场景。
- 异步I/O(Asynchronous I/O)
- 特点:应用程序发起I/O请求后,内核会立即返回,I/O操作在后台进行,完成后通过回调函数或事件通知应用程序。
- 优点:应用程序不需要阻塞等待I/O操作完成,可以继续执行其他任务,效率高。
- 缺点:实现复杂,需要处理回调函数或事件。
- 适用场景:需要处理大量I/O操作且对响应时间要求极高的场景,如高性能服务器、实时数据处理系统。
总的来说,不同的I/O模型有不同的优缺点和适用场景。在实际应用中,需要根据具体的需求和场景选择合适的I/O模型,以达到最佳的性能和响应性。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!