【Linux系统编程】1-文件IO操作

文章目录

  • 1 概述
  • 2 文件描述符
  • 3 文件I/O操作
    • 3.1 打开文件操作
    • 3.2 关闭文件操作
    • 3.3 向文件写入数据
    • 3.4 从文件读取数据
  • 4 给文件描述符添加非阻塞特性
    • 4.1 当此文件描述符不存在
    • 4.2 当此文件描述符存在
  • 5 获取文件状态信息
  • 6 文件目录操作
    • 6.1 打开目录操作
    • 6.2 读取目录信息
    • 6.3 关闭目录
    • 6.4 参考示例:扫描目录

1 概述

系统调用:操作系统提供给用户函数调用的一组特殊接口。

image.png

2 文件描述符

文件描述符是通过存储在内核区的文件描述符表(位图)管理。

功能命令
查看进程号ps -A | grep 可执行文件名
查看打开的文件描述符ls /proc/进程号/fd
查看系统限制ulimit -a
修改最大存储文件描述符空间大小
(当前终端有效)
ulimit -n 1024
查看系统掩码umask
修改系统掩码umask mode
查看各组用户的默认权限umask -S

系统默认为每个进程打开的文件描述符

文件描述符文件设备
0标准输入设备键盘
1标准输出设备屏幕
2标准错误输出设备屏幕

3 文件I/O操作

3.1 打开文件操作

open - 打开并可能创建一个文件
open() 系统调用打开路径名指定的文件。如果指定的文件有,如果不存在,则可以选择通过 open() 创建它(如果在标志中指定了 O_CREAT)。概要#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);参数pathname - 文件路径名flags - 文件操作标志mode - 文件创建权限返回值成功返回新的文件描述符(非负整数),或者如果发生错误,则为 -1(在这种情况下,会适当设置 errno)。

常用文件操作标志

标志含义
O_RDONLY只读方式打开文件。
O_WRONLY只写方式打开文件。
O_RDWR可读可写的方式打开文件。
O_CREAT如果路径名不存在,将其创建为常规文件。
O_EXCL确保此调用创建文件:
如果结合指定此标志,使用 O_CREAT,并且路径名已经存在,则 open() 失败并出现错误 EEXIST
O_TRUNC如果文件已经存在并且是常规文件并且访问模式允许写入(即是 O_RDWRO_WRONLY)它将被截断为长度 0。
如果文件是 FIFO 或终端设备文件,则忽略 O_TRUNC 标志。
O_APPEND文件以附加方式打开,文件流指针指向文件末尾。
O_NONBLOCK文件以非阻塞模式打开。

mode提供的符号常量(与O_CREAT配套使用):

符号常量含义
S_IRWXU0700文件所有者具有读、写、执行权限。
S_IRUSR0400文件所有者权限。
S_IWUSR0200文件所有者权限。
S_IXUSR0100文件所有者执行权限。
S_IRWXG0070同组用户具有读、写、执行权限。
S_IRGRP0040同组用户权限。
S_IWGRP0020同组用户权限。
S_IXGRP0010同组用户执行权限。
S_IRWXO0007其他用户具有读、写、执行权限。
S_IROTH0004其他用户权限。
S_IWOTH0002其他用户权限。
S_IXOTH0001其他用户执行权限。

创建的文件权限为:mode & ~umask


示例1:打开已经存在的文件并清空文件内容。

方法一:使用库函数操作。

#include <stdio.h>int main(int argc, char **argv)
{FILE *fp = NULL;// 打开文件操作// w+ == O_RDWR | O_CREAT | O_TRUNCfp = fopen("test", "w+");if (NULL == fp){perror("fopen");return -1;} /* end of if (NULL == fp) */// 关闭文件操作fclose(fp);return 0;
}

方法二:使用系统调用操作。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char **argv)
{int fd = 0;// 打开文件fd = open("test", O_WRONLY | O_TRUNC);if (-1 == fd){perror("open");return -1;} /* end of if (-1 == fd) */// 打印文件描述符printf("fd = %d\n", fd);            // 3// 关闭文件close(fd);return 0;
}

示例2:打开不存在文件,文件权限为0741

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char **argv)
{int fd = 0;// 创建文件并设置权限fd = open("test1", O_CREAT | O_RDWR, S_IRWXU | S_IRGRP | S_IXOTH);if (-1 == fd){perror("open");return -1;} /* end of if (-1 == fd) */printf("fd: %d\n", fd);// 关闭文件close(fd);return 0;
}

