服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Linux|Centos|Ubuntu|系统进程|Fedora|注册表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服务器之家 - 服务器系统 - Linux - 利用Linux高级IO实现非阻塞和多路复用IO

利用Linux高级IO实现非阻塞和多路复用IO

2023-12-13 14:41编程技术汇 Linux

在传统的阻塞IO模型中,当进行IO操作时,程序会一直等待直到IO操作完成。这种方式会导致程序在等待IO的过程中无法进行其他任务,造成资源的浪费。本文将介绍如何利用Linux的高级IO实现非阻塞和多路复用IO。

高级IO(Advanced IO)是一种在Linux系统中进行非阻塞和多路复用IO操作的技术。这种技术可以提高系统的并发处理能力,提升IO性能,并减少资源的消耗。下面将介绍如何利用Linux的高级IO实现非阻塞和多路复用IO。

在传统的阻塞IO模型中,当进行IO操作时,程序会一直等待直到IO操作完成。这种方式会导致程序在等待IO的过程中无法进行其他任务,造成资源的浪费。而非阻塞IO允许程序进行其他任务而不需等待IO操作的完成,从而提高了系统的并发性能。

而多路复用IO允许程序同时监视多个IO事件,并一次性等待多个IO事件中的任意一个就绪。这样,程序可以通过一次系统调用来同时等待多个IO操作的完成,而不需要轮询每个IO事件是否就绪,从而减少了系统调用的次数,提高了系统的效率。

下面将分别介绍如何使用高级IO实现非阻塞IO和多路复用IO。

一、非阻塞IO

非阻塞IO是指在进行IO操作时,程序不会被阻塞等待IO操作的完成,而是立即返回。程序可以通过轮询的方式来检查IO操作是否已经完成,如果完成则进行后续处理,如果未完成则继续执行其他任务。

在Linux系统中,可以使用以下方式来实现非阻塞IO:

1、设置文件描述符为非阻塞模式:

在进行IO操作之前,可以通过fcntl函数设置文件描述符的属性,将其设置为非阻塞模式。例如,可以使用以下代码将文件描述符fd设置为非阻塞模式:

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

这样,当进行IO操作时,即使没有数据可读或没有空闲的缓冲区可写,也会立即返回而不会阻塞程序的执行。

2、使用select函数进行轮询:

select函数是一个多路复用IO的系统调用,可以同时监视多个IO事件,包括可读、可写和异常事件。通过将文件描述符加入到select函数的监视集合中,程序可以等待多个IO事件中的任意一个就绪。可以使用以下代码示例使用select函数进行非阻塞IO:

fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);

struct timeval timeout;
timeout.tv_sec = 5;  // 设置超时时间为5秒
timeout.tv_usec = 0;

int ret = select(fd + 1, &read_fds, NULL, NULL, &timeout);
if (ret > 0 && FD_ISSET(fd, &read_fds)) {
    // IO操作已完成,进行后续处理
}

在上面的代码中,首先将要监视的文件描述符添加到read_fds集合中,然后调用select函数等待IO事件的就绪。如果select函数返回大于0的值,并且文件描述符在read_fds集合中,则表示IO操作已经完成。

二、多路复用IO

多路复用IO是指通过一次系统调用同时等待多个IO事件的就绪,从而提高系统的效率。在Linux系统中,可以使用以下方式来实现多路复用IO:

1、使用select函数进行多路复用:

如前所述,select函数可以同时监视多个IO事件的就绪情况。通过将需要监视的文件描述符添加到select函数的不同集合中,即可等待多个IO事件的就绪。以下是一个示例代码:

fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd1, &read_fds);
FD_SET(fd2, &read_fds);

struct timeval timeout;
timeout.tv_sec = 5;  // 设置超时时间为5秒
timeout.tv_usec = 0;

int ret = select(fd2 + 1, &read_fds, NULL, NULL, &timeout);
if (ret > 0) {
    if (FD_ISSET(fd1, &read_fds)) {
        // fd1的IO操作已完成,进行后续处理
    }
    if (FD_ISSET(fd2, &read_fds)) {
        // fd2的IO操作已完成,进行后续处理
    }
}

在上面的代码中,首先将需要监视的文件描述符分别添加到read_fds集合中,然后调用select函数等待多个IO事件的就绪。如果select函数返回大于0的值,并且文件描述符在相应的集合中,则表示IO操作已经完成。

2、使用epoll进行多路复用:

