Linux:五种IO模型

news2024/9/20 23:31:23

1:五种IO模型 

 1:阻塞IO

阻塞IO:

        在内核将数据准备好之前,系统调用会一直等待.所有的套接字,默认 都是阻塞方式。

2:非阻塞 IO

非阻塞 IO:

        如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK 错误码。

        非阻塞 IO 往往需要循环的方式反复尝试读写文件描述符(对于CPU会有较大的浪费), 这个过程称为轮询

3:信号驱动IO 

 信号驱动 IO:

        内核将数据准备好的时候, 使用 SIGIO 信号通知应用程序进行 IO操作。

4:IO多路转接

IO 多路转接:

        虽然从流程图上看起来和阻塞 IO 类似. 实际上最核心在于 IO 多路转接能够同时等待多个文件描述符的就绪状态。


 

5:异步IO 

异步 IO:

      由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据)。

2:总结

        任何 IO 过程中, 都包含两个步骤。 第一是等待, 第二是拷贝。而且在实际的应用场景中, 等待消耗的时间往往都远远高于拷贝的时间。让 IO 更高效, 最核心的办法就是让等待的时间尽量少。

同步通信(synchronous communication) vs 异步通信(asynchronous communication)

         1. 同步(Synchronous IO) 

        就是在发出一个调用时, 在没有得到结果之前, 该调用就不返回。但是一旦调用返回, 就得到返回值了; 换句话说, 就是由调用者主动等待这个调用的结果;

        2. 异步(Asynchronous IO): 

        调用在发出之后, 这个调用就直接返回了, 所以没有返回结果; 换句话说, 当一个异步过程调用发出后, 调用者不会立刻得到结果; 而是在调用发出后, 被调用者通过状态、 通知来通知调用者, 或通过回调函数处理这个调用。

同步(Synchronization)vs 互斥(Mutual Exclusion)

  1. 同步(Synchronization)

    • 同步是指在多线程环境中,协调多个线程的执行顺序,使得它们能够按照预定的顺序执行。
    • 同步通常用于确保线程之间的合作,例如,一个线程可能需要等待另一个线程完成某些任务后才能继续执行。
    • 同步可以通过多种机制实现,如信号量(Semaphore)、事件(Event)、条件变量(Condition Variable)等。
  2. 互斥(Mutual Exclusion)

    • 互斥是指在多线程环境中,确保同一时间只有一个线程能够访问某个特定的资源或代码段。
    • 互斥主要用于防止竞争条件,即多个线程同时访问和修改共享数据,导致数据不一致的问题。
    • 互斥可以通过锁(Locks)如互斥锁(Mutex)、读写锁(Read-Write Lock)等来实现。

常见的同步和互斥机制:

  • 互斥锁(Mutex):一种基本的同步机制,用于保护临界区,确保同一时间只有一个线程可以进入临界区。
  • 信号量(Semaphore):用于控制对共享资源的访问,可以允许多个线程同时访问,也可以限制访问数量。
  • 事件(Event):用于线程之间的通信,一个线程可以等待事件被另一个线程触发。
  • 条件变量(Condition Variable):用于线程之间的同步,允许线程在某些条件不满足时挂起,并在条件满足时被唤醒。
  • 读写锁(Read-Write Lock):允许多个读操作同时进行,但写操作会独占锁,确保写操作的互斥。

同步与互斥的区别:

  • 同步:关注的是线程之间的协调和合作,确保它们能够按照正确的顺序执行。
  • 互斥:关注的是保护共享资源,防止多个线程同时访问同一资源,从而避免数据不一致。

阻塞(Blocking)vs 非阻塞(Non-blocking)

        阻塞和非阻塞关注的是程序在等待调用结果(消息, 返回值) 时的状态。

  1. 阻塞(Blocking)

    • 当一个线程执行一个阻塞操作时,它会停止执行,直到该操作完成。在等待期间,线程不会做任何其他工作。
    • 阻塞操作通常用于简化编程模型,因为它们不需要额外的机制来处理并发和同步。
    • 缺点是阻塞操作可能导致程序的响应性降低,特别是在等待时间较长的情况下。
  2. 非阻塞(Non-blocking)

    • 非阻塞操作不会停止线程的执行。如果操作尚未完成,线程可以继续执行其他任务。
    • 非阻塞操作通常需要额外的同步机制,如事件、回调或轮询,来处理操作的完成。
    • 优点是可以提高程序的并发性和响应性,因为线程不需要等待就可以继续执行其他任务。

阻塞与非阻塞的比较:

  • 性能

    • 阻塞操作可能导致线程资源的浪费,特别是在IO密集型应用中。
    • 非阻塞操作可以提高资源利用率,因为线程可以在等待期间执行其他任务。
  • 编程复杂性

    • 阻塞操作通常更容易理解和实现,因为它们遵循同步编程模型。
    • 非阻塞操作可能更复杂,需要更多的同步和错误处理机制。
  • 适用场景

    • 阻塞操作适用于简单的应用或那些不需要高并发的场景。
    • 非阻塞操作适用于需要高并发和快速响应的系统,如服务器和网络应用。