3.2 关闭文件操作

close - 关闭文件描述符
close() 关闭文件描述符,使其不再引用任何文件,并且可以被重用。
与其关联的文件上持有的任何记录锁(请参阅 fcntl(2))进程所拥有的和所拥有的都将被删除(无论用于获取锁文件描述符是什么)。概要#include <unistd.h>int close(int fd);参数fd - 文件描述符返回值close() 成功时返回零。出错时,返回 -1,并设置适当的 errno。注意成功关闭并不能保证数据已成功保存到磁盘,因为内核使用缓冲区高速缓存来延迟写入。通常,文件系统文件关闭时不刷新缓冲区。如果您需要确保数据物理存储在底层磁盘上,请使用 fsync(2)

示例:验证成功关闭文件描述符的返回值。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char **argv)
{int fd = 0;int ret = -1;fd = open("test", O_CREAT | O_RDWR, S_IRWXU | S_IRGRP | S_IROTH);if (-1 == fd){perror("open");return -1;} /* end of if (-1 == fd) */printf("fd: %d\n", fd);ret = close(fd);printf("ret: %d\n", ret);return 0;
}
$ ./a.out 
fd: 3
ret: 0

3.3 向文件写入数据

write - 写入文件描述符
write() 从 buf 开始的缓冲区中写入 count 个字节到由文件描述符 fd 引用的文件。概要#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);参数fd - 文件描述符buf - 缓冲区count - 字节数返回值成功时,返回写入的字节数。出错时,返回-1,并且设置 errno 来指示错误原因。

示例:将数据写入文件中。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(int argc, char **argv)
{int ret = -1;// 打开文件描述符int fd = open("test", O_CREAT | O_TRUNC | O_RDWR, S_IRWXU | S_IRGRP | S_IROTH);if (-1 == fd){perror("open");return -1;} /* end of if (-1 == fd) */printf("%d\n", fd);// 写数据ret = write(fd, "hello world", 5);if (-1 == ret){perror("write");return -1;} /* end of if (-1 == ret) */// 关闭文件描述符close(fd);return 0;
}
$ ./a.out 
3$ cat test
hello

3.4 从文件读取数据

read - 从文件描述符中读取
read() 尝试从文件描述符 fd 中读取最多 count 个字节到缓冲区中从 buf 开始。概要#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);参数fd - 文件描述符buf - 缓冲区count - 字节数返回值成功时,返回读取的字节数;出错时,返回 -1,并适当设置 errno。

4 给文件描述符添加非阻塞特性

4.1 当此文件描述符不存在

当此文件描述符不存在,我们只需要以非阻塞方式打开文件描述符。

open(FILE_PATH, O_WRONLY | O_NONBLOCK | CREAT, 0744);

4.2 当此文件描述符存在

使用fcntl()修改文件描述符状态标记。

fcntl - 操作文件描述符概要#include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );参数fd - 文件描述符cmd - 指令... - 变参返回值成功时根据不同的cmd返回不同的值;	出错时,返回 -1,并适当设置 errno。

修改状态标记相关的cmd

命令含义arg
F_GETFL获取文件访问模式和文件状态被忽略。
F_SETFL将文件状态标志设置为 arg 指定的值。文件状态标记

注意
每个打开的文件描述都有一定的关联状态标志,由open(2) 并可能由 fcntl() 修改。重复的文件描述符(由dup(2)、fcntl(F_DUPFD)、fork(2)等)引用相同的打开文件描述,并且因此共享相同的文件状态标志。

文件存取方式(O_RDONLYO_WRONLYO_RDWR)和文件创建标志(即 O_CREATO_EXCLarg 中的 O_NOCTTY、O_TRUNC)将被忽略。在 Linux 上,此命令可以更改仅 O_APPEND、O_ASYNC、O_DIRECT、O_NOATIMEO_NONBLOCK 标志。它无法更改 O_DSYNCO_SYNC 标志。


使用:将文件描述符添加非阻塞特性。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(int argc, char **argv)
{int fd = 0;int flag = 0;int ret = 0;// 打开文件描述符fd = open("test", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IROTH);if (-1 == fd){perror("open");return -1;} /* end of if (-1 == fd) */// 获取文件描述符的状态标记flag = fcntl(fd, F_GETFL);if (-1 == flag){perror("fcntl");return -1;} /* end of if (-1 == flag) */// 添加阻塞特性ret = fcntl(fd, F_SETFL, flag | O_NONBLOCK);if (-1 == ret){perror("fcntl");} /* end of if (-1 == ret) */// 关闭文件描述符close(fd);return 0;
}

