首页 > 其他分享 >IO多路复用

IO多路复用

时间:2024-09-15 14:55:35浏览次数:12  
标签:文件 多路复用 epoll 阻塞 描述符 IO select

I/O 模型指的是操作系统处理输入/输出(I/O input/output)操作的不同方式,它们主要在于如何处理程序与 I/O 操作设备(如磁盘、网络等)之间的交互,以及在等待 I/O 操作完成时,程序如何调度和管理。

常见的IO模型有:

  1. 阻塞IO
  2. 非阻塞IO
  3. IO多路复用
  4. 异步IO

 阻塞IO

最基础的IO模型,简单调用read()函数进行处理,程序发出 I/O 操作请求后,会被阻塞,直到 I/O 操作完成。期间,程序无法执行其他任务,必须等待数据准备好或者操作完成。也可以开启多线程,每次接受一个请求就开启一个线程去处理。

特点:编程简单,但会浪费系统资源,因为线程在等待 I/O 完成期间无法做其他事情。如果开启多线程,线程太多会导致内存开销过大,并且每次切换线程也会给CPU带来开销。

非阻塞IO

升级了read()函数,执行后程序发出 I/O 请求时不会被阻塞,如果操作不能立即完成,系统调用会立即返回错误或特定状态,告知程序数据尚未准备好,避免了一直阻塞的等待。

程序可以选择稍后重试(自己写轮询read()函数监控判断是否就绪),或者继续执行其他任务。

特点:程序不会被阻塞,但 CPU 资源可能会被浪费在重复的轮询操作上。

IO多路复用

是一种在单个线程中同时监控多个 I/O 事件(如文件描述符、网络套接字)的机制。当其中某个或多个 I/O 事件就绪时,操作系统通知应用程序处理相应的 I/O 操作,从而避免为每个 I/O 事件单独创建线程或进程。这种机制有效地提高了系统对多 I/O 并发的处理能力。

IO多路复用相对于非阻塞IO就是系统自己提供轮询监控机制直接交给内核处理,避免了用户态切换到内核态的消耗。

IO多路复用常用机制

select函数

select 是最早期的 I/O 多路复用机制,它允许监控多个文件描述符,阻塞直到其中一个或多个就绪(可读、可写或有错误发生)。用数组,用户侧将数组拷贝传给内核,内核去轮询。

缺点:

  • 文件描述符限制select 的监控文件描述符数量有限,在大多数系统上为 1024。
  • 效率低:每次调用 select 都需要遍历所有文件描述符,因为它每次返回的是发生事件的数量,需要轮询判断是哪一个发生,导致在文件描述符数量较多时性能下降。
poll函数

poll 机制类似于 select,但没有文件描述符数量的限制。它通过传递一个文件描述符数组来监控多个 I/O 事件。解决了文件字符数量限制问题。数组变成链表。

缺点:

效率低:和 select 一样,poll 需要遍历所有的文件描述符数组,性能在文件描述符数量较大时也不理想。

epoll函数 (主要使用)

epoll 是 Linux 下的高效 I/O 多路复用机制,专为大规模文件描述符的高效管理设计。它与 selectpoll 相比有显著的性能提升。不用拷贝直接传到内核,在内核中进行红黑树的创建,轮询速度快;返回时返回的是一个队列或链表,里面存储发生事件的描述符,不需要轮询判断那个事件发生

特点:

  • 文件描述符无限制epoll 没有文件描述符数量的限制,适合处理大规模并发连接。
  • 高效的事件通知epoll 使用事件驱动的模型(边缘触发水平触发),即只有当文件描述符发生了新的 I/O 事件时才会返回,无需每次遍历整个描述符列表。
  • 内核支持epoll 内部使用事件表,将事件存储在内核空间中,避免每次调用时传递大量文件描述符。
int epoll_fd = epoll_create(1);  // 创建 epoll 句柄
struct epoll_event event, events[MAX_EVENTS];

// 将一个 socket 文件描述符注册到 epoll 中
event.events = EPOLLIN;  // 监听读事件
event.data.fd = listen_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event);//直接将fd传递到内核

// 循环等待事件
int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);  // 阻塞等待事件
for (int i = 0; i < nfds; i++) {
    if (events[i].events & EPOLLIN) {
        // 处理可读事件
    }
}

总结

        I/O 多路复用是一种在高并发环境中高效处理多个 I/O 操作的机制,避免了传统阻塞 I/O 模型的线程开销问题。常见的机制如 selectpollepollkqueue 各自适用于不同的场景,其中 epoll 是 Linux 系统中处理大规模 I/O 操作的首选。

标签:文件,多路复用,epoll,阻塞,描述符,IO,select
From: https://blog.csdn.net/Junhe4512/article/details/142265850

相关文章