嵌入式学习——3——IO分类模型

news2024/11/20 12:24:49

1、阻塞IO和非阻塞IO

1.1 阻塞IO

 - 在阻塞IO模型中,当一个IO操作(如读取或写入)开始时,如果数据没有准备好,程序会被挂起(即阻塞),直到数据准备好并且IO操作完成。

   - 在数据准备阶段,程序做不了其他事情,它会等待在那里直到整个IO操作完全完成后才会继续执行。

   - 阻塞IO简化了编程模型,因为在发起IO请求之后,你只需要等待结果,不必担心在这个过程中如何处理其他任务。

1.2 非阻塞IO

 - 非阻塞IO模型中,IO操作不会导致程序挂起等待。如果数据没有准备好,IO调用会立即返回一个指示数据尚未准备好的状态。

   - 程序可以继续执行后续代码,它可以定期地检查IO操作是否可以进行,或者可以进行其他工作,这样很好地利用了等待时间。该过程称为 polling 。

   - 非阻塞IO通常与事件驱动或轮询机制一起使用,程序可以在多个IO操作之间有效地切换,提高了程序的整体效率和响应性。

非阻塞IO更适用于处理高并发情况,尤其在需要同时管理多个连接或者进行多个并行IO操作时。但这种模型编程难度较高,因为要管理和调度多个IO操作,而且可能需要额外的机制(如IO复用或事件通知)来检测IO状态。

1.3 如何将阻塞IO更改成非阻塞IO

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

功能:获取或者设置当前文件描述符的属性和状态,是哪一种操作取决于cmd

fd:要处理的文件描述符

cmd: 要执行的操作

        F_GETFL:  获取文件描述符的属性,第三个参数可以忽略

        F_SETFL:设置文件描述符的属性,第三个参数为int

是否设置参数3,取决于参数2,如果参数2为 F_SETFL,参数3就是为当前文件描述符设置的值

返回值:取决于cmd

        如果cmd 为F_GETFL,则成功返回当前文件描述符的属性值,失败返回-1并置位错误码

        如果cmd 为 F_SETFL,则成功返回0,失败返回-1并置位错误码

步骤:

1、先获取当前文件描述符的属性

        int flag = fcntl(fd, F_GETFL);

2、将当前的文件描述符的属性中,添加非阻塞属性

        flag |= O_NONBLOCK;

3、将更改后的状态加到当前文件描述符中

        fcntl(fd, F_SETFL, flag);

int main(int argc, const char *argv[])
{
    int num = 0;

    //1、获取当前文件描述的属性
    int flag = fcntl(0, F_GETFL);

    //2、给当前的文件描述符加上非阻塞属性
    flag |= O_NONBLOCK;

    //3、再将新属性设置回去
    fcntl(0, F_SETFL, flag);

    while(1)
    {
        printf("请输入:");
        scanf("%d", &num);

        //此处省略一万行代码
        printf("num = %d\n", num);
    }

    return 0;
}

2、IO多路复用

2.1 IO多路复用的相关概念

1、如果程序中需要同时处理多个阻塞任务时,在使用单进程或单线程的情况下,可以处理多个阻塞任务

2、在无法使用多进程或多线程时,还想完成多任务并发,此时可以使用IO多路复用技术

3、优点:由于不需要多进程或多线程,能够有效减少系统的资源开销,减少上下文切换的次数,效率较高

4、原理图

2.2 select

#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

功能:阻塞等待检测容器中是否有事件产生,如果有一个或多个事件产生,则解除阻塞,并且将没有产生事件的文件描述符从集合中清除

参数1:检测集合中最大的文件描述符的值 + 1

参数2、3、4:分别是读、写、异常检测的文件描述符集合,如果不用,可以填NULL

参数5:超时时间,可以是如下的结构体变量的地址,也可以填NULL,表示永久等待

struct timeval {

        long tv_sec; /* seconds */

        long tv_usec; /* microseconds */

};

and

struct timespec {

        long tv_sec; /* seconds */

        long tv_nsec; /* nanoseconds */

};

返回值: 

        >0     表示本次解除阻塞触发事件的文件描述符总个数

        =0     表示设置的超时时间,并超时时间内没有事件产生

        =-1    出错,置位错误码

四个宏函数,用于对文件描述符集合的操作

        void FD_CLR(int fd, fd_set *set);         // 将fd文件描述符从集合set中移除

        int FD_ISSET(int fd, fd_set *set);         // 判断fd文件描述符是否存在于set集合中

        void FD_SET(int fd, fd_set *set);         // 将fd文件描述符添加到set集合中

        void FD_ZERO(fd_set *set);         // 将set文件描述符集合清空

使用select实现TCP并发服务器--框架

