Linux 文件系统与 I/O 编程核心原理及实践笔记
文章目录
- 一、理解文件
- 1.1 狭义理解
- 1.2 广义理解
- 1.3 文件操作的归类认识
- 1.4 系统角度:进程与文件的交互
- 1.5 实践示例
- 二、回顾 C 文件接口
- 2.1 hello.c 打开文件
- 2.2 hello.c 写文件
- 2.3 hello.c 读文件
- 2.4 输出信息到显示器的几种方法
- 2.5 stdin & stdout & stderr
- 三、系统文件I/O
- 3.1 一种传递标志位的方法
- 3.2 接口介绍
- 3.5 3-5 open函数返回值
- 3.6 文件描述符 fd
- 3.6.1 0 & 1 & 2
- 3.6.2 文件描述符的分配规则:最小未使用下标优先
- 3.6.3 应用场景:重定向的实现
- 3.6.4 dup2 系统调用
- 五、缓冲区
- 5.1 什么是缓冲区
- 5.2 为什么要引入缓冲区机制
- 5.3 缓冲类型
一、理解文件
1.1 狭义理解
- 文件在磁盘里
*磁盘作为永久性存储介质,通过文件系统(如 EXT4、XFS)管理文件存储。文件系统将磁盘划分为inode(索引节点)和block(数据块):- inode:存储文件元数据(权限、所有者、修改时间等),每个文件唯一对应一个 inode。
- block:存储文件实际数据,大小由文件系统决定(如 4KB)。
注意:即使 0KB 的空文件也会占用inode 空间(不同文件系统 inode 大小不同,如 EXT4 默认 256 字节),但不占用数据块(block)。
- 磁盘是外设(输入 / 输出设备)
对磁盘文件的操作本质是IO(Input/Output),涉及内核与外设的数据交互(如通过 DMA 控制器读写磁盘)。
1.2 广义理解
Linux下一切皆文件
系统将硬件设备、进程信息、通信管道等抽象为文件,通过统一接口管理:
- 硬件设备:
- 块设备:以块为单位读写(如硬盘
/dev/sda
,文件类型b
)。 - 字符设备:以字符流读写(如键盘
/dev/input/event0
,文件类型c
)。
- 块设备:以块为单位读写(如硬盘
- 虚拟文件系统:
/proc
:动态映射进程信息(如/proc/self/exe
是当前进程二进制文件)。/sys
:暴露内核设备驱动细节(如/sys/class/leds/
控制 LED 灯)。
- 进程通信:
- 管道文件(类型
p
):mkfifo mypipe
创建命名管道。 - 套接字文件(类型 s):
/run/docker.sock
用于Docker
进程通信。
这种抽象屏蔽了底层差异,例如读写/dev/tty1
(终端设备文件)与读写普通文件使用相同 API。
- 管道文件(类型
1.3 文件操作的归类认识
文件 = 元数据(属性) + 数据内容
- 元数据:
- 基础属性:权限(
rwx
)、所有者(uid/gid
)、硬链接数(ls -l
第二列)。 - 时间戳:修改时间(
mtime
)、状态改变时间(ctime
)、访问时间(atime
)。 - 技术属性:inode 编号(
ls -i
)、文件大小(ls -l
第五列)、块数(ls -s
)。
- 基础属性:权限(
- 数据内容:
分为文本(ASCII/UTF-8)和二进制(如可执行程序、图片),通过cat
、hexdump
等工具查看。 - 操作分类
- 内容操作:读写(
read/write
系统调用)、定位(lseek
)、截断(truncate
)。
- 内容操作:读写(
- 属性操作:
- 修改权限:
chmod
(对应chmod
系统调用)。 - 更改所有者:
chown
(对应chown
系统调用)。 - 查看元数据:
stat命令
(对应stat
系统调用,返回struct stat
结构体)。
- 修改权限:
1.4 系统角度:进程与文件的交互
- 一切文件操作由进程触发
内核通过 ** 文件描述符(File Descriptor, FD)** 标识进程打开的资源,FD
是0~1023
的整数(默认:0=stdin
,1=stdout
,2=stderr
)。
可通过ls -l /proc/$$/fd
查看当前进程打开的文件($$
为当前进程PID
)。 - 系统调用 vs 库函数
- 系统调用:内核提供的底层接口(如
open
、read
),需从用户态陷入内核态,开销较高但更直接。 - 库函数:C 标准库封装的高层接口(如
fopen
、fread
),内部调用系统调用并提供缓存机制(如stdio
的缓冲区)。 - 示例:
fprintf(stdout, "hello")
最终会调用write(1, "hello", 5)
系统调用。
- 系统调用:内核提供的底层接口(如
- 内核如何管理文件
- 每个打开的文件对应内核中的 file结构体,记录文件位置、引用计数等。
- 多个进程可通过不同 FD 指向同一file结构体(如父子进程共享文件),实现数据共享。
1.5 实践示例
- 查看文件元数据
stat test.txt # 显示inode、权限、时间戳等详细信息
ls -li test.txt # 查看inode编号和硬链接数
- 操作设备文件
echo "Hello zkp!" > /home/zkp/linux/25/6/7/file/test.txt # 向文件写入信息
cat /home/zkp/linux/25/6/7/file/test.txt # 查看文件内容
- 理解文件描述符
exec 3<> file.txt # 在当前Shell中打开文件,FD=3可读可写
echo "test" >&3 # 通过FD=3写入文件
cat <&3 # 通过FD=3读取文件
exec 3>&- # 关闭FD=3
二、回顾 C 文件接口
2.1 hello.c 打开文件
打开的myfile
文件在哪个路径下?
- 在程序的当前路径下,那系统怎么知道程序的当前路径在哪里呢?
可以使用ls /proc/[进程id]
命令查看当前正在运行进程的信息:
其中: cwd
:指向当前进程运行目录的一个符号链接。exe
:指向启动当前进程的可执行文件(完整路径)的符号链接。
打开文件,本质是进程打开,所以,进程知道自己在哪里,即便文件不带路径,进程也知道。由此OS就能知道要创建的文件放在哪里。
2.2 hello.c 写文件
2.3 hello.c 读文件
2.4 输出信息到显示器的几种方法
2.5 stdin & stdout & stderr
- C 默认会打开三个输出流,分别是 stdin,stdout,stderr
- 这三个流的类型都是
FILE*
,而fopen
返回值类型也是文件指针
三、系统文件I/O
我们知道,文件的权限分为 rwx
,对应的标志位为 4,2,1。
3.1 一种传递标志位的方法
核心原理:位掩码(Bit Mask)
每个标志对应 唯一的二进制位(如第 0 位、第 1 位…),通过 位运算 组合 / 解析:
- 设置标志:用
|
(按位或)组合多个标志(如FLAG_A | FLAG_B
)。 - 检查标志:用
&
(按位与)判断某一位是否为 1(如if (flags & FLAG_A)
)。
#include <stdio.h>// 定义权限标志位(与Linux系统保持一致)
#define PERM_READ (1 << 2) // 4: 读权限
#define PERM_WRITE (1 << 1) // 2: 写权限
#define PERM_EXEC (1 << 0) // 1: 执行权限// 解析权限并打印
void func(int perms) {printf("用户权限: ");printf(perms & USER_PERMS(PERM_READ) ? "r" : "-");printf(perms & USER_PERMS(PERM_WRITE) ? "w" : "-");printf(perms & USER_PERMS(PERM_EXEC) ? "x" : "-");printf("\n");
}int main() {// 组合权限:用户有读写,组有读,其他用户无权限int perms = (PERM_READ | PERM_WRITE)printf("权限掩码(八进制): 0%o\n", perms); // 输出: 0x6func(perms);return 0;
}
3.2 接口介绍
参数:
pathname
:要打开或创建的目标文件flags
:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags
。O_RDONLY
:只读打开O_WRONLY
:只写打开O_RDWR
:读,写打开
这三个常量,必须指定一个且只能指定一个O_CREAT
:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限O_APPEND
:追加写
返回值:
- 成功:新打开的文件描述符
- 失败:-1
open
函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open
创建,则第三个参数表示创建文件的默认权限;否则,使用两个参数的open
。
write
、read
、close
、lseek
,类比c文件相关接口。
3.5 3-5 open函数返回值
在认识返回值之前,先来认识一下两个概念:系统调用和库函数
- 上面的
fopen
fclose
fread
fwrite
都是C标准库当中的函数,我们称之为库函数(libc)。 - 而
open
close
read
write
lseek
都属于系统提供的接口,称之为系统调用接口
看下面这张图:
系统调用接口和库函数的关系,一目了然。
所以,可以认为,f#
系列的函数,都是对系统调用的封装,方便二次开发。
3.6 文件描述符 fd
- 通过对
open
函数的学习,我们知道了文件描述符就是一个小整数
3.6.1 0 & 1 & 2
- Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2。
- 0,1,2对应的物理设备一般是:键盘,显示器,显示器
所以输入输出还可以采用如下方式:
#include <stdio.h>
#include <sys/types.h>#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>int main()
{char buf[1024];ssize_t s = read(0, buf, sizeof(buf));if (s > 0) {buf[s] = 0;write(1, buf, strlen(buf));write(2, buf, strlen(buf));} return 0;
}
3.6.2 文件描述符的分配规则:最小未使用下标优先
- 默认初始状态:
进程启动时,内核会自动打开 3 个标准文件描述符:- 0:标准输入(
stdin
,默认关联键盘) - 1:标准输出(
stdout
,默认关联终端) - 2:标准错误(
stderr
,默认关联终端)
因此,首次打开新文件时,文件描述符从 3 开始分配(依次递增:3、4、5…)。
- 0:标准输入(
- 关闭后复用:
如果进程主动关闭某个文件描述符(如close(0)
),后续调用open
时,内核会 扫描文件描述符表,选择最小的未被使用的下标 分配给新文件。- 例:关闭 0 后,新打开的文件会优先占用 0;
- 若同时关闭 0 和 2,新打开的文件会依次占用 0、2,再继续递增(如 3、4…)。
代码验证:
#include <stdio.h>
#include <unistd.h> // close
#include <fcntl.h> // open, O_RDWR, O_CREATint main() {// 1. 初始打开:未关闭默认FD,从3开始int fd1 = open("test1.txt", O_RDWR | O_CREAT, 0644);printf("fd1: %d\n", fd1); // 输出:3(0、1、2已占用)// 2. 关闭标准输入(FD=0),后续打开优先复用0close(0); int fd2 = open("test2.txt", O_RDWR | O_CREAT, 0644);printf("fd2: %d\n", fd2); // 输出:0(最小未使用下标)// 3. 关闭标准错误(FD=2),后续打开优先复用2close(2); int fd3 = open("test3.txt", O_RDWR | O_CREAT, 0644);printf("fd3: %d\n", fd3); // 输出:2(当前最小未使用下标)// 4. 继续打开,下一个最小未使用是3(0、2已用,1仍被stdout占用)int fd4 = open("test4.txt", O_RDWR | O_CREAT, 0644);printf("fd4: %d\n", fd4); // 输出:3return 0;
}
运行结果:
fd1: 3
fd2: 0
fd3: 2
fd4: 3
3.6.3 应用场景:重定向的实现
- 输出重定向示例:
# 将命令输出写入文件(本质是修改FD=1的指向)
ls -l > output.txt
实现逻辑:
- Shell 先关闭 FD=1(标准输出),再打开
output.txt
,此时新文件会占用 FD=1; - 后续
ls
命令的输出会写入 FD=1(即output.txt
),而非终端。
- 代码模拟重定向:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>int main() {// 1. 关闭标准输出(FD=1)close(1); // 2. 打开新文件,会复用FD=1int fd = open("redirect.txt", O_WRONLY | O_CREAT, 0644);// 3. printf 会向 FD=1 写入(此时指向 redirect.txt)printf("Hello, Redirect!\n"); close(fd);return 0;
}
运行后,redirect.txt 会包含 Hello, Redirect!,而非终端输出
注意事项
- 关闭默认描述符(如
close(1)
)后,若后续代码依赖标准输出(如printf
),会导致输出丢失或异常。 - 建议使用 dup2 实现重定向(安全关闭旧描述符,避免冲突)。
重定向的本质:
3.6.4 dup2 系统调用
示例:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>int main() {// 1. 打开文件(获取新的文件描述符,如3)int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open failed");return 1;}// 2. 将标准输出(FD=1)重定向到 fd 指向的文件if (dup2(fd, 1) == -1) {perror("dup2 failed");close(fd);return 1;}// 3. 此时 printf 会写入 output.txt,而非终端printf("Hello, dup2!\n");// 4. 关闭 fd(注意:标准输出仍指向 output.txt)close(fd);// 5. 验证:继续向标准输出写入fprintf(stdout, "This will also appear in output.txt\n");return 0;
}
printf
是C库当中的IO函数,一般往stdout
中输出,但是stdout
底层访问文件的时候,找的还是fd:1,但此时,fd:1下标所表示内容,已经变成了myfifile
的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写入,进而完成输出重定向。
五、缓冲区
5.1 什么是缓冲区
缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
5.2 为什么要引入缓冲区机制
读写文件时,如果不会开辟对文件操作的缓冲区,直接通过系统调用对磁盘进行操作(读、写等),那么每次对文件进行一次读写操作时,都需要使用读写系统调用来处理此操作,即需要执行一次系统调用,执行一次系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率造成很大的影响。
为了减少使用系统调用的次数,提高效率,我们就可以采用缓冲机制。比如我们从磁盘里取信息,可以在磁盘文件进行操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部分的访问就不需要再使用系统调用了,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。可以看出,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
5.3 缓冲类型
标准I/O提供了3种类型的缓冲区。
- 全缓冲区:这种缓冲方式要求填满整个缓冲区后才进行I/O系统调用操作。对于磁盘文件的操作通常使用全缓冲的方式访问。
- 行缓冲区:在行缓冲情况下,当在输入和输出中遇到换行符时,标准I/O库函数将会执行系统调用操作。当所操作的流涉及一个终端时(例如标准输入和标准输出),使用行缓冲方式。因为标准1/O库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行I/0系统调用操作,默认行缓冲区的大小为1024。
- 无缓冲区:无缓冲区是指标准I/O库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。
除了上述列举的默认刷新方式,下列特殊情况也会引发缓冲区的刷新:
- 缓冲区满时;
- 执行
flush
语句;
相关文章:

Linux 文件系统与 I/O 编程核心原理及实践笔记
文章目录 一、理解文件1.1 狭义理解1.2 广义理解1.3 文件操作的归类认识1.4 系统角度:进程与文件的交互1.5 实践示例 二、回顾 C 文件接口2.1 hello.c 打开文件2.2 hello.c 写文件2.3 hello.c 读文件2.4 输出信息到显示器的几种方法2.5 stdin & stdout & st…...

vite+tailwind封装组件库
前言 演示视频 https://www.bilibili.com/video/BV1EST3zPEyP/?spm_id_from333.1387.homepage.video_card.click 参考 https://juejin.cn/post/7112295067682865166 https://juejin.cn/post/7046187185615142949 代码仓库 https://gitee.com/malguy/vite-components-li…...
Gin框架实战指南:从入门到进阶
Gin框架实战指南:从入门到进阶 在当今的后端开发领域,Gin框架以其高性能、简洁易用的特点,赢得了众多Go语言开发者的青睐。本文将带你深入探索Gin框架的方方面面,从基础的安装与使用,到响应处理、请求参数解析、中间件…...

【Java学习笔记】包装类
包装类(Wrapper) 1. 介绍 (1)针对八种基本数据类型相应的引用类型 --> 包装类 (2)有了类的特点,就可以调用类中的方法 2. 分类和继承关系 基本数据类型包装类父类booleanBooleanObjectc…...

【高效开发工具系列】Blackmagic Disk Speed Test for Mac:专业硬盘测速工具
博客目录 一、Blackmagic Disk Speed Test 概述二、软件核心功能解析三、v3.3 版本的新特性与改进四、实际应用场景分析五、使用技巧与最佳实践六、与其他工具的比较及优势 一、Blackmagic Disk Speed Test 概述 Blackmagic Disk Speed Test 是 Mac 平台上广受专业人士青睐的一…...
QtDBus模块功能及架构解析
Qt 6.0 中的 QtDBus 模块是一个用于进程间通信(IPC)的核心模块,它基于 D-Bus 协议实现。D-Bus 是一种在 Linux 和其他类 Unix 系统上广泛使用的消息总线系统,允许应用程序和服务相互通信。 一、QtDBus模块主要功能: 1…...
光学字符识别(OCR)理论概述与实践教程
一、 光学字符识别(OCR)理论基础 OCR,即Optical Character Recognition,旨在通过计算机视觉和模式识别技术,将图像中包含的文本信息转换为机器可编辑、可搜索的文本数据。这项技术是实现信息数字化、自动化处理纸质或图像化文档的关键。 1. OCR处理管线 OCR系统通常采用…...
关键字--sizeof
sizeof 是 C 中的一个编译时运算符,用于获取一个类型或对象在内存中所占的字节数(单位:字节,byte)。 用法 获取类型的大小: std::cout << sizeof(int) << std::endl; // 输出int类型的字节数…...
Ubuntu20.04启动python的虚拟环境
如果你使用 mkvirtualenv 来创建虚拟环境,说明你已经安装了 virtualenvwrapper,这是一个用于管理 Python 虚拟环境的工具。 激活虚拟环境 要激活你使用 mkvirtualenv 创建的虚拟环境,按照以下步骤操作: 1.确保已经安装了 virtu…...
网页在线客服系统自动欢迎语实现方案(PHP+MySQL)
一、实现思路 在网页在线客服系统中实现自动欢迎语,主要需要以下几个步骤: 在数据库中存储欢迎语内容判断用户是否为首次访问或新会话在适当时机自动发送欢迎消息 演示网站:gofly.v1kf.com 二、数据库设计 首先需要扩展数据库结构:…...

UniRig:如何在矩池云一站式解决 3D 模型绑定难题
在 3D 动画制作中,绑定(Rigging)是一个至关重要但复杂耗时的步骤。它包括为 3D 模型创建骨架并分配蒙皮权重,以实现流畅的动画效果。由清华大学与 Tripo 联合开发的 UniRig 框架,为这一难题提供了全新的解决方案。 什…...
用函数实现模块化程序设计(适合考研、专升本)
函数 定义:本质上是一段可以被连续调用、功能相对独立的程序段 c语言是通过“函数”实现模块化的。根据分类标准不同函数分为以下几类。 用户角度:库函数、自定义函数 函数形式:有参函数、无参函数 作用域:外部函数、内部函数 …...
玩转抖音矩阵:核心玩法与高效运营规则
一、 抖音矩阵:流量协同的生态网络 抖音矩阵,本质是运营一个相互关联、互相支持的抖音账号群。核心目标在于通过账号间的深度协同(内容、流量、粉丝),打破单个账号的流量天花板,实现11>2的效果。它不仅…...
spring:继承接口FactoryBean获取bean实例
spring框架提供接口FactoryBean获取bean实例。 实现步骤: 实现接口FactoryBean。 在xml文件中配置实现接口FactoryBean的类。 调用接口FactoryBean中方法getObject,获取bean实例。 实现接口类 package com.itheima.factory;import org.springframework…...

字符串字典序最大后缀问题详解
字符串字典序最大后缀问题详解 一、问题定义与背景1.1 问题描述1.2 实际应用场景 二、暴力解法及其局限性2.1 暴力解法思路2.2 代码示例2.3 局限性分析 三、双指针算法:高效解决方案3.1 算法核心思想3.2 算法步骤3.3 代码实现3.4 与暴力解法对比 四、复杂度分析4.1 …...

VScode打开后一直显示正在重新激活终端 问题的解决方法
一、问题 本人打开“.py”文件后,同时会出现以下两个问题。 1、VScode一直循环在”正在重新激活终端“ 2、日志显示intellicode报错: Sorry, something went wrong activating IntelliCode support for Python. Please check the “Python” and “VS I…...

pe文件结构(TLS)
TLS 什么是TLS? TLS是 Thread Local Storage 的缩写,线程局部存储。主要是为了解决多线程中变量同步的问题 如果需要要一个线程内部的各个函数调用都能访问,但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变…...
二进制安全-OpenWrt-uBus
1 需求 需求:ubus list 需求:ubus -v list 需求:ubus -v list zwrt_router.api 2 接口 rootOpenWrt:/# ubus Usage: ubus [<options>] <command> [arguments...] Options:-s <socket>: Set the unix domain …...
分页查询的实现
第一步:导入pom依赖 <!--配置PageHelper分页插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version><exclusions>…...

中型零售业数据库抉择:MySQL省成本,SQL SERVER?
针对中型零售企业(20台固定POS数十台移动POS,含库存管理与结算业务)的操作系统与数据库选型,需平衡性能、成本、扩展性及运维效率。结合行业实践与系统需求,建议如下: 🖥️ 一、操作系统选型…...
使用 Windows 完成 iOS 应用上架:Appuploader对比其他证书与上传方案
iOS 应用上架流程对很多开发者来说都是一道复杂关卡,特别是当你并不使用 Mac 电脑时。虽然 Apple 一直强调使用其原生工具链(Xcode 和 Transporter),但现实是大量开发者正在寻找更灵活的替代方案。 今天我将从证书申请和 IPA 上传…...

IDEA中的debug使用技巧
详细教学视频见b站链接:IDEA的debug调试 CSDN详细博客文章链接:debug文章学习 以下为个人学习记录总结: idea中的debug模式界面如下: 现在详细介绍图标作用: 图标一(Show Execution Point)&…...

RockyLinux9.6搭建k8s集群
博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…...
MS358A 低功耗运算放大器 车规
MS358A 低功耗运算放大器 车规 产品简述 MS358A 是双通道运算放大器,具有低功耗、宽电源电压范围、高单位增益带宽的特性。在特定情况下,压摆率可以达到0.4V/μs 。每个通道的静态电流 (5V) 只有 430μA 。 MS358A输入共模范围可以到地,同时…...

AI IDE 正式上线!通义灵码开箱即用
近期,通义灵码AI IDE正式上线,即日起用户可在通义灵码官网免费下载开箱即用。 作为AI原生的开发环境工具,通义灵码AI IDE深度适配了最新的千问3大模型,并全面集成通义灵码插件能力,具备编程智能体、行间建议预测、行间…...
CRMEB 中 PHP 快递查询扩展实现:涵盖一号通、阿里云、腾讯云
目前已有一号通快递查询、阿里云快递查询扩展 扩展入口文件 文件目录 crmeb\services\express\Express.php 默认一号通快递查询 namespace crmeb\services\express;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use think\Container; use thi…...

Ubuntu20.04基础配置安装——系统安装(一)
引言: 工作需要,Ubuntu的各类环境配置,从23年开始使用Ubuntu20.04之后,尽管能力在不断提升,但是依旧会遇到Ubuntu系统崩掉的情况,为了方便后续系统出现问题及时替换,减少从网上搜索资源进行基础…...
ubuntu opencv 安装
1.ubuntu opencv 安装 在Ubuntu系统中安装OpenCV,可以通过多种方式进行,以下是一种常用的安装方法,包括从源代码编译安装。请注意,安装步骤可能会因OpenCV的版本和Ubuntu系统的具体版本而略有不同。 一、安装准备 更新系统&…...
使用Python和Flask构建简单的机器学习API
在机器学习项目中,将模型部署为一个Web API是一种常见的需求。这样可以方便地将模型集成到其他应用程序中,例如移动应用、Web应用或其他后端服务。Flask是一个轻量级的Python Web框架,非常适合用于构建简单的API。本文将通过一个具体的例子&a…...

Kafka入门-消费者
消费者 Kafka消费方式:采用pull(拉)的方式,消费者从broker中主动拉去数据。使用pull的好处就是消费者可以根据自身需求,进行拉取数据,但是坏处就是如果Kafka没有数据,那么消费者可能会陷入循环…...