Linux-笔记 高级I/O操作

news2024/11/20 20:34:45

前言

        I/O(Input/Output,输入/输出)是计算机系统中的一个重要组成部分,它是指计算机与 外部世界之间的信息交流过程。I/O 操作是计算机系统中的一种基本操作,用于向外部设备(如 硬盘、键盘、鼠标、网络等)读取数据或向外部设备写入数据。

        常见的I/O操作方式:

        1)同步 I/O(Synchronous I/O):在进行 I/O 操作时,程序会一直等待操作完成后再 继续执行后面的代码。如果 I/O 操作阻塞,程序会一直等待,直到操作完成或超时。

        2)异步 I/O(Asynchronous I/O):在进行 I/O 操作时,程序会立即返回,而不必等待 操作完成。当操作完成后,操作系统会通知程序。这种方式可以允许程序在等待 I/O 操作完 成的同时执行其他代码。

        3)阻塞 I/O(Blocking I/O):在进行 I/O 操作时,程序会一直等待操作完成后再继续执行后面的代码。如果 I/O 操作阻塞,程序会一直等待,直到操作完成或超时。阻塞 I/O 是 同步 I/O 的一种。

        4)非阻塞 I/O(Non-blocking I/O):在进行 I/O 操作时,程序会立即返回,而不必等待操作完成。如果 I/O 操作无法立即完成,程序也会立即返回,但是会周期性地检查操作是否完成。非阻塞 I/O 是同步 I/O 的一种。

        5)I/O 多路复用(I/O Multiplexing):是一种同时监视多个 I/O 事件的机制,通常使用select、poll、epoll 等系统调用。程序通过这些调用告知操作系统它要监视哪些 I/O 事件,当有 I/O 事件发生时,操作系统通知程序,并返回发生事件的描述符。I/O 多路复用通常是异步 I/O 模型的一部分。

阻塞I/O与非阻塞I/O

        阻塞和非阻塞的主要区别在于程序在进行 I/O 操作时是否会被阻塞。在实际应用中,阻塞 I/O 的使用场景较为有限,因为阻塞 I/O 会导致程序性能下降,会造成资源浪费。非阻塞 I/O 则可以较好地解决这个问题,但需要程序周期性地检查 I/O 操作是否完成,增加了编程难度。

接下来通过几个小实验来区分阻塞I/O与非阻塞I/O的区别。

       1)阻塞I/O读取鼠标的数据,运行后发现不动鼠标就会一直阻塞直到移动鼠标,这就是阻塞I/O的特点。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void) 
{
    char buf[1024];
    int fd, ret;

    fd = open("/dev/input/event2", O_RDONLY);
    if (-1 == fd) {
        perror("open error \r\n");
        exit(-1);
    }

    memset(buf, 0, sizeof(buf));
    ret = read(fd, buf, sizeof(buf));
    if (0 > ret) {
        perror("read error \r\n");
        close(fd);
        exit(-1);
    }

    printf("读到:%d\r\n", ret);

    close(fd);
    exit(0);
}

        2)非阻塞I/O读取鼠标数据,发现运行后立刻结束了程序,并输出了一些错误信息,提示信息为"Resource temporarily unavailable",意思就是说资源暂时不可用;原因在于调用 read()时,如果鼠标并没有移动或者被按下(没有 发生输入事件),是没有数据可读,故而导致失败返回,这就是非阻塞 I/O。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void) 
{
    char buf[1024];
    int fd, ret;

    fd = open("/dev/input/event2", O_RDONLY | O_NONBLOCK);
    if (-1 == fd) {
        perror("open error \r\n");
        exit(-1);
    }

    memset(buf, 0, sizeof(buf));
    ret = read(fd, buf, sizeof(buf));
    if (0 > ret) {
        perror("read error \r\n");
        close(fd);
        exit(-1);
    }

    printf("读到:%d\r\n", ret);

    close(fd);
    exit(0);
}

                

        3)通过非阻塞I/O+轮询读取鼠标数据,可以发现采用非阻塞方式也会停留住,等到移动鼠标才退出程序,这样虽然可行但是会占用很高的CPU使用率。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
    char buf[1024];
    int fd, ret;

    fd = open("/dev/input/event2", O_RDONLY | O_NONBLOCK);
    if (-1 == fd)
    {
        perror("open error \r\n");
        exit(-1);
    }

    memset(buf, 0, sizeof(buf));
    for (;;)
    {
        ret = read(fd, buf, sizeof(buf));
        if (0 < ret)
        {
            printf("成功读取<%d>个字节数据\n", ret);
            close(fd);
            exit(0);
        }
    }
    printf("读到:%d\r\n", ret);

    close(fd);
    exit(0);
}

        4)通过对比发现阻塞式 I/O 的优点在于能够提升 CPU 的处理效率,当自身条件不满足时,进入阻塞状态,交出 CPU 资源,将 CPU 资源让给别人使用;而非阻塞式则是抓紧利用 CPU 资源,譬如不断地去轮训,这样就会导致 该程序占用了非常高的 CPU 使用率!

        但是阻塞I/O也有缺点,我们都知道使用阻塞I/O会在没获取到鼠标移动数据的时候会阻塞,那么如果我在读取鼠标数据之后还有很多任务呢,那我一直不移动鼠标后面的任务就不用完成了吗,肯定不是。虽然我们可以通过创建多个线程去解决这个问题,但是也可以尝试其他办法,比如使用fcntl函数。

        5)使用fcntl函数

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

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