int main(){

        sfd = socket();      // 创建用于连接的套接字

        bind();                   // 绑定ip和端口号

        listen();                 // 将套接字设置成被动监听状态

        fd_set readfds, tempfds;

        FD_ZERO(&readfds)

        FD_SET(sfd, &readfds);

        int max = sfd;

        while(1){

                tempfds = readfds;

                select(max+1, &tempfds, NULL, NULL,NULL); //阻塞检测集合中文件描述符

                                                                                                是否有事件产生

                for(int i = 0; i <= max; i++){

                        if(!FD_ISSET(i, &tempfds)){

                                continue;

                        }

                        if(i == sfd){

                                newfd = accept()

                                FD_SET(newfd ,&readfds );

                                max = max > newfd ? max : newfd;

                        }else{

                                recv()

                                send()

                                (下线关闭)close(i)

                                FD_CLR(i, &readfds);

                                //更新max

                                 for(j = max; j >= sfd; j--){

                                        if(FD_ISSET(j, &tempfds)){

                                                max = j;

                                        }

                                }

                        }

                }

        }

        close(sfd);

}

2.3 poll

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

功能:阻塞等待文件描述符集合中是否有事件产生,如果有事件产生,则解除阻塞

参数1:文件描述符集合数组,是一个结构体数组

                struct pollfd {

                        int fd; /* 要检测的文件描述符 */

                        short events; /* 要检测的事件 */

                        short revents; /* 真实发生的事件 */  该值无需初始化,poll函数会给

                                                        该参数赋值

                };

常用事件种类:

          POLLIN:读事件

          POLLOUT:写事件

参数2:集合中文件描述符的个数

参数3:以毫秒为单位的超时时间

                >0:        表示设置的超时时间

                =0:      表示非阻塞

                <0:        表示永久阻塞

返回值:

                >0:        表示返回解除阻塞的事件对应的文件描述符个数

                =0:        表示超时

                <0:        失败,置位错误码

poll完成TCP客户端中发送数据和接收数据的并发执行

int main(){

        cfd = socket();

        bind()

        connect();

        // 使用poll 完成 多阻塞任务的并发

        struct pollfd pfd[2];               //  定义一个2长度的结构体数组  

        pfd[0].fd = 0;                        //  表示检测0号(stdin)文件描述符

        pfd[0].events = POLLIN;      //  表示检测事件

        

        pfd[1].fd = cfd;                      //  表示检测cfd文件描述符

        pfd[1].events = POLLIN;       //  表示检测事件

        

        while(1){

                int res = poll(pfd, 2, -1);

                if (res == -1){

                        perror("poll error");

                        return -1;

                }else if (res == 0){

                        printf("time out\n");

                        return -1;

                }

                //判断是否为0号文件描述符产生的事件

                if(pfd[0].revents == POLLIN){

                }

                //判断是否为cfd文件描述符产生事件

                 if(pfd[1].revents == POLLIN){

                        recv()

                }

        }        

        close(cfd)

         return 0;

}

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

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

相关文章

sql server【 特定分隔符隔开的字符串转表】和【 列转逗号隔开的字符串】