实际应用中的阻塞与非阻塞:

  • 文件IO

    • 阻塞式文件IO:当一个线程读取文件时,如果文件不可用,线程会等待直到文件可用。
    • 非阻塞式文件IO:线程会立即返回,不会等待文件可用,而是定期检查文件状态。
  • 网络IO

    • 阻塞式网络IO:当一个线程等待数据到来时,它会阻塞直到数据到达。
    • 非阻塞式网络IO:线程会立即返回,不会等待数据,而是定期检查数据是否到达。

 3:非阻塞IO举例

 fcntl

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

         传入的 cmd 的值不同, 后面追加的参数也不相同。

        fcntl 函数有 5 种功能:

               • 复制一个现有的描述符(cmd=F_DUPFD)。

               • 获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD)。

               • 获得/设置文件状态标记(cmd=F_GETFL 或 F_SETFL)。

               • 获得/设置异步 I/O 所有权(cmd=F_GETOWN 或 F_SETOWN)。

               • 获得/设置记录锁(cmd=F_GETLK,F_SETLK 或 F_SETLKW)。

轮询方式读取标准输入

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>

int SetNoBlock(int fd)
{
    int flags = fcntl(fd, F_GETFL);
    if (flags == -1)
    {
        perror("fcntl get flags");
        return 0;
    }
    else
    {
        int n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
        if (n == -1)
        {
            perror("fcntl set flags");
            return 0;
        }
    }
    return 1;
}