epoll是一种高效的多路复用IO机制,通过提供一个事件驱动的接口,可以监视大量的文件描述符状态。与select函数相比,epoll具有更高的性能和可扩展性。

使用epoll进行多路复用IO主要包括以下几个步骤:

1)创建一个epoll实例:使用epoll_create函数创建一个epoll实例。

2)注册文件描述符和事件:使用epoll_ctl函数将需要监视的文件描述符和事件注册到epoll实例中。

3)等待IO事件的就绪:使用epoll_wait函数等待IO事件的就绪,该函数会阻塞直到有IO事件就绪。

4)处理就绪的IO事件:根据epoll_wait函数的返回结果,处理就绪的IO事件。

下面是一个示例代码:

int epoll_fd = epoll_create(1);
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN | EPOLLET;  // 监视可读事件,使用边缘触发模式
event.data.fd = fd1;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd1, &event);

event.events = EPOLLOUT | EPOLLET;  // 监视可写事件,使用边缘触发模式
event.data.fd = fd2;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd2, &event);

struct epoll_event events[10];
int ret = epoll_wait(epoll_fd, events, 10, -1);
if (ret > 0) {
    for (int i = 0; i < ret; ++i) {
        if (events[i].data.fd == fd1) {
            // fd1的IO操作已完成,进行后续处理
        }
        if (events[i].data.fd == fd2) {
            // fd2的IO操作已完成,进行后续处理
        }
    }
}

在上面的代码中,首先创建一个epoll实例,然后使用epoll_ctl函数将需要监视的文件描述符和事件注册到epoll实例中。接着调用epoll_wait函数等待IO事件的就绪,并根据返回结果处理就绪的IO事件。

通过使用Linux的高级IO技术,包括非阻塞IO和多路复用IO,可以提高系统的并发性能,减少资源的浪费。开发人员可以根据实际需求选择合适的方式来实现非阻塞和多路复用IO操作,从而提高系统的效率和性能。

原文地址:https://www.toutiao.com/article/7254364952381686310/

延伸 · 阅读

精彩推荐
  • LinuxLinux下Redis服务器搭建过程

    Linux下Redis服务器搭建过程

    这篇文章主要介绍了Linux下Redis服务器搭建过程,需要的朋友可以参考下...

    服务器之家6072020-08-13
  • LinuxLinux系统下中 在命令行中实现Wifi 连接的方法

    Linux系统下中 在命令行中实现Wifi 连接的方法

    无论何时要安装一款新的 Linux 发行系统,一般的建议都是让您通过有线连接来接到互联网的。所以我迫使自己学习如何在命令行中管理WiFi连接,下面把在...

    Linux教程网10012019-10-27
  • Linux利用linux命令查看某个目录的内容的教程

    利用linux命令查看某个目录的内容的教程

    linux命令怎么查看某个目录的内容?想要看看某个盘里的内容,一个文件夹一个文件夹的去打开查找就太麻烦了,linux命令可以直接打开目录查看内容吗?下...

    脚本之家5992019-10-14
  • Linux使用Linux要改掉几个的命令习惯

    使用Linux要改掉几个的命令习惯

    现在越来越多的人用linux系统,本文分享的这些习惯也许会令你事半功倍,找到其中的乐趣。刚开始使用Linux时你也许会感到不习惯,许多高手也都有这样的...

    Linux教程网7522021-11-25
  • Linux.httacces文件的配置技巧

    .httacces文件的配置技巧

    我要介绍的.htaccess的第一个应用是自定义错误页面,这将使你可以拥有自己的、个性化的错误页面(例如找不到文件时),而不是你的服务商提供的错误页...

    Linux教程网3242020-06-05
  • LinuxLinux输入输出重定向详细使用说明

    Linux输入输出重定向详细使用说明

    Linux标准输入、输出设备主要是键盘和显示器,输出重定向是改变程序运行的输入来源和输出地点...

    Linux教程网4582022-03-03
  • LinuxLinux中僵尸进程和孤儿进程详解

    Linux中僵尸进程和孤儿进程详解

    早就了解孤儿进程与僵尸进程,但仅仅是停留在一知半解的程度,最近正好有空就顺便学习一下,下面这篇文章主要给大家介绍了关于Linux中僵尸进程和孤...

    z5176026589382022-01-20
  • LinuxLinux静态链接库与模板类的处理方式

    Linux静态链接库与模板类的处理方式

    这篇文章主要介绍了Linux下编译使用静态链接库遇到模板类的时该如何处理。...

    24k的帅哥5872022-02-22