Linux四种I/O模型

news2024/9/21 22:33:11

一.四种模型

阻塞式IO,非阻塞式IO,信号驱动IO,IO多路复用

二.阻塞式IO

特点:最简单,最常用,效率低

阻塞I/O 模式是最普遍使用的I/O 模式

  系统默认状态,套接字建立后所处于的模式就是阻塞I/O 模式。

  目前学习的读写函数中会发生阻塞相关函数如下:

 ·      read、recv、recvfrom

         读阻塞--》需要读缓冲区中有数据可读,读阻塞才会解除

 ·      write, send 

         写阻塞--》阻塞就是写入数据时遇到缓冲区满了的情况,需要等待缓冲区有空间后才能继续写入, 所以写阻塞发生的情况比较少.

 ·      accept    connect

需要注意的是使用UDP时,UDP没有发送缓存区 ,则sendto没有阻塞

 1)UDP通信无连接,且无发送缓冲区(不怕粘包),即sendto在UDP中没有发送缓冲区。

 2)UDP不用等待确认,没有实际的发送缓冲区,所以UDP协议中不存在缓冲区满的情况,在UDP套接字上进行写操作永远不会阻塞。

UDP与TCP缓存区 

UDP是一种无连接的传输协议,它不保证数据的可靠性和顺序性, 所以不需要考虑连接和缓存,而是将数据尽快发送出去,不关心数据是否到达目标主机或者是否按照发送顺序到达. 但是UDP有接受缓存区, 因为数据发送过快, 如果接收缓存区内数据已满, 则继续发送数据, 可能会出现丢包。

TCP是一种面向连接的传输协议,有发送缓存区和接收缓存区, 如果发送频率过快, 且内容小于发送缓存区的大小 , 可能会导致多个数据的粘包。如果发送的数据大于发送缓存区的剩余大小,send将会阻塞,  在阻塞期间,send函数会自动拆分数据包发送,直到所有数据都被发送完毕或者发送缓冲区的空间不足以继续发送为止, 这就是拆包。

UDP不会造成粘包和拆包,  TCP不会造成丢包

UDP_数据报:  本质是独立的包, 有边界;

TCP_流,:本质是字节流形式, 一帧一帧发送,且每一帧没有边界,一帧丢失会重新补发;

  

 

 三.阻塞式IO

特点:可以处理多路IO,需要轮询,大量浪费CPU资源

  1. 当一个应用程序使用了非阻塞模式的套接字,则它需要使用一个循环来不停的测试是否一个文件描述符有数据可读。
  2. 应用程序不停的测试,会占用大量的cpu资源 ,所以说一般不适用

 将recv设置为非阻塞时, recv在接收缓存区内, 未拿到客户端发送来的数据, 那么recv就会报错 , 所以会一直打印 recv is err: 资源不可用

fcntl设置文件描述符的属性

声明: int fcntl (int fd, int cmd, ...arg);

头文件: #include<fcntl.h>      #include<unistd.h>

功能:设置文件描述符的属性

参数:fd:文件描述符

         cmd: 操作功能选项 (可以定义个变量,通过vi -t F_GETFL 来找寻功能赋值 )

          F_GETFL:获取文件描述符的原有的状态信息 

          //不需要第三个参数,返回值为获取到的属性

          F_SETFL:设置文件描述符的状态信息 - 需要填充第三个参数

          //需要填充第三个参数  O_RDONLY, O_RDWR ,O_WRONLY ,O_CREAT

                  O_NONBLOCK 非阻塞   O_APPEND追加

                  O_ASYNC 异步        O_SYNC  同步 

          F_SETOWN:    可以用于实现异步通知机制。

        //当文件描述符上发生特定事件时(例如输入数据到达),内核会向拥有该  文件描述符 的进程发送 SIGIO 信号(异步),以便进程能够及时处理这些事件。

        arg:文件描述符的属性      --------------------同上参数

返回值: 特殊选择:根据功能选择返回 (int 类型)

            其他:  成功0   失败: -1;

改变步骤:

1.获取该文件描述符0 (标准输入) 的原属性 : 标准输入原本具有阻塞的功能  

int flag = fcntl(0, F_GETFL); //获取文件描述符原有信息后,保存在flag变量内