int main()
{
    if (!SetNoBlock(0))
    {
        perror("fcntl set fcntl!");
        return -1;
    }
    while (true)
    {
        printf("Enter: ");
        fflush(stdout);
        char buffer[1024];
        ssize_t n = ::read(0, buffer, sizeof(buffer));
        // 如果是非阻塞,底层数据没有准备就绪,IO接口,会以出错的形式返回!
        // 区分 底层不就绪 与 真的出错了 ?
        // 底层没有就绪(错误码被设置):errno错误码:EWOULDBLOCK EAGAIN
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer << std::endl;
        }
        else if (n == 0) //ctrl + d 读取输入结束
        {
            perror("read done");
            break;
        }
        else
        {
            if (errno == EWOULDBLOCK)
            {
                sleep(1);
                // 轮询检测...
                // Do other things...
                printf("Do other things\n");
                continue;
            }
            else if (errno == EINTR) // 处理读取被中断
            {
                continue;
            }
            else
            {
                perror("read");
                break;
            }
        }

        sleep(1);
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2125083.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7.9部署Gitlab-ce-16.9

一、环境信息 软件/系统名称版本下载地址备注Centos77.9.2009https://mirrors.nju.edu.cn/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.isogitlab-cegitlab-ce-16.9.1https://mirror.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.9.1-ce.0.el7.x86_64.rpm…

4款免费录屏工具,哪款更实用?

作为一个经常需要录制教程和游戏视频的UP主&#xff0c;我尝试过市面上不少录屏工具。今天&#xff0c;我就来分享一下我使用过的四款软件录制全屏时的体验感受&#xff0c;看看哪款软件的表现更胜一筹。 一、福昕录屏大师 网址&#xff1a;https://www.foxitsoftware.cn/REC/…

配置 MinGW 以及使用 g++ 编译 C++ 程序

如何在 Windows 上安装和配置 MinGW 以及使用 g 编译 C 程序 (C语言&#xff08;gcc&#xff09;类似 ) 在Windows环境下&#xff0c;使用C进行编程需要一个编译器&#xff0c;而MinGW (Minimalist GNU for Windows) 是一个常用的C/C编译器工具集。对于编程新手来说&#xff0c…

SAP与赛美特MES系统集成案例

一、项目环境 上海某通信有限公司主要产品应用于图像传感器、 图像信号处理芯片、 低功耗芯片、 射频芯片。 为实现生产流程的自动化调度&#xff0c;减少人为干预的错误&#xff0c;保证流程的一致性和合规性&#xff0c;同时也简化操作流程&#xff0c;降低培训成本。&am…

护眼台灯对眼睛好吗?眼科医生推荐的台灯告诉你答案

作为一名家长&#xff0c;我深刻体会到保护孩子眼部健康的重要性。随着科技的迅猛发展&#xff0c;孩子们越来越多地接触并依赖电子设备&#xff0c;如平板电脑、手机和电视&#xff0c;长时间盯着屏幕已成为他们日常生活的一部分。然而&#xff0c;这些屏幕发出的蓝光及闪烁的…

等保测评前的准备工作:企业必知的五大步骤

信息安全等级保护&#xff08;等保&#xff09;测评是企业信息安全合规的重要环节&#xff0c;对于确保企业信息系统的安全性、稳定性和合规性具有重大意义。为了顺利通过等保测评&#xff0c;企业需要提前做好充分的准备。本文将从实战角度出发&#xff0c;详细介绍等保测评前…

2024年10款好用的图纸加密软件推荐|有效的图纸加密方法分享

在数字化时代&#xff0c;保护CAD图纸等设计文件的安全性是企业不可忽视的重要任务。随着技术的不断进步&#xff0c;各类图纸加密软件应运而生&#xff0c;为企业提供了强大的数据保护能力。本文将为您推荐2024年十款好用的图纸加密软件&#xff0c;并分享一些有效的图纸加密方…

GD32F4开发 -- FATFS文件系统

一、FATFS源码下载 FatFs - Generic FAT Filesystem Module (elm-chan.org) 二、移植 打开ffconf.h文件&#xff0c;找到对应宏并按照需求修改 FF_CODE_PAGE: #define FF_CODE_PAGE 936 //改为936以支持简体中文 /* This option specifies the OEM code page to be used on…

Find My资讯|国外外设品牌发布新型素皮护照套,支持苹果Find My功能

外设品牌 Satechi 发布一款采用苹果Find My技术的新型素皮护照套&#xff0c;售价为 59.99 美元。这款新型护照套除了可以存放护照外&#xff0c;还可存放银行卡、信用卡、身份证、登机牌等物品&#xff0c;其最大特性是采用了与苹果 AirTags 相同的技术&#xff0c;内置了可充…

YOLOv9改进策略【Neck】| 有效且轻量的动态上采样算子:DySample

一、本文介绍 本文记录的是利用DySample上采样对YOLOv9的颈部网络进行改进的方法研究。YOLOv9采用传统的最近邻插值的方法进行上采样可能无法有效地捕捉特征的细节和语义信息&#xff0c;从而影响模型在密集预测任务中的性能。DySample通过动态采样的方式进行上采样&#xff0…

Brave编译指南2024 Windows篇:安装depot_tools(三)

1.引言 在编译Brave浏览器的过程中&#xff0c;depot_tools是不可或缺的一部分。这是一组由Chromium项目提供的脚本和工具&#xff0c;用于获取、管理和更新Chromium及其衍生项目的源码。通过depot_tools&#xff0c;开发者可以方便地同步最新的源码版本&#xff0c;并进行项目…

NVD系列语音芯片在报警器中通常应用在哪些场景中

语音芯片在各类场景中应用的最大作用就是进行语音提示和警报提示。本文将对NVD系列语音芯片应用在报警器中的场景。 1.提升电动车的安全性 当电动车遭受震动或异常移动时&#xff0c;报警器会感应到并触发报警装置&#xff0c;通常是通过发出高分贝的声音警报来吸引人们的注意…

基于HTML+JS+CSS+Echarts实现的设备环境监测可视化平台前端整套模板

效果图 基于HTMLJSCSSEcharts实现的设备环境监测可视化平台前端整套模板。可用过修改源码快速完成需求。 源码结构 下载地址

Shell实用功能及文件权限

1、使用命令“cat /etc/named.conf”设置为别名named&#xff0c;然后再取消别名。 设置别名&#xff1a;alias namedcat /etc/named.conf 取消别名&#xff1a;unalias named 2、使用echo命令和输出重定向创建文本文件/root/nn&#xff0c;内容是hello&#xff0c;然后再使用…

C++笔记---list

1. list的介绍 list其实就是就是我们所熟知的链表&#xff08;双向循环带头结点&#xff09;&#xff0c;但其是作为STL中的一个类模板而存在。 也就是说&#xff0c;list是可以用来存储任意类型数据的顺序表&#xff0c;既可以是内置类型&#xff0c;也可以是自定义类型&…

【目标检测数据集】工具钳子、剪刀、螺丝刀检测数据集3668张3类VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3668 标注数量(xml文件个数)&#xff1a;3668 标注数量(txt文件个数)&#xff1a;3668 标注…

安卓13系统导航方式分析以及安卓13修改默认方式为手势导航 android13修改导航方式

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.彩蛋1.前言 系统导航方式默认一般是按键的,如果要改成手势的话,我们来看看用户怎么修改的: 设置=>系统=>手势=>系统导航,在这里进行修改。我们来分析下这个流程,并且将其修改为…

Stage模型UIAbility组件【单任务列表/多任务列表】

什么是多线程 比如你在微信中聊天 突然打开一个小程序 然后查看手机进程 如果一个软件有多个那就是多进程 &#xff08;目前小编看下来 只有安卓有 苹果看不出来&#xff09; 进程之间是可以相互跳转的 UIAbility组件可以是单个任务列表或多个任务列表 启动页想用哪个就设置哪个…

《python语言程序设计》2018版第8章第14题金融:信用卡号合法性 利用6.29题

一、之前6.29题我做的代码 这是用数字来进行分辨的 is_txt 4383576018402626 #合法def split_the_data_even(vis_n):current_a1 vis_n // 10000a_t1 vis_n % 10000# print("1th", a_t1)a_t2 current_a1 % 10000# print("2th", a_t2)current_a3 curre…

【自用23.】C++-const数据成员及const成员函数

const数据成员 const数据成员的初始化方式&#xff1a; 使用类内值&#xff08;C11支持&#xff09;使用构造函数的初始化列表 &#xff08;如果同时使用这两种方式&#xff0c;以初始化列表中的值为最终初始化结果&#xff09; 注意&#xff1a; 不能在构造函数或其他成员…