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

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.mzph.cn/news/838917.shtml

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

相关文章

浏览器API与协议

现代浏览器是一个囊括了数百个组件的操作系统&#xff0c;包括进程管理、安全沙箱、分层的优化缓存、JavaScript虚拟机、图形渲染和GPU管道、存储系统、传感器、音频和视频&#xff0c;网络机制等等。 在浏览器上运行的应用的性能。&#xff0c;取决于多个组件&#xff1a;解析…

notepad++ 批量转所有文件编码格式为UTF-8

1、安装notepad及PythonScript_3.0.18.0插件 建议两者都保持默认路径安装x64版本&#xff1a; 阿里云盘分享https://www.alipan.com/s/xVUDpY8v5QL安装好后如下图&#xff1a; 2、new Script&#xff0c;新建脚本&#xff0c;文件名为ConvertEncoding 3、自动打开脚本&#xff…

YOLOV8 如何训练自己的数据

1、git code 项目 地址 2、数据标注&#xff1a;使用yolov8官方推荐的roboflow 地址 2.1 上传数据 2.2 标注 2.3 生成数据集 2.4 导出数据 3 训练 3.1 建.yaml 文件 建立.yaml 文件 3.2 修改.yaml文件里面的内容 1.这是roboflow 网站下下来的数据&#xff0c;只需要把.…

MySQL中锁的几种类型

MySQL根据加锁的范围&#xff0c;可以分为全局锁、表级锁、行级锁三类。 2.5.1. 锁定读 2.5.1.1. 共享锁和独占锁 事务的 读-读 情况并不会引起什么问题&#xff0c;对于 写-写、读-写 或 写-读 这些情况可能会引起一些问题&#xff0c;需要使用MVCC或者加锁的方式来解决。在…

15:00面试,15:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

MySQL数据库下的Explain命令深度解析

Explain是一个非常有的命令&#xff0c;可以用来获取关于查询执行计划的信息&#xff0c;以及如何解释输出。Explain命令是查看查询优化器如何决定执行查询的主要方法。这个功能有一定的局限性&#xff0c;并不总是会说出真相&#xff0c;但是它的输出是可以获取的最好信息&…

Kubernetes集群上的Etcd备份和恢复

在本教程中&#xff0c;您将学习如何在Kubernetes集群上使用etcd快照进行etcd备份和恢复。 在Kubernetes架构中&#xff0c;etcd是集群的重要组成部分。所有集群对象及其状态都存储在etcd中。为了更好地理解Kubernetes&#xff0c;有几点关于etcd的信息是您需要了解的。 它是…

【探索数据结构】线性表之双链表

&#x1f389;&#x1f389;&#x1f389;欢迎莅临我的博客空间&#xff0c;我是池央&#xff0c;一个对C和数据结构怀有无限热忱的探索者。&#x1f64c; &#x1f338;&#x1f338;&#x1f338;这里是我分享C/C编程、数据结构应用的乐园✨ &#x1f388;&#x1f388;&…

【超全干货】一文讲清什么是全民分销?怎么做好全民分销?

一、什么是全民分销&#xff1f; 全民分销&#xff0c;作为新时代营销模式的代表之一&#xff0c;是基于互联网尤其是社交媒体平台兴起的一种分销策略。它打破了传统零售与电子商务的界限&#xff0c;允许任何个人&#xff0c;无论是否为专业销售人员&#xff0c;都能成为品牌…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第27课-门的打开

【WEB前端2024】开源智体世界&#xff1a;乔布斯3D纪念馆-第27课-门的打开 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎&am…

FreeRTOS_互斥量_学习笔记

互斥量 数值只有0或1 谁获得互斥量&#xff0c;就必须由谁释放同一个互斥量。 但其实在freeRTOS中&#xff0c;任务A获取的互斥锁&#xff0c;任务B也能释放。因此谁上锁谁开锁只是约定&#xff0c;在程序实现上不是强制的。 “可重入的函数"是指&#xff1a;多个任务同时…

Qt输入输出类使用总结

Qt输入输出类简介 QTextStream 类(文本流)和 QDataStream 类(数据流)Qt 输入输出的两个核心类,其作用分别如下: QTextStream 类:用于对数据进行文本格式的读/写操作,可在 QString、QIODevice或 QByteArray 上运行,比如把数据输出到 QString、QIODevice 或 QByteArray 对象…

Linux-文件或目录权限

在使用 ll 时&#xff0c;可以查看文件夹内容的详细信息&#xff0c;信息的第1位表示类型&#xff0c;具体信息如下&#xff1a; 类型说明-普通文件d文件夹b块设备文件c字符设备文件p管道文件s套接口文件 第2-10位表示权限&#xff0c; 举例&#xff1a;rwxr-xr-x 类型说明r…

业务架构核心要素之间的关系

背景 前面已经对业务架构的概念和发展简史有了初步的了解&#xff0c;现在主流的业务架构就是价值流能力&#xff0c;在这套架构体系中&#xff0c;有四个核心元素&#xff0c;分别是价值流、业务能力、信息、组织。 这四个核心元素&#xff0c;特别是对于价值流以及业务能力…

查看主机的php参数short_open_tag 是否为 on

我想要查看主机的php参数short_open_tag 是否为 on&#xff0c;由于我使用的是Hostease的Linux虚拟主机产品&#xff0c;在cPanel面板中并没有找到这个参数选项&#xff0c;因此无法查看。这边联系了Hostease技术支持了解&#xff0c;可以通过以下方式进行查看。 1.先登陆cPane…

Shell编程之条件判断语句

目录 一、条件判断 1、test命令 2、文件测试 3、整数值比较 4、字符串判断 5、逻辑测试 二、if语句 1、if单分支语句 2、双分支语句 3、多分之语句 4、case 分支语句 一、条件判断 Shell环境根据命令执行后的返回状态值&#xff08;echo $?&#xff09;来判断是否执行成…

鸿蒙HarmonyOS开发中的易混点归纳-持续补充中

相关文章目录 鸿蒙HarmonyOS开发术语全解&#xff1a;小白也能看懂&#xff01; 文章目录 相关文章目录前言一、build()函数和Builder装饰器&#xff1f;二、自定义组件和系统组件&#xff08;内置组件&#xff09;三、组件和页面四、自定义弹窗和其他弹窗总结 前言 一、build…

SpringBoot(五)之新增注解

SpringBoot&#xff08;五&#xff09;之新增注解 文章目录 SpringBoot&#xff08;五&#xff09;之新增注解核心注解EnableAutoConfiguration**SpringBootApplication** 条件注解Spring原生Conditional注解手写Conditional注解**ConditionalOnProperty****ConditionalOnMissi…

Logrus IT的供应商经理如何找到优秀地翻译人员

在现代世界&#xff0c;翻译和本地化可以使企业打入新市场并与来自不同国家的客户互动&#xff0c;从而对企业的成功起到决定性作用。翻译过程中的一个关键部分是寻找和招聘翻译。在Logrus IT&#xff0c;这是Anna Gulenkova的工作&#xff0c;我们决定和她谈谈她是如何做到的。…

BUUCTF---misc---我吃三明治

1、下载附件是一张图片 2、在winhex分析&#xff0c;看到一串整齐的编码有点可疑&#xff0c;保存下来&#xff0c;拿去解码&#xff0c;发现解不了&#xff0c;看来思路不对 3、再仔细往下看的时候也发现了一处这样的编码&#xff0c;但是这次编码后面多了一段base编码 4、拿去…