相关文章

服务器数据恢复—异常断电导致RAID6阵列中磁盘出现坏扇区的数据恢复案例

服务器存储数据恢复环境&#xff1a; 一台存储中有一组由12块SAS硬盘组建的RAID6磁盘阵列&#xff0c;划分为一个卷&#xff0c;分配给几台Vmware ESXI主机做共享存储。该卷中存放了大量Windows虚拟机&#xff0c;这些虚拟机系统盘是统一大小&#xff0c;数据盘大小不确定&…

服务器硬件及RAID配置

目录 一、RAID磁盘阵列 1.概念 2.RAID 0 3.RAID 1 4.RAID 5 5.RAID 6 6.RAID 10 二、阵列卡 1.简介 2.缓存 三、创建 1.创建RAID 0 2.创建RAID 1 3.创建RAID 5 4.创建RAID 10 四、模拟故障 一、RAID磁盘阵列 1.概念 &#xff08;1&#xff09;是Redundant Array …

求任意方阵每行,每列,两对角线上元素之和

注&#xff1a;其中对角线&#xff0c;我们可以分为正副两个&#xff0c;正&#xff1a;左上角指向右下角&#xff0c;副&#xff1a;右上角指向左下角 //这里我们以阶层为5为例子进行代码的实现 #define N 5 void arr_diagonal(int arr[N][N]) {int sum1 0, sum2 0, sum 0…

Js逆向爬虫基础篇

这里写自定义目录标题 逆向技巧断点一 、请求入口定位1. 关键字搜索2. 请求堆栈3. hook4. JSON.stringify 二、响应入口定位&#xff1a;1. 关键字搜索2. hook3. JSON.parse 逆向技巧 断点 普通断点 条件断点 日志断点 XHR断点 一 、请求入口定位 1. 关键字搜索 key关…

C++ | Leetcode C++题解之第198题打家劫舍

题目&#xff1a; 题解&#xff1a; class Solution { public:int rob(vector<int>& nums) {if (nums.empty()) {return 0;}int size nums.size();if (size 1) {return nums[0];}int first nums[0], second max(nums[0], nums[1]);for (int i 2; i < size; …

10.XSS绕过之htmlspecialchars()函数

XSS绕过之htmlspecialchars()函数 首先可以测试一下是否将字符被转移成html实体&#xff0c;输入字符测试 1111"<>$点击提交 查看页面元素代码&#xff0c;发现单引号不变&#xff0c;可以利用 重新输入攻击代码&#xff0c;用单引号闭合前面的&#xff0c;进…

深圳大学 软件测试作业 #2

声明&#xff1a;本人上课摆烂选手&#xff0c;稍微听了下&#xff0c;答案仅供参考。 ———————— 1. 考虑下面这个代码&#xff0c;并回答以下的问题。 (a) 请画出上面代码的控制流程图。(20分) (b) 请画出上面代码的数据流程图。(10分) (c) 找出每个变量的定义使…

SpringBoot整合Mybatis并实现数据库增删改查