2.修改对应的位nonblock(非阻塞)

int flag |= O_NONBLOCK; 

3. 将修改好的属性写回去 (0 标准输入 -- 阻塞  改为  非阻塞)

fcntl (0, F_SETFL, flag); //文件描述符   设置状态  添加的新属性

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    char buf[64] = {0};
    while (1)
    {
        int flag = fcntl(0, F_GETFL); 
        flag |= O_NONBLOCK;
        fcntl(0, F_SETFL, flag);
        fgets(buf, sizeof(buf), stdin);
        sleep(1);
        printf("buf: %s\n",buf);
    }

    return 0;
}

四.信号驱动IO

特点:异步通知模式,需要底层驱动支持

异步通知:异步通知是一种非阻塞的通知机制,发送方发送通知后不需要等待接收方的响应或确认。通知发送后,发送方可以继续执行其他操作,而无需等待接收方处理通知。

1. 通过信号方式,当内核检测到设备数据后,会主动给应用发送信号SIGIO

2. 应用程序收到信号后做异步处理即可。

3. 应用程序需要把自己的进程号告诉内核,并打开异步通知机制。

 步骤:

1.设置将文件描述符和进程号提交给内核驱动,一旦fd有事件响应, 则内核驱动会给进程号发送一个SIGIO的信号

     fcntl(fd,F_SETOWN,getpid());

2.设置异步通知

    int flags;

    flags = fcntl(fd, F_GETFL); //获取原属性

    flags |= O_ASYNC;       //给flags设置异步   O_ASUNC 通知

    fcntl(fd, F_SETFL, flags);  //修改的属性设置进去,此时fd属于异步

3.signal捕捉SIGIO信号 --- SIGIO:内核通知会进程有新的IO信号可用一旦内核给进程发送sigio信号,则执行handler

    signal(SIGIO,handler);

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