5 获取文件状态信息

stat、lstat - 获取文件状态
这些函数返回有关文件的信息,位于 stat 指向的缓冲区中缓冲区。
文件本身不需要任何权限,但是对于 stat() 来说,fstatat()lstat()——所有直接命令都需要执行(搜索)权限通向该文件的路径名中的内容。概要#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>int stat(const char *pathname, struct stat *statbuf);int lstat(const char *pathname, struct stat *statbuf);参数pathname - 文件路径名statbuf - 数据存储缓冲区地址返回值成功后,返回零。出错时,返回 -1,并适当设置 errno。

状态统计结构体参考结构:

struct stat 
{dev_t     st_dev;         /* ID of device containing file */ino_t     st_ino;         /* Inode number */mode_t    st_mode;        /* File type and mode */nlink_t   st_nlink;       /* Number of hard links */uid_t     st_uid;         /* User ID of owner */gid_t     st_gid;         /* Group ID of owner */dev_t     st_rdev;        /* Device ID (if special file) */off_t     st_size;        /* Total size, in bytes */blksize_t st_blksize;     /* Block size for filesystem I/O */blkcnt_t  st_blocks;      /* Number of 512B blocks allocated *//* Since Linux 2.6, the kernel supports nanosecondprecision for the following timestamp fields.For the details before Linux 2.6, see NOTES. */struct timespec st_atim;  /* Time of last access */struct timespec st_mtim;  /* Time of last modification */struct timespec st_ctim;  /* Time of last status change */#define st_atime st_atim.tv_sec      /* Backward compatibility */#define st_mtime st_mtim.tv_sec#define st_ctime st_ctim.tv_sec
};

结构体成员解析:

成员含义
st_ino该字段包含文件的索引节点号。
st_mode该字段包含文件类型和模式。有关详细信息,请参阅 inode(7)。
st_nlink该字段包含文件的硬链接数。
st_uid该字段包含文件所有者的用户 ID。
st_gid该字段包含文件的组所有者的 ID。
st_size该字段给出文件的大小(如果它是常规文件或符号文件链接)以字节为单位。
符号链接的大小是它包含路径名的长度,但没有终止空字节。
st_atime这是最后一次访问文件数据的时间。
st_mtime这是文件数据最后一次修改的时间。
st_ctime这是文件的上次状态更改时间戳(上次更改的时间索引节点)。

拓展函数:ctime()

ctime - 将日期和时间转换为细分时间或 ASCII
ctime()函数都采用数据类型的参数time_t,表示日历时间。
当解释为绝对时间时值,它表示自纪元 1970-01-01 以来经过的秒数00:00:00 +0000(世界标准时间)。概要#include <time.h>char *ctime(const time_t *timep);参数timep - 指向时间类型的指针返回值成功时,ctime() 返回指向字符串的指针。错误时为 NULL。发生错误时,会设置 errno 以指示错误原因。

参考示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>int main(int argc, char **argv)
{struct stat sb;int ret = 0;// 获取文件状态ret = stat("test", &sb);if (-1 == ret){perror("stat");return -1;} /* end of if (-1 == ret) */// 解析获取到的信息// 1.文件索引节点号printf("%lu\n", sb.st_ino);// 2.文件的硬链接数printf("%lu\n", sb.st_nlink);// 3.文件类型
#if 0if (S_IFREG & sb.st_mode){printf("普通文件\n");}else if (S_IFDIR & sb.st_mode){printf("目录\n");}else if (S_IFLNK & sb.st_mode){printf("符号链接\n");}else if (S_IFCHR & sb.st_mode){printf("字符设备\n");}else if (S_IFBLK & sb.st_mode){printf("块设备\n");}else if (S_IFSOCK & sb.st_mode){printf("套接字");}else if (S_IFIFO & sb.st_mode){printf("管道\n");}#else if (S_ISREG(sb.st_mode)){printf("普通文件\n");}else if (S_ISDIR(sb.st_mode)){printf("目录\n");}else if (S_ISLNK(sb.st_mode)){printf("符号链接\n");}else if (S_ISCHR(sb.st_mode)){printf("字符设备\n");}else if (S_ISBLK(sb.st_mode)){printf("块设备\n");}else if (S_ISSOCK(sb.st_mode)){printf("套接字");}else if (S_ISFIFO(sb.st_mode)){printf("管道\n");}
#endif// 4.文件所有者的用户ID和组IDprintf("uid:%u  gid:%u\n", sb.st_uid, sb.st_gid);// 5.文件的大小printf("size: %luB\n", sb.st_size);// 6.文件的最后一次数据访问时间printf("atime: %s", ctime(&sb.st_atime));// 7.文件的最后一次数据修改时间printf("mtime: %s", ctime(&sb.st_mtime));// 8.文件状态更改时间戳printf("ctime: %s", ctime(&sb.st_ctime));return 0;
}
$ ./a.out 
2631317
1
普通文件
uid:1000  gid:1000
size: 5B
atime: Wed Mar 13 13:21:04 2024
mtime: Wed Mar 13 13:21:00 2024
ctime: Wed Mar 13 13:21:00 2024

