I/O相关
大黄 Lv4

IO.png

Linux是如何进行I/O操作的

首先先明确一点:Linux内核将所有的外部设备都看做一个文件来操作

其次是涉及到I/O的两种场景(对应文件描述符的路径 /proc/xxx)

  • 对文件的读写操作会调用内核提供的系统命令,返回一个文件描述符(fd file descriptor)
  • 对socket的读写也会有对应的描述符,socket描述符(socketfd)

那么这里考虑到一个问题,为什么要通过描述符访问外部数据(四个方面)

  • 安全性:外部数据可能存在安全隐患,例如通过网络传输的数据可能会被黑客攻击或者恶意篡改。为了保证系统安全,操作系统需要对外部数据进行权限控制和安全验证。
  • 简化编程:操作系统通过提供通用的描述符接口来屏蔽底层细节,使得用户进程可以更容易地访问和处理外部数据,同时还能够处理多种不同类型的数据源。
  • 资源管理:操作系统需要对所有外部数据进行管理和调度,以确保外部数据的高效利用。如果用户进程直接访问外部数据,将会导致资源管理变得非常困难,并可能导致系统崩溃。
  • 抽象层:操作系统通过提供通用的描述符接口来屏蔽底层细节,使得用户进程可以在不同的外部数据源之间移植代码。

几种I/O模型

阻塞I/O模型(最常用)

在用户空间中调用 recvfrom,用户的进程会一直阻塞到数据包被复制到应用进程缓冲区或发生错误时才结束

阻塞I_O模型.png

非阻塞I/O模型

recvfrom从应用层到内核时,如果缓冲区没有数据,就直接返回EWOULEBACK错误。用户程序一直轮询

非阻塞I_O模型.png

I/O复用模型

Linux提供了select或poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select操作上。select/poll是顺序扫描fd是否就绪,且支持的fd数量有限。Linux还提供了一个epoll系统调用,基于事件驱动方式代替顺序扫描,当有fd就绪时,立即回调函数rollback

I_O复用模型.png

信号驱动I/O模型

首先开启套接口信号驱动I/O功能,并通过系统调用sigaction执行一个信号处理函数(此系统调用立即返回,进程继续工作,它是非阻塞的)。当数据准备就绪,就为该进程生产一个SIGIO信号,通过信号回调通知应用程序调用recvfrom来读取数据,并通知主循环函数处理数据

信号驱动I_O模型.png

异步I/O模型

告诉内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核复制到用户自己的缓冲区)通知我们

与信号驱动I/O模型的区别:

  • 信号驱动I/O模型:由内核通知我们何时可以开始一个I/O操作
  • 异步I/O模型:由内核通知我们I/O操作何时已经完成

异步I_O模型.png

I/O多路复用技术

适用场景:需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术来处理

I/O多路复用技术:把多个I/O的阻塞复用到同一个select的阻塞上,使得系统在单线程的情况下可以处理多个客户端请求。不需要创建多线程/多进程,系统开销小

关于I/O多路复用,为什么要用epoll而不是用select/poll

  • 事件通知方式:epoll使用事件通知方式,只会通知发生了事件的文件描述符,而poll则需要轮询所有注册的文件描述符,效率较低。
  • 可扩展性:epoll使用基于红黑树的数据结构来存储文件描述符,可以处理数以万计的并发连接,而poll只能处理数百个连接。
  • 稳定性:epoll在注册和注销文件描述符时,不需要拷贝文件描述符列表,而poll需要拷贝文件描述符列表,可能会导致内核空间和用户空间数据同步问题。(mmap)
  • 兼容性:epoll只能在Linux 2.6及以上版本中使用,而poll可以在所有Unix系统上使用。

综上所述,epoll相较于poll有更好的性能和可扩展性,并且不会有数据同步问题,但是在兼容性方面有限制。选择使用哪种多路复用机制,需要根据具体的应用场景和操作系统版本来综合考虑。

  • Post title:I/O相关
  • Post author:大黄
  • Create time:2023-03-01 21:44:35
  • Post link:https://huangbangjing.cn/2023/03/01/I-O相关/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.