文章目录 引言I 特定分隔符隔开的字符串转表II Sql Server 列转逗号隔开的字符串2.1 多列转行,逗号分隔(字段拼接/字段分割)2.1 案例引言 Sql Server 列转逗号隔开的字符串 和 逆转,常用于数据导出和数据查询。 I 特定分隔符隔开的字符串转表 CREATE FUNCTION [dbo].[GetIDLi…

LitCTF

[LitCTF 2023]enbase64 base 64 里面有一个换表的函数 写代码 #include<stdio.h> #include<string.h> #include<stdlib.h> int main() {char *result; char Destination[65]; int v3[65];int j;int i; char Source[]"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde…

【配置】雷池WAF社区版安装

官方文档点击跳转 什么是雷池 雷池&#xff08;SafeLine&#xff09;是长亭科技耗时近 10 年倾情打造的 WAF&#xff0c;核心检测能力由智能语义分析算法驱动。 什么是 WAF WAF 是 Web Application Firewall 的缩写&#xff0c;也被称为 Web 应用防火墙。 区别于传统防火墙…

MySql--SQL语言

目录 SQl---DDL 结构定义 创建、删除 数据库 代码 运行 设计表 数据类型 整数 浮点数 主键 约束 主键自增长 默认值 字段注释 创建、删除 表 代码 运行 代码 代码 运行 SQL---DML 数据操纵 插入数据 代码 运行 代码 运行 代码 运行 代码 …

sqlserver查看索引碎片,并整理

DBCC SHOWCONTIG WITH ALL_INDEXES --查看所有表的索引碎片情况 DBCC SHOWCONTIG(fq_viewvform) --指定表索引碎片情况 dbcc dbreindex(fq_viewvform) --重建表索引 DBCC SHOWCONTIG(fq_viewvform) --检查重建后表索引碎片情况 查看全库索引碎片情况&#xff1a; 查看单表索引…

H800基础能力测试

H800基础能力测试 参考链接A100、A800、H100、H800差异H100详细规格H100 TensorCore FP16 理论算力计算公式锁频安装依赖pytorch FP16算力测试cublas FP16算力测试运行cuda-samples 本文记录了H800基础测试步骤及测试结果 参考链接 NVIDIA H100 Tensor Core GPU Architecture…

中国医学健康管理数字化发展风向标——专家共话未来趋势

随着科技的飞速发展&#xff0c;数字化已经成为中国医学健康管理领域的重要发展方向。 2024年5月20日由中国管理科学研究院智联网研究所、中国民族医药协会医养教育委员会、国家卫健委基层健康服务站、中国老龄事业发展基金会、中国智联网健康管理系统平台、中国医学健康管理数…

Postman进阶功能-集合分支管理与编写接口文档

大家好&#xff0c;在接口测试的领域中&#xff0c;我们不断追求更高效、更便捷、更强大的方法与工具。而 Postman 作为一款备受青睐的接口测试工具&#xff0c;其进阶功能更是为我们打开了新的天地。在这其中&#xff0c;集合分支管理与编写接口文档的功能显得尤为重要。 当面…

向上调整建堆与向下调整建堆的时间复杂度 AND TopK问题

目录 前言建堆的时间复杂度TOPK问题总结 前言 本篇旨在介绍使用向上调整建堆与向下调整建堆的时间复杂度. 以及topk问题 博客主页: 酷酷学!!! 感谢关注~ 建堆的时间复杂度 堆排序是一种优于冒泡排序的算法, 那么在进行堆排序之前, 我们需要先创建堆, 为什么说堆排序的是优于…

网络模型-VLAN聚合

VLAN聚合 VLAN聚合(VLAN Aggregation,也称SuperVLAN)指在一个物理网络内&#xff0c;用多个VLAN(称为Sub-VLAN)隔离广播域并将这些Sub-VLAN聚合成一个逻辑的VLAN(称为SuperVLAN)&#xff0c;这些Sub-VLAN使用同一个IP子网和缺省网关&#xff0c;&#xff0c;进而达到节约IP地址…

leetcode_2024年5月19日10:51:26

238.除自身以外各元素的乘积 给你一个整数数组nums&#xff0c;返回数组answer&#xff0c;其中answer[i]等于nums中除nums[i]之外其余各元素的乘积。 题目数据保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32位整数范围内。 请不要使用除法&#xff0c;且在o&am…

Go 切片常用操作与使用技巧

1.什么是切片 在 Go 语言中的切片&#xff08;slice&#xff09;是一种灵活的动态数组&#xff0c;它可以自动扩展和收缩&#xff0c;是 Go 语言中非常重要的数据结构之一。切片是基于数组实现的&#xff0c;它的底层是数组&#xff0c;可以理解为对底层数组的抽象。它会生成一…

智能车竞赛指南:从零到一,驶向自动驾驶的未来

智能车竞赛指南&#xff1a;从零到一&#xff0c;驶向自动驾驶的未来 一、智能车竞赛概览1.1 竞赛介绍1.2 竞赛分类 二、智能车开发技术基础2.1 硬件平台2.2 软件开发 三、实战案例&#xff1a;循线小车开发3.1 系统架构3.2 代码示例 四、技术项目&#xff1a;基于ROS的视觉导航…

一款功能强大的安卓虚拟机应用——VMOS Pro使用分享

前段时间我刚刚分享一个WeChat平板模块能够允许用户自由修改系统设置&#xff0c;让你的Android备用手机焕发新生&#xff0c;实现手机PAD化&#xff0c;实现两台设备同时登录微信号。今天我分享的这个相比WeChat更为简单&#xff0c;因为它可以通过虚拟机的方式进行多种androi…

【Numpy】深入解析numpy.diag()函数

numpy.diag()&#xff1a;深入探索NumPy库中的对角矩阵操作 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f3…

MGRE实验——路由配置

对134环回 ping一下发现都可以通 配置3&#xff0c;4同3 再注册 然后内网要互通&#xff0c;起rip 宣告1的左边和右边 对3 对4 当3&#xff0c;4之间要互通时&#xff0c;首先在1上 关闭之后&#xff0c;3就能学到4上的用户网段&#xff0c;4也能学到3 局域网要访问广域网一定…

Web 3D 框架简介

前言 3D游戏引擎的历史可以追溯到20世纪80年代末和90年代初。当时,计算机技术迅速发展,人们开始对图形和游戏感兴趣。以下是3D游戏引擎的历史故事: 早期引擎的诞生(1980-1990年代) 在这个时期,一些早期的3D游戏引擎开始出现。其中一个著名的例子是id Software开发的Do…

单细胞分析(Signac): PBMC scATAC-seq 聚类

引言 在本教学指南中&#xff0c;我们将探讨由10x Genomics公司提供的人类外周血单核细胞&#xff08;PBMCs&#xff09;的单细胞ATAC-seq数据集。 加载包 首先加载 Signac、Seurat 和我们将用于分析人类数据的其他一些包。 if (!requireNamespace("EnsDb.Hsapiens.v75&qu…

Dijkstra算法在《庆余年》中的应用:范闲的皇宫之旅

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

英语学习笔记24——Give me/us/him/her/them some ...

Give me/us/him/her/them some … 给我/我们/他/她/他们一些…… 词汇 Vocabulary desk n. 课桌&#xff08;有书桌堂&#xff09;&#xff0c;写字台 复数&#xff1a;desks 搭配&#xff1a;desk mate 同桌    构成&#xff1a;desk mate 桌子上的伙伴 同桌    cl…