6 文件目录操作

6.1 打开目录操作

opendir - 打开目录
opendir()函数打开目录对应的目录流name,并返回指向目录流的指针。该流位于目录中的第一个条目。概要#include <sys/types.h>#include <dirent.h>DIR *opendir(const char *name);参数name - 目录名返回值函数返回指向目录流的指针。出错时,返回 NULL,并适当设置 errno。

6.2 读取目录信息

readdir - 读取目录
readdir() 函数返回一个指向 dirent 结构的指针,该结构表示dirp 指向的目录流中的下一个目录条目。
它返回 NULL到达目录流末尾或发生错误时。概要#include <dirent.h>struct dirent *readdir(DIR *dirp);参数dirp - 目录句柄返回值成功时,readdir() 返回指向 dirent 结构的指针。 (这个结构是静态分配;不要尝试free(3)。)如果到达目录流末尾,则返回 NULL 并且不返回 errno改变了。如果发生错误,则返回 NULL 并适当设置 errno。到区分流结束和错误,在调用 readdir() 之前将 errno 设置为零,然后检查 errno 的值,如果返回 NULL

struct dirent结构体定义:

struct dirent 
{ino_t          d_ino;       /* Inode number */off_t          d_off;       /* Not an offset; see below */unsigned short d_reclen;    /* Length of this record */unsigned char  d_type;      /* Type of file; not supportedby all filesystem types */char           d_name[256]; /* Null-terminated filename */
};

d_type定义的宏:

含义
DT_REG常规文件
DT_DIR目录
DT_CHR字符设备
DT_BLK块设备
DT_LNK符号链接
DT_SOCK套接字
DT_FIFO管道
DT_UNKNOWN无法确定文件类型

6.3 关闭目录

closedir - 关闭目录
Closedir() 函数关闭与 Dirp 关联的目录流。一个成功的
成功调用 Closedir() 也会关闭与Dirp关联的底层文件描述符。目录流描述符 dirp 在此调用后不可用。概要#include <sys/types.h>#include <dirent.h>int closedir(DIR *dirp);参数dirp - 目录流返回值closeir() 函数成功时返回 0。出错时返回-1,并返回errno被适当地设置。

6.4 参考示例:扫描目录

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>int main(int argc, char **argv)
{DIR *dir = NULL;struct dirent *dp = NULL;int cnt = 0;// 打开目录dir = opendir("./");if (NULL == dir){perror("opendir");return -1;} /* end of if (NULL == dir) */// 逐个读取目录流errno = 0;cnt = 0;while (1){dp = readdir(dir);if (0 == errno && NULL == dp){// 目录扫描结束break;}else if (0 != errno && NULL == dp){// 读取出错perror("readdir");return -2;}cnt++;// 解析信息printf("file%d: %s\n", cnt, dp->d_name);printf("类型: ");if (DT_REG == dp->d_type){printf("普通文件\n");}else if (DT_DIR == dp->d_type){printf("目录\n");}else if (DT_LNK == dp->d_type){printf("符号链接\n");}else if (DT_CHR == dp->d_type){printf("字符设备\n");}else if (DT_BLK == dp->d_type){printf("块设备\n");}else if (DT_SOCK == dp->d_type){printf("套接字\n");}else if (DT_FIFO == dp->d_type){printf("管道\n");}else if (DT_UNKNOWN == dp->d_type){printf("未知\n");}} /* end of while (1) */closedir(dir);return 0;
}
$ ./a.out 
file1: test
类型: 普通文件
file2: 02code.c
类型: 普通文件
file3: tes1
类型: 普通文件
file4: 05code.c
类型: 普通文件
file5: 01code.c
类型: 普通文件
file6: 07code.c
类型: 普通文件
file7: 06code.c
类型: 普通文件
file8: 08code.c
类型: 普通文件
file9: 04code.c
类型: 普通文件
file10: 03code.c
类型: 普通文件
file11: ..
类型: 目录
file12: a.out
类型: 普通文件
file13: .
类型: 目录
file14: test1
类型: 普通文件

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

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

