嵌入式Linux之文件IO

一、标准IO库 

1.1 打开/关闭文件 

fopen

新建 fopen_test.c,写入以下内容:

#include <stdio.h>
int main()
{/* 打开文件函数:FILE *fopen (const char *__restrict __filename,const char *__restrict __modes)参数:char *__restrict __filename: 字符串表示要打开文件的路径和名称char *__restrict __modes: 字符串表示访问模式(1)"r": 只读模式 没有文件打开失败(2)"w": 只写模式 存在文件写入会清空文件,不存在文件则创建新文件(3)"a": 只追加写模式 不会覆盖原有内容 新内容写到末尾,如果文件不存在则创建(4)"r+": 读写模式 文件必须存在 写入是从头一个一个覆盖(5)"w+": 读写模式 可读取,写入同样会清空文件内容,不存在则创建新文件(6)"a+": 读写追加模式 可读取,写入从文件末尾开始,如果文件不存在则创建return: FILE * 结构体指针 表示一个文件*/char *filename = "io.txt";FILE *ioFile = fopen(filename, "a+");if (ioFile == NULL){printf("FAILED, a+不能打开不存在的文件\n");}else{printf("SUCCESS, a+能打开不存在的文件\n");}
}

新建 Makefile,写入以下内容:

CC:=gcc
fopen_test: fopen_test.c-$(CC) -o $@ $^-./$@-rm ./$@

说明:

1. 有时编译器不只是 gcc,我们将编译器定义为变量 CC,当切换编译器时只需要更改该变量的定义,而无须更改整个 Makefile。
2. $@相当于当前 target 目标文件的名称,此处为 fopen_test。
3. $^相当于当前 target 所有依赖文件列表,此处为 fopen_test.c
4. ./$@的作用是执行目标文件
5. rm ./$@的作用是在执行完毕后删除目标文件,如果没有这个操作,当源文件fopen_test.c 未更改时就无法重复执行,会提示: make:“fopen_test”已是最新。此处删除目标文件,使得我们在不更改源文件的情况下可以多次执行。
6. 所有命令前都添加了“-”符号以忽略错误,确保即便上面的命令执行失败,仍然会向下执行。这样做是为了在发生错误时,确保删除目标文件,使得再次执行相同 target时不会提示: make:“fopen_test”已是最新,可以重新执行 target 下的命令。
fclose

创建 fclose_test.c 文件,写入以下内容:

#include <stdio.h>
int main()
{char *filename = "io1.txt";FILE *ioFile = fopen(filename, "r");if (ioFile == NULL){printf("r 不能打开不存在的文件\n");}else{printf("r 能打开不存在的文件\n");}/*函数:int fclose (FILE *__stream)FILE *__stream: 需要关闭的文件return: 成功返回 0 失败返回 EOF(负数) 通常失败会造成系统崩溃*/int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}

Makefile 中补充以下内容:

fclose_test: fclose_test.c-$(CC) -o $@ $^-./$@-rm ./$@

1.2 向文件中写入数据

fputc 函数

创建 fputc_test.c 文件,写入以下内容:

#include <stdio.h>
int main()
{char *filename = "io.txt";FILE *ioFile = fopen(filename, "a+");if (ioFile == NULL){printf("a+不能打开不存在的文件\n");}else{printf("a+能打开不存在的文件\n");}/*写入文件一个字符函数:int fputc (int __c, FILE *__stream)int __c: 写入的 char 按照 AICII 值写入 可提前声明一个 charFILE *__stream: 要写入的文件,写在哪里取决于访问模式return: 成功返回 char 的值 失败返回 EOF*/int putcR = fputc(97, ioFile);if (putcR == EOF){printf("写入字符失败\n");}else{printf("写入字符成功:%c\n", putcR);}int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}

在 Makefile 中补充以下内容:

fputc_test: fputc_test.c-$(CC) -o $@ $^-./$@-rm ./$@
fputs 函数

创建 fputs_test.c 文件,写入以下内容:

#include <stdio.h>
int main()
{char *filename = "io.txt";FILE *ioFile = fopen(filename, "a+");if (ioFile == NULL){printf("a+不能打开不存在的文件\n");}else{printf("a+能打开不存在的文件\n");}/*写入文件一个字符串函数:int fputs (const char *__restrict __s, FILE *__restrict __stream)char *__restrict __s: 需要写入的字符串FILE *__restrict __stream: 要写入的文件,写在哪里取决于访问模式return: 成功返回非负整数(一般是 0,1) 失败返回 EOF*/int putsR = fputs(" love letter\n", ioFile);if (putsR == EOF){printf("写入字符串失败\n");}else{printf("写入字符串成功:%d\n", putsR);}int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}
fprintf 函数

创建 fprintf_test.c 文件,写入以下内容:

#include <stdio.h>
int main()
{char *filename = "io.txt";FILE *ioFile = fopen(filename, "a+");if (ioFile == NULL){printf("a+不能打开不存在的文件\n");}else{printf("a+能打开不存在的文件\n");}/*函数:fprintf (FILE *__restrict __stream, const char *__restrictFILE *__restrict __stream: 要写入的文件,写在哪里取决于访问模式char *__restrict __fmt: 格式化字符串...: 变长参数列表return: 成功返回正整数(写入字符总数不包含换行符) 失败返回 EOF __fmt, ...)*/char *name = "大海";int fprintfR = fprintf(ioFile, "今天是2025年1月12号!/n我是guuilin", name);if (fprintfR == EOF){printf("写入字符串失败");}else{printf("写入字符串成功:%d\n", fprintfR);}int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");fprintf(stderr, "%s\n", filename);return 1;}return 0;
}

1.3 从文件中读取数据

fgetc 函数

创建 fgetc_test.c 文件,写入以下内容:

#include <stdio.h>
int main()
{// 打开文件FILE *ioFile = fopen("io.txt", "r");if (ioFile == NULL){printf("不能读不存在的文件");}/*函数:int fgetc (FILE *__stream)FILE *__stream: 需要读取的文件return: 读取的一个字节 到文件结尾或出错返回 EOF*/char c = fgetc(ioFile);while (c != EOF){printf("%c", c);c = fgetc(ioFile);}int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}
fgets 函数

创建 fgets_test.c,写入以下内容:

#include <stdio.h>
int main()
{// 打开文件FILE *ioFile = fopen("io.txt", "r");if (ioFile == NULL){printf("不能读不存在的文件");}/*函数:fgets (char *__restrict __s, int __n, FILE *__restrict __stream)char *__restrict __s: 接收读取的数据字符串int __n: 能够接收数据的长度FILE *__restrict __stream: 需要读取的文件return: 成功返回字符串 失败返回 NULL(可以直接用于 while)*/char buffer[100];while (fgets(buffer, sizeof(buffer), ioFile)){printf("%s", buffer);}int result = fclose(ioFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}
fscanf 函数

新建文件 user.txt,写入以下内容:

罗密欧 18 朱丽叶
贾宝玉 14 薛宝钗
梁山伯 16 祝英台
--2025.1.12 guilin

创建 fscanf_test.c,写入以下内容:

#include <stdio.h>
int main()
{ /*函数:int fscanf (FILE *__restrict __stream, const char *__restrict__format, ...)FILE *__restrict __stream: 读取的文件char *__restrict __format: 读取的匹配表达式...: 变长参数列表 用于接收匹配的数据return: 成功返回参数的个数 失败返回 0 报错或结束返回 EOF*/FILE *userFile = fopen("user.txt", "r");if (userFile == NULL){printf("不能打开不存在的文件");}char name[50];int age;char wife[50];int scanfR;while (fscanf(userFile, "%s %d %s\n", name, &age, wife) != EOF){printf("%s 在%d 岁爱上了%s\n", name, age, wife);}int result = fclose(userFile);if (result != 0){printf("关闭文件失败");return 1;}return 0;
}

1.4 标准输入/输出/错误

        读写文件通常用于代码内部操作,如果想要和用户沟通交流,就需要使用标准输入、输出和错误了。

创建文件 stdin_out_err_test.c,写入以下内容:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{// malloc 动态分配内存 也可以用 char ch[100]接收数据char *ch = malloc(100);// char ch1[100];/*stdin: 标准输入 FILE **/fgets(ch, 100, stdin);printf("你好:%s", ch);/*stdout: 标准输出 FILE * 写入这个文件流会将数据输出到控制台printf 底层就是使用的这个*/fputs(ch, stdout); /*stderr: 错误输出 FILE * 一般用于输出错误日志*/fputs(ch, stderr);return 0;
}

二、系统调用

        系统调用是操作系统内核提供给应用程序,使其可以间接访问硬件资源的接口。

2.1 常见系统调用

open()系统调用用于打开一个标准的文件描述符:

int open(const char *__path, int __oflag, ...);
/*
const char *__path: 文件路径
int __oflag: 用于指定打开文件的方式,可以是以下选项的组合:(1) O_RDONLY: 以只读方式打开文件(2) O_WRONLY: 以只写方式打开文件(3) O_RDWR: 以读写方式打开文件(4) O_CREAT: 如果文件不存在,则创建一个新文件(5) O_APPEND: 将所有写入操作追加到文件的末尾(6) O_TRUNC: 如果文件存在并且以写入模式打开,则截断文件长度为 0还有其他标志,如 O_EXCL(当与 O_CREAT 一起使用时,只有当文件不存在时才创建新文件)、O_SYNC(同步 I/O)、 O_NONBLOCK(非阻塞 I/O)等可选参数: mode -> 仅在使用了 O_CREAT 标志且文件尚不存在的情况下生效,用于指定新创建文件的权限位 权限位通常由三位八进制数字组成,分别代表文件所有者、同组用户和其他用户的读写执行权限return: (1) 成功时返回非负的文件描述符。(2) 失败时返回-1,并设置全局变量 errno 以指示错误原因。
*/

read()系统调用用于读取已经打开的文件描述符:

ssize_t read(int __fd, void *__buf, size_t __nbytes);
/*
int __fd:一个整数,表示要从中读取数据的文件描述符
void *__buf:一个指向缓冲区的指针,读取的数据将被存放到这个缓冲区中
size_t __nbytes:一个 size_t 类型的整数,表示要读取的最大字节数 系统调用将尝试读取最多这么多字节的数据,、但实际读取的字节数可能会少于请求的数量。return: (1) 成功时,read()返回实际读取的字节数 这个值可能小于__nbytes,如果遇到了文件结尾(EOF)或者因为网络读取等原因提前结束读取(2) 失败时,read()将返回-1
*/

write()系统调用用于对打开的文件描述符写入内容:

ssize_t write(int __fd, const void *__buf, size_t __n);
/*
参数:int __fd:一个整数,表示要写入数据的文件描述符void *__buf:一个指向缓冲区的指针,写入的数据需要先存放到这个缓冲区中size_t __n:一个 size_t 类型的整数,表示要写入的字节数 write()函数会尝试写入__n 个字节的数据,但实际写入的字节数可能会少于请求的数量return: (1) 成功时,write()返回实际写入的字节数 这个值可能小于__n,如果写入操作因故提前结束,例如: 磁盘满、网络阻塞等情况(2) 失败时,write()将返回-1
*/

close()系统调用用于在使用完成之后,关闭对文件描述符的引用:

int close(int __fd);
/*
参数:int __fd:一个整数,表示要关闭的文件描述符return: (1) 成功关闭时 返回 0(2) 失败时 返回-1
*/
exit 和_exit()

系统调用_exit():立即终止当前进程,且不进行正常的清理操作,如关闭文件、释放内存等。

库函数 exit():终止当前进程,但是在此之前会执行 3 种清理操作:
        (1) 调用所有通过 atexit()注册的终止处理函数(自定义);
        (2) 刷新所有标准 I/O 缓冲区(刷写缓存到文件);
        (3) 关闭所有打开的标准 I/O 流(比如通过 fopen 打开的文件)。

使用场景:

1.通常在父进程中使用 exit(),以确保程序在退出前能执行清理操作,如关闭文件和刷新输出。
2.在子进程中,特别是在 fork()之后立即调用了一个执行操作(如 exec())但执行失败时,推荐使用_exit()或_Exit()来确保子进程的快速、干净地退出,避免执行标准的清理操作,这些操作可能会与父进程发生冲突或不必要的重复。

2.2 综合案例

创建文件 system_call_test.c,写入以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{int fd = open("io.txt", O_RDONLY);if (fd == -1){perror("open");exit(EXIT_FAILURE);}char buffer[1024]; // 创建一个缓冲区来存放读取的数据ssize_t bytes_read;while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0){// 将读取的数据写入标准输出write(STDOUT_FILENO, buffer, bytes_read);}if (bytes_read == -1){perror("read");close(fd);exit(EXIT_FAILURE);}close(fd); // 使用完毕后关闭文件描述符return 0;
}

三、文件描述符

        在 Linux 系统中,当我们打开或创建一个文件(或套接字)时,操作系统会提供一个文件描述符(File Descriptor, FD),这是一个非负整数,我们可以通过它来进行读写等操作。然而,文件描述符本身只是操作系统为应用程序操作底层资源(如文件、套接字等)所提供的一个引用或“句柄”。在 Linux 中,文件描述符 0、 1、 2 是有特殊含义的。

        ➢ 0 是标准输入(stdin)的文件描述符

        ➢ 1 是标准输出(stdout)的文件描述符

        ➢ 2 是标准错误(stderr)的文件描述符

3.1 文件描述符关联的数据结构

struct file:

        每个文件描述符都关联到内核一个 struct file 类型的结构体数据,结构体定义位于 Linux 系统的/usr/src/linux-hwe-6.5-headers-6.5.0-27/include/linux/fs.h文件中,从 992 行开始。

struct file
{...... atomic_long_t f_count; // 引用计数,管理文件对象的生命周期struct mutex f_pos_lock;      // 保护文件位置的互斥锁loff_t f_pos;                 // 当前文件位置(读写位置)...... struct path f_path;    // 记录文件路径struct inode *f_inode;        // 指向与文件相关联的 inode 对象的指针,该对象用于维护文件元数据,如文件类型、访问权限等const struct file_operations *f_op; // 指向文件操作函数表的指针,定义了文件支持的操作,如读、写、锁定等...... void *private_data; // 存储特定驱动或模块的私有数据......
} __randomize_layout__attribute__((aligned(4)));
struct path:
struct path
{struct vfsmount *mnt;    // 是虚拟文件系统挂载点的表示,存储有关挂载文件系统的信息struct dentry *dentry;   // 目录项结构体,代表了文件系统中的一个目录项。目录项是文件系统中的一个实体,通常对应一个文件或目录的名字。通过这个类型的属性,可以定位文件位置。
} __randomize_layout;
 struct inode:
struct inode
{umode_t i_mode;     // 文件类型和权限。这个字段指定了文件是普通文件、目录、字符设备、块设备等,以及它的访问权限(读、写、执行)。unsigned short i_opflags;kuid_t i_uid;       // 文件的用户 ID,决定了文件的拥有者。kgid_t i_gid;       // 文件的组 ID,决定了文件的拥有者组。unsigned int i_flags;...... unsigned long i_ino; // inode 编号,是文件系统中文件的唯一标识。...... loff_t i_size;       // 文件大小
} __randomize_layout;

3.2 文件描述符表关联的数据结构 

struct files_struct 是用来维护一个进程(下文介绍)中所有打开文件信息的。

struct files_struct
{...... struct fdtable __rcu *fdt;                    // 指向当前使用的文件描述符表(fdtable)...... unsigned int next_fd;                         // 存储下一个可用的最小文件描述符编号...... struct file __rcu *fd_array[NR_OPEN_DEFAULT]; // struct file 指针的数组,大小固定,用于快速访问。
};

打开文件描述符表底层的数据结构是 struct fdtable。

struct fdtable {unsigned int max_fds;     // 文件描述符数组的容量,即可用的最大文件描述符struct file __rcu **fd;   // 指向 struct file 指针数组的指针unsigned long *close_on_exec;unsigned long *open_fds;unsigned long *full_fds_bits;struct rcu_head rcu;
}

fd_array 和 fd

fd_array 是一个定长数组,用于存储进程最常用的 struct file。

fd 是一个指针,可以指向任何大小的数组,其大小由 max_fds 字段控制。它可以根据需要动态扩展,以容纳更多的文件描述符。

3.3 文件描述符引用图解

图:文件描述符引用图解

        總結:当我们执行 open() 等系统调用时,内核会创建一个新的 struct file,这个数据结构记录了文件的元数据(文件类型、权限等)、文件路径、支持的操作等,然后分配文件描述符,将 struct file 维护在文件描述符表中,最后将文件描述符返回给应用程序。我们可以通过后者对文件执行它所支持的各种函数操作,而这些函数的函数指针都维护在struct file_operations 数据结构中。文件描述符实质上是底层数据结构 struct file 的一个引用或者句柄,它为用户提供了操作底层文件的入口。

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

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

相关文章

HTML5实现好看的端午节网页源码

HTML5实现好看的端午节网页源码 前言一、设计来源1.1 网站首页界面1.2 登录注册界面1.3 端午节由来界面1.4 端午节习俗界面1.5 端午节文化界面1.6 端午节美食界面1.7 端午节故事界面1.8 端午节民谣界面1.9 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 H…

【2024年华为OD机试】(A卷,100分)- 单词倒序(Java JS PythonC/C++)

一、问题描述 题目描述 输入单行英文句子&#xff0c;里面包含英文字母&#xff0c;空格以及,.?三种标点符号&#xff0c;请将句子内每个单词进行倒序&#xff0c;并输出倒序后的语句。 输入描述 输入字符串S&#xff0c;S的长度 1 ≤ N ≤ 100 输出描述 输出倒序后的字…

插入实体自增主键太长,mybatis-plaus自增主键

1、问题 spring-boot整合mybtais执行insert语句时&#xff0c;主键id为长文本数据。 2、分析问题 1)数据库主键是否自增 2&#xff09;数据库主键的种子值设置的多少 3、解决问题 1&#xff09;数据库主键设置的时自增 3&#xff09;种子值是1 所以排查是数据库的问题 4、继…

Java高频面试之SE-11

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中是引用传递还是值传递&#xff1f; 在 Java 中&#xff0c;方法参数传递是通过 值传递 的方式实现的&#xff0c;但这可能会引起一…

Proser:升级为简易的通讯调试助手软件

我本来打算将Proser定位为一个直观的协议编辑、发送端模拟软件&#xff0c;像下面这样。 但是按耐不住升级的心理&#xff0c;硬生生的把即时收发整合了进去&#xff0c;就像这样&#xff01; 不过&#xff0c;目前针对即时收发还没有发送历史、批量发送等功能&#xff0c;…

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

计算机视觉算法实战——打电话行为检测

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​​ ​​​​​​​​​​​​​​​ ​​​​​​ ​ 1. 引言✨✨ 随着智能手机的普及&#xff0c;打电话行为检测成为了计算机视…

SpringBoot日常:集成Kafka

文章目录 1、pom.xml文件2、application.yml3、生产者配置类4、消费者配置类5、消息订阅6、生产者发送消息7、测试发送消息 本章内容主要介绍如何在springboot项目对kafka进行整合&#xff0c;最终能达到的效果就是能够在项目中通过配置相关的kafka配置&#xff0c;就能进行消息…

HTTPS SSL/TLS 工作流程

目录 一、HTTP/HTTPS 简介1、HTTP协议相关内容2、HTTPS协议3、HTTP版本差异&#xff1a; 二、HTTPS 协议工作流程解析1. 客户端请求 SSL 握手2. 服务端接收 SSL 握手连接3. TLS 握手中的密钥协商4. HTTP 数据的加密与解密5. 安全性保障 三、HTTPS 协议的相关知识拓展1. TLS 与 …

Ubuntu中使用miniconda安装R和R包devtools

安装devtools环境包 sudo apt-get install gfortran -y sudo apt-get install build-essential -y sudo apt-get install libxt-dev -y sudo apt-get install libcurl4-openssl-dev -y sudo apt-get install libxml2.6-dev -y sudo apt-get install libssl-dev -y sudo apt-g…

解决SpringBoot无法使用JDK8问题

解决SpringBoot无法使用JDK8问题 现状解决方案 现状 使用idea创建springboot项目无法选择java8。原因是23年11月的spring更新后就明确了不在支持java8版本的项目创建&#xff0c;但是目前为止很多公司开发还在用java8&#xff0c;导致会有问题的产生。 解决方案 使用idea创…

八、系统托盘与配置面板

没有人会把你变得越来越好&#xff0c;时间和经历只是陪衬。 支撑你变得越来越好的&#xff0c;是你自己坚强的意志、修养、品行、以及不断的反思和经验。 人生最好的贵人&#xff0c;就是努力向上的自己。 一、系统托盘 1、资源文件夹 新建资源文件夹&#xff0c;我们需要把…

IntelliJ IDEA中Maven项目的配置、创建与导入全攻略

大家好&#xff0c;我是袁庭新。 IntelliJ IDEA是当前最流行的Java IDE&#xff08;集成开发环境&#xff09;之一&#xff0c;也是业界公认最好用的Java开发工具之一。IntelliJ IDEA支持Maven的全部功能&#xff0c;通过它我们可以很轻松地实现创建Maven项目、导入Maven项目、…

Element-plus、Element-ui之Tree 树形控件回显Bug问题。

需求&#xff1a;提交时&#xff0c;需要把选中状态和半选中状态 的数据id提交。如图所示&#xff1a; 数据回显时&#xff0c;会出现代码如下&#xff1a; <template><el-tree ref"treeRef" :data"tree" show-checkbox node-key"id" …

C语言#define定义宏

目录 一、什么是宏以及宏的声明方式 1.宏常量&#xff1a; 2.宏函数&#xff1a; 二、宏的替换原则 三、宏设计的易犯错误 ERROR1&#xff1a;尾部加分号&#xff08;当然有些特定需要加了分号&#xff0c;这里说明一般情况&#xff09; ERROR2&#xff1a;宏函数定义时&…

第33 章 - ES 实战篇 - MySQL 与 Elasticsearch 的一致性问题

思维导图 0. 前言 MySQL 与 Elasticsearch 一致性问题是老生常谈了。网上有太多关于这方面的文章了&#xff0c;但是千篇一律&#xff0c;看了跟没看没有太大区别。 在生产中&#xff0c;我们往往会通过 DTS 工具将 binlog 导入到 Kafka&#xff0c;再通过 Kafka 消费 binlog&…

Gitlab-Runner配置

原理 Gitlab-Runner是一个非常强大的CI/CD工具。它可以帮助我们自动化执行各种任务&#xff0c;如构建、测试和部署等。Gitlab-Runner和Gitlab通过API通信&#xff0c;接收作业并提交到执行队列&#xff0c;Gitlab-Runner从队列中获取作业&#xff0c;并允许在不同环境下进行作…

STM32第6章、WWDG

一、简介 WWDG&#xff1a;全称Window watchdog&#xff0c;即窗口看门狗&#xff0c;本质上是一个能产生系统复位信号和提前唤醒中断的计数器。 特性&#xff1a; 是一个递减计数器。 看门狗被激活后&#xff0c; 当递减计数器值从 0x40减到0x3F时会产生复位&#xff08;即T6位…

【Qt】事件、qt文件

目录 Qt事件 QEvent QMouseEvent QWheelEvent QKeyEvent QTimerEvent Qt文件 QFile QFileInfo Qt事件 在Qt中用一个对象表示一个事件&#xff0c;这些事件对象都继承自抽象类QEvent。事件和信号的目的是一样的&#xff0c;都是为了响应用户的操作。有两种产生事件的方…

Jenkins触发器--在其他项目执行后构建

前言&#xff1a; jenkins中有多种触发器可用&#xff0c;可以方便的控制构建的启动 这里简单介绍下项目后构建的配置方法 1. 解释&#xff1a; Build after other projects are built Set up a trigger so that when some other projects finish building, a new build is…