写在前面 Mybatis一个基于Java的持久层框架&#xff0c;它通过XML或注解的方式&#xff0c;将SQL语句和Java方法进行映射&#xff0c;使得开发者可以轻松地进行数据库操作。下面我会演示mybatis的配置与使用并实现数据库的增删改查。 1.准备测试数据 使用mybatis实现对数据库…

Java银系统/超市收银系统/智慧新零售/ERP进销存管理/线上商城/h5/小程序

>>>系统简述&#xff1a; 神点收银系统支持B2B2C多商户模式&#xff0c;系统基于前后端分离的架构&#xff0c;后端采用Java SpringBoot Mysql Mybatis Plus&#xff0c;前端基于当前流行的Uniapp、Element UI&#xff0c;支持小程序、h5。架构包含&#xff1a;会员端…

AI智能写作工具,AI写作助手大全

随着人工智能技术的快速发展&#xff0c;AI智能写作工具助手已成为学术研究、内容创作和商业文案等领域的重要辅助工具。它们不仅能够提高写作效率&#xff0c;还能激发创意灵感&#xff0c;为各行各业的专业人士提供了强大的支持。下面小编将为大家全面介绍目前市场上备受瞩目…

Mac(M1芯片)安装多个jdk,Mac卸载jdk

1.jdk下载 oracle官方链接&#xff1a;oracle官方下载链接 2.安装 直接下一步&#xff0c;下一步就行 3.查看是否安装成功 出现下图内容表示安装成功。 4.配置环境变量 open -e .bash_profile 路径建议复制过去 #刷新环境变量 source ~/.bash_profile 5.切换方法 6.jdk…

HTML+CSS 彩色浮雕按钮

效果演示 实现了一个彩色按钮特效&#xff0c;包括一个按钮&#xff08;button&#xff09;和一个前景色&#xff08;::before&#xff09;。按钮具有四种不同的颜色&#xff0c;当鼠标悬停在按钮上时&#xff0c;前景色会出现渐变效果&#xff0c;并且按钮的颜色、文本阴影和边…

【研究】AI大模型需要什么样的硬件?

关注AI大模型 x 硬件的两条思路 从22年11月OpenAI推出ChatGPT至今&#xff0c;我们看到Chatbot应用的能力不断增强&#xff0c;从最初的文字问答&#xff0c;迅速向具有自主记忆、推理、规划和执行的全自动能力的AI Agent发展。我们认为端侧智能是大模型发展的重要分支。建议投…

昇思25天学习打卡营第二天|张量

张量 Tensor 张量&#xff08;Tensor&#xff09;是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数&#xff0c;这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 &#x1d45b;&#x1d45b; 维空间内&#xff0c;有  &#x1…

北尔Beijer软件iXDeveloper2触摸屏和使用说明手侧

北尔Beijer软件iXDeveloper2触摸屏和使用说明手侧

Python笔记 文件的写,追加,备份操作

一、文件的写操作 案例演示&#xff1a; # 1.打开文件 f open(python.txt,w)# 2.文件写入 f.write(hello world)# 3.内容刷新 f.flush() 注意&#xff1a; 直接调用write&#xff0c;内容并为真正的写入文件&#xff0c;二十会积攒在程序的内存中&#xff0c;称之为缓冲区…

SpringBoot控制反转和依赖注入

目录 一、内聚和耦合 二、分层解耦 三、具体实现 四、bean的组件扫描 五、bean注入 一、内聚和耦合 在了解分层解耦的概念之前我们我们要去先了解一下内聚和耦合。内聚&#xff1a;通常将的是软件中各个模块之间的功能联系。耦合衡量软件各个模块之间的依赖、关联的程度。一…

Lua网站开发之文件表单上传

这个代码示例演示如何上传文件或图片&#xff0c;获取上传信息及保存文件到本地。 local fw require("fastweb") local request require("fastweb.request") local response require("fastweb.response") local cjson require("cjson&q…

30-33、SpringBoot项目部署\属性配置方式\多环境开发(一个文件)\多环境分组(多个文件)

1、打包插件:和springboot的版本保持一致 根pom <build><plugins><!--打包插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.1.3</versi…

期末复习题中的问题

一、编程中&#xff08;包括函数&#xff09;的问题 1. malloc 头文件是stdlib.h 二、第二次写复习题的不会的 三、程序填空 总结&#xff1a; 删除节点m >>>>要有一个指针来遍历找到这个m >>>> 用另一个指针指向这个指针的下一 个 >>&…