相关文章

个人IP打造孵化运营产业链商业计划书

【干货资料持续更新&#xff0c;以防走丢】 个人IP打造孵化运营产业链商业计划书 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT共90页&#xff08;完整资料包含以下内容&#xff09; 目录 个人IP运营方案&#xff1a; 1. 个人IP定位与构建 1.1 人格画像构…

【Vue】Vue初体验

目录 Vue简介Vue的特点MVVM 概念MVVM 的工作原理 虚拟DOM和Diff算法 与其他 JS 框架的关联Vue 周边库vue 的特性1.数据驱动视图2.双向数据绑定 开发工具 Vue快速上手1.搭建Vue开发环境2.创建Vue实例内容解析注意data的两种写法 3.Vue模板语法插值语法指令语法代码示例 4.Vue数据…

Unity Shader中获取像素点深度信息

1.顶点着色器中对深度进行计算 v2f vert(appdata v) {v2f o;o.pos UnityObjectToClipPos(v.vertex);o.uv TRANSFORM_TEX(v.uv, _MainTex);o.depth (o.pos.z / o.pos.w 1.0) * 0.5; // Normalize depth to [0, 1]return o; }但是达不到预期&#xff0c;最后返回的值一直大于…

QT+网络调试助手+TCP服务器

一、UI界面设计 二、单线程 代码设计 1、 查找合法的本地地址&#xff0c;用于当作服务器的IP地址 #include <QThread> #include <QTcpSocket> #include <QNetworkInterface> #include <QMessageBox>QList<QHostAddress> ipAddressesList QNe…

【iOS】——浅析CALayer

文章目录 一、CALayer介绍二、UIview与CALayer1.区别2.联系 三、CALayer的使用1.初始化方法2.常用属性 四.CALayer坐标系1.position属性和anchorPoint属性2.position和anchorPoint的关系3.position、anchorPoint和frame的关系 五、CALayerDelegate六、CALayer绘图机制1.绘图流程…

vue2结合element-ui实现TreeSelect 树选择功能

需求背景 在日常开发中&#xff0c;我们会遇见很多不同的业务需求。如果让你用element-ui实现一个 tree-select 组件&#xff0c;你会怎么做&#xff1f; 这个组件在 element-plus 中是有这个组件存在的&#xff0c;但是在 element-ui 中是没有的。 可能你会直接使用 elemen…

6、随机森林(Random forests)

Random forests started a revolution in machine learning 20 years ago. For the first time, there was a fast and reliable algorithm which made almost no assumptions about the form of the data, and required almost no preprocessing. In today’s lesson, you’ll…

全新Adobe利器:Project Neo为2D平面图像轻松添加3D立体效果

Adobe的崭新创意工具Project Neo&#xff0c;正以其独特的3D技术为传统的2D图像设计领域带来革命性的变化。这款工具的核心功能在于&#xff0c;它能够将原本平面的2D图像巧妙地转化为立体感十足的三维作品。 想象一下&#xff0c;你手中的图标、动画插图&#xff0c;在Projec…

高效项目管理:如何利用zz-plan在线甘特图工具

作为项目管理人员&#xff0c;使用 zz-plan https://zz-plan.com/这样的在线甘特图协作软件可以极大地提高项目管理的效率和效果。以下是结合zz-plan特点的一些关键步骤&#xff1a; 1. 制定项目计划 在zz-plan上创建新的项目&#xff0c;定义项目目标、关键里程碑和最终期限。…

Llama 3 模型上下文长度扩展至1048K

AI苏妲己&#xff1a; Gradient AI 近日宣布&#xff0c;通过其创新的渐进式训练方法&#xff0c;成功将 Llama 3 系列模型的上下文长度扩展至超过100万令牌。 Llama 3 模型最初设计用于处理8000个令牌的上下文长度&#xff0c;这大约相当于6000字或10页文档。为了适应更长的…

Spring中的Bean相关理解

在Spring框架中&#xff0c;Bean是一个由Spring IoC容器实例化、配置和管理的对象。Bean是一个被Spring框架管理并且被应用程序各个部分所使用的对象。Spring IoC容器负责Bean的创建、初始化、依赖注入以及销毁等生命周期管理。 注&#xff1a;喜欢的朋友可以关注公众号“JAVA学…

央国企加速新质生产力形成和发展,HR数字化工具如何推动创新内核构建?

自今年两会以来&#xff0c;“新质生产力”一词获得了广泛的关注。众多专家学者对其重要性、定义及作用进行了热烈且深入的讨论&#xff0c;一致强调了新质生产力的核心地位。对于那些致力于转型为现代化国有企业的国资中央企业而言&#xff0c;培育新质生产力无疑成为了当前及…

通过高效的升级计划控制云成本

快速迁移到云以及使用和成本的复杂性使得公司迫切希望减少浪费并控制其支出。更糟糕的是&#xff0c;动荡的经济让决策者紧张不安&#xff0c;他们考虑削减成本措施并优先考虑锁定收入。 如果没有正式的 FinOps 或成本优化策略&#xff0c;公司很容易看到云费用如滚雪球般失控…

ABAP—ALV 进阶:对展示数字要求负号提前、有千分符、有百分号

1、负号提前 问题描述&#xff1a;SAP的数据&#xff0c;例如金额&#xff0c;为负数时&#xff0c;负号放在数值后面&#xff0c;不符合一般的负号在前的读数习惯&#xff0c;如何把负号放到数值前面&#xff1f; 解决办法&#xff1a;使用 CLOI_PUT_SIGN_IN_FRONT CALL FU…

QSPI的使用

Quad SPI接口(QSPI)是一种同步串行数据链路,在主模式下提供与外部设备的通信。它类似于SPI协议,只是它有额外的数据线。 普通SPI有四条通信线路:芯片选择、时钟、MOSI和MISO。对于QSPI,可提供额外的数据线。因此,命令/数据/地址是根据所选模式通过单、四或双IO发送的。由…

一个物业管理服务项目的思考——智慧停车场无人值守呼叫系统到电梯五方对讲再到呼叫中心

目录 起源智慧停车场无人值守呼叫系统然后电梯五方对讲系统又然后物业呼叫中心集控E控中心怎么做 起源 小区里新装了智慧停车场系统&#xff0c;马上展现出了科技化、现代化的新形象。一个显著的好处是&#xff1a;停车场的出入口&#xff0c;再也看不到司机和保安争吵的场景了…

STM32F407VET6 学习笔记2:定时器、串口、自定义串口打印函数

今日继续学习使用嘉立创购买的 立创梁山派天空星&#xff0c;芯片是 STM32F407VET6 因为已经有学习基础了&#xff0c;所以学习进度十分快&#xff0c;这次也是直接一块学习配置定时器与串口了&#xff0c;文章也愈来愈对基础的解释越来越少了...... 文章提供测试代码讲解、完…

什么是企业出海?

本文节选自Odoo亚太金牌服务机构【开源智造】所编写的《企业数字化百科大全》如需获取完整的知识内容&#xff0c;请至开源智造官网免费获取。感谢网友一键三连&#xff1a;点赞、转发、收藏&#xff0c;您的支持是我们最大的前进动力&#xff01; 企业出海是什么意思&#xff…

idea Maven 插件 项目多环境打包配置

背景 不同环境的配置文件不一样&#xff0c;打包方式也有差异 1. 准备配置文件 这里 local 为本地开发环境 可改为 dev 名称自定义 test 为测试环境 prod 为生产环境 根据项目业务自行定义 application.yml 配置&#xff1a; spring:profiles:#对应pom中的配置active: spring.…

指代消解类方法梳理

概念&#xff1a; MLM&#xff1a;带遮罩的语言模型 NSP&#xff1a;单句预测&#xff0c;任务包括两个输入序列 SBO&#xff1a;分词边界目标 1.spanBERT&#xff0c;2019 spanBERT是对bert从分词到文本跨度的优化&#xff0c;主要有两方面的优化&#xff1a;&#xff08…