int fd;
void handler(int set)
{
    char buf[128] = {0};
    int len = read(fd, buf, sizeof(buf));
    buf[len] = '\0';
    printf("%s\n", buf);
}
int main(int argc, char const *argv[])
{
    fd = open("/dev/input/mouse0", O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    fcntl(fd, F_SETOWN, getpid());

    int flags = fcntl(fd, F_GETFL);
    flags |= O_ASYNC;
    fcntl(fd, F_SETFL, flags);
    
    signal(SIGIO, handler);
    char buf[128] = {0};
    while (1)
    {
        fgets(buf, sizeof(buf), stdin);
        printf("%s", buf);
    }

    return 0;
}

 signal信号处理相关函数

头文件: #include <signal.h>

        typedef void (*sighandler_t)(int);

        sighandler_t   signal(int signum, sighandler_t handler)

功能:信号处理函数(注册信号)

参数: int signum:要处理的信号(要修改的信号)

           sighandler_t handler: 函数指针: void(*handler)(int) (修改的功能:)

           handler:------void handler(int num) 自定义的信号处理函数指针

返回值: 成功:设置之前的信号处理方式

失败:   SIG_ERR

 五.IO多路复用

帮助TCP实现并发服务器

特点:

  1. 进程中若需要同时处理多路输入输出 ,在使用单进程和单线程的情况下, 可使用IO多路复用处理多个请求;
  2. IO多路复用不需要创建新的进程和线程, 有效减少了系统的资源开销。

就比如服务员给50个顾客点餐,分两步:

       顾客思考要吃什么(等待客户端数据发送)

       顾客想好了,开始点餐(接收客户端数据)

要提高效率有几种方法? 

  1.  安排50个服务员   (类似于多进程/多线程实现服务器连接多个客户端,太占用资源)
  2. 哪个顾客想好了吃啥, 那个顾客来柜台点菜 (类似IO多路复用机制实现并发服务器)

 实现IO多路复用的方式:  select   poll   epoll

六.Linux四种IO模型对比

linux下的四种IO模型假设:

假设妈妈有一个孩子,孩子在房间里睡觉,妈妈需要及时获知孩子是否醒了,如何做?

  阻塞式IO:    进到房间陪孩子一起睡觉,孩子醒了吵醒妈妈,不累,但是不能干别的了

  非阻塞式IO: 时不时进房间看一下:简单,空闲时间还能干点别的,但是很累

  信号驱动IO:  妈妈在客厅干活,小孩醒了他会自己走出房门告诉妈妈:互不耽误

假设妈妈有三个孩子, 分别在不同房间睡觉, 需要及时检测每个房间信息, 如何做?

   阻塞式IO:  阻塞处理多条路, 得不到该目的;

   非阻塞IO:  一直轮询, 大量占用CPU;

   多线程多进程, 或IO多路复用, 可以做到; 

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

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

相关文章

C语言 模拟计算器 版本更迭

简单版 ​ //模拟计算器&#xff1a; void menu() {printf("*****************************************\n");printf("************ 1.add 2.sub ***********\n");printf("************ 3.mul 4.div ***********\n");printf("**…

vscode 当中vue 全局自定义组件没有提示以及一些技巧

阅读技术文章可以查漏补缺&#xff0c;借鉴别人编码方式提高代码水平 阅读优秀项目 可以扩展业务处理能力 坚持每天阅读&#xff0c;每天学习新东西 积少成多&#xff0c;水到渠成 在写项目时候&#xff0c;我全局注册了组件&#xff0c;YhSwitch&#xff0c;但是在使用时候&am…

dart包的创建

浅讲dart包(Packages)的创建 创建 package 在 Dart 生态系统中使用 packages 实现共享软件&#xff0c;比如一些库和工具。本章将通过最常见的 Package 来介绍如何创建一个 Package。 若要为 package 创建一个初始化的目录和结构&#xff0c;使用 dart create 命令&#xff…

MySQL数据库技术笔记(2)

对于数据库表中列的增加的命令 : alter table 表名 add 列名 数据类型 [first|after 指定的列名 ] ; 例如 : 在 student 表中增加一列家庭地址&#xff0c;排列在手机号这一列的后面。 alter table student add address varchar(100) after phone; 调整数据库表中列的顺序…

王道数据结构C语言循环链表基本操作实现

文章目录 一、循环单链表1.1初始化及判空操作1.2判断是否是尾结点 二、循环双链表2.1初始化2.2判空2.3判断尾结点2.4循环双链表的删除 一、循环单链表 1.1初始化及判空操作 其实循环链表就是在单链表&#xff08;双链表&#xff09;上做一点小小的优化 它是把尾结点的next指…

广西建筑模板施工中的常见问题及解决方法

广西建筑模板施工中的常见问题及解决方法在广西建筑模板的施工过程中&#xff0c;可能会出现一些常见的质量问题。以下是常见问题及其解决方法&#xff0c;以帮助您更好地处理这些问题。 1. 透胶问题&#xff1a;透胶是指模板中出现胶水渗透的现象。可能的原因包括单板质量差、…

设备树的理解与运用

设备树&#xff1a; 本质是一个文件&#xff0c;包含很多节点&#xff0c;每个节点里边是对设备属性的描述&#xff08;包括GPIO&#xff0c;时钟&#xff0c;中断等等&#xff09;,其中节点&#xff08;node&#xff09;和属性&#xff08;property&#xff09;就是设备树最重…

mysql数据库数据如何迁移目录

目录 1.关闭正在运行mysql2.找到本机my.ini 文件3.观察目录结构4.复制注意是复制Data文件夹到目的地5.找到my.ini初始位置修改数据路径并保存6.启动mysql7.关注my.ini 常用配置 1.关闭正在运行mysql 2.找到本机my.ini 文件 默认位置 C:\ProgramData\MySQL\MySQL Server 8.0 …

如果你是独立开发者,你是先写前端还是先写后端?

当我们站在独立开发的路口时&#xff0c;一个重要的抉择就摆在了我们面前&#xff1a;是先着手前端开发还是后端开发&#xff1f;这看似简单的问题&#xff0c;却蕴含着许多深刻的考虑和决策。无论你是准备构建一个复杂的分布式系统还是一个引人入胜的用户界面&#xff0c;接下…

LeetCode每日一题:1462. 课程表 IV(2023.9.12 C++)

目录 1462. 课程表 IV 题目描述&#xff1a; 实现代码与解析&#xff1a; 拓扑排序 原理思路&#xff1a; 1462. 课程表 IV 题目描述&#xff1a; 你总共需要上 numCourses 门课&#xff0c;课程编号依次为 0 到 numCourses-1 。你会得到一个数组 prerequisite &#xff…

分布式文件系统对比与选型参考

目录 一、分布式文件系统 1、 数据的存储方式&#xff1a; 2、 数据的读取速率 3、 数据的安全机制 二、主流分布式文件系统介绍 1. GFS&#xff08;Google File System&#xff09; 2. HDFS&#xff08;Hadoop Distributed File System&#xff09; 3. Ceph …

java在mysql中查询内容无法塞入实体类中,报错 all elements are null

目录 一、问题描述二、解决方案 一、问题描述 java项目中整体配置了mysql的驼峰式字段匹配规则。 mybatis.configuration.map-underscore-to-camel-casetrue由于项目需求&#xff0c;需要返回字段为file_id&#xff0c;file_url&#xff0c;并且放入实体类中&#xff0c;实体…

对话大模型中的情感支持及商业化落地

在1982年经典科幻电影《银翼杀手》中&#xff0c;仿生人瑞秋因为被植入记忆而以为自己是真人&#xff0c;当被告知自己是仿生人时&#xff0c;她拒绝相信&#xff0c;流下了眼泪。如今&#xff0c;随着AI领域对话大模型技术的发展&#xff0c;“比人更像真人”的人工智能正从梦…

vue实现左右伸缩(el-drawer自定义位置展开收缩)

内容左右收缩展开 实现需求实现效果自定义抽屉(el-drawer)展开位置实现原理 js方法&#xff0c;点击的时候抽屉伸缩展开&#xff0c;并且给左侧右侧内容对应的宽度第二种方法 实现需求 页面内容是左右布局&#xff0c;需求想让左侧内容可收缩&#xff0c;然后展示完全右侧内容。…

模拟经营类游戏是怎么开发的?

模拟经营类游戏开发是一个充满挑战但也充满乐趣的领域。下面是一些步骤和关键考虑因素&#xff0c;可以帮助您开始开发自己的模拟经营游戏&#xff1a; 明确游戏概念&#xff1a; 确定游戏开发的主题和类型&#xff0c;例如城市建设、农场经营、餐厅经营等。 制定一个引人入胜…

《论文阅读》通过动态融入常识知识来提高同理心对话的生成

《论文阅读》通过动态融入常识知识来提高同理心对话的生成 前言简介模型架构Contextual ProbingContextual Unification Workspace代码实现Knowledge-Aware Decoder实验结果前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到…

文件路径中的/,\的区别和文件路径的常见用法

/是Unix和类Unix系统上的路径分隔符.现代Windows通常可以同时使用\和/交换文件路径,但微软\几十年来一直主张使用路径分隔符. 关于文件路径的常用方法再学习一下&#xff1a; "./"&#xff1a;代表目前所在的目录 "../"&#xff1a;代表上一层目录 以&q…

如何在Blender中压缩/减小GLTF模型的大小

GLTF 如何在Blender中压缩/减小GLTF模型的大小 Blender是一款功能强大的开源软件&#xff0c;旨在创建3D图形&#xff0c;动画和视觉效果。它支持多种文件格式的导入和导出&#xff0c;包括GLB&#xff0c;GLTF&#xff0c;DAE&#xff0c;OBJ&#xff0c;ABC&#xff0c;USD…

CAD批量转换低版本怎么转?教你一看就会的转换方法

CAD文件需要转换版本是因为不同版本的CAD软件可能不兼容。这意味着&#xff0c;如果在一个版本的CAD软件中创建了一个文件&#xff0c;可能无法在另一个版本的CAD软件中打开它。这可能会导致数据丢失或格式错误。 为了避免这种情况&#xff0c;需要将CAD文件转换为适当的版本以…

短视频seo矩阵系统源码开发与部署全解析

在这个数字化快速发展的时代&#xff0c;短视频已经成为人们获取娱乐&#xff0c;学习&#xff0c;商业信息的主要途径之一。对于企业来说&#xff0c;利用短视频矩阵进行高效且精准的营销推广&#xff0c;无疑是一个重要的战略方向。本文将详细介绍如何进行短视频矩阵源码的开…