深入理解 Linux 基础 IO:从文件操作到缓冲区机制
亲爱的读者朋友们😃,此文开启知识盛宴与思想碰撞🎉。
快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。
在 Linux 系统中,文件输入输出(IO)操作是程序开发的基础部分,它涉及从简单的文件读写到复杂的系统调用和缓冲区管理。本文将基于相关知识进行详细梳理,帮助读者深入理解 Linux 基础 IO 的核心概念和操作原理。
目录
一、文件的多元理解
1.1 狭义与广义认知
1.2 文件构成与操作本质
二、以C语言为主,先回忆一下C接口
2.1 文件打开、读写与关闭
2.2 标准输入输出流
2.3 文件打开模式
三、系统文件 I/O 详解
3.1 系统调用接口与标志位传递
3.2 文件描述符
3.3 重定向原理与实现
四、“一切皆文件” 的深度剖析
五、缓冲区机制探究
5.1 引入一些奇怪的现象
5.2 缓冲区不在操作系统内部
5.3 缓冲区的刷新策略
5.4 为什么要有缓冲区
5.5 用户层缓冲区在哪
5.6 内核缓冲区在哪
一、文件的多元理解
1.1 狭义与广义认知
狭义:
- 文件在磁盘里
- 磁盘是永久性存储介质,因此文件在磁盘上的存储是永久性的
- 磁盘是外设(即是输出设备也是输入设备)
- 磁盘上的文件 本质是对文件的所有操作,都是对外设的输入和输出 简称 IO
广义:
在 Linux “一切皆文件” 的理念下,键盘、显示器、网卡等硬件设备都被抽象为文件。这种广义理解极大地简化了系统资源的访问方式,开发者可以使用统一的文件操作接口来与不同设备交互。
1.2 文件构成与操作本质
文件由文件属性(元数据)和文件内容组成。所有文件操作归根结底是对文件内容和属性的操作,⭐而这些操作在系统层面是由进程执行的,进程通过系统调用接口来实现文件的读写等操作,C 语言的库函数只是为用户提供了更便捷的调用方式🌈。
二、以C语言为主,先回忆一下C接口
2.1 文件打开、读写与关闭
C 标准库提供了一系列文件操作函数,如fopen
用于打开文件,其打开路径默认是程序当前路径,可通过/proc/[进程id]/cwd
查看。fwrite
和fread
分别用于文件的写入和读取,在使用fread
时需注意返回值和参数设置。文件使用完毕后,要用fclose
关闭,以释放资源。
fopen
是 C 语言中用于打开文件的函数,其函数原型为:
FILE *fopen(const char *filename, const char *mode);
特性
- 文件打开模式:
mode
参数决定了文件的打开方式,常见的有:
r
:以只读方式打开文本文件。文件必须存在,否则打开失败。w
:以写入方式打开文本文件。若文件不存在则创建;若存在则会清空文件原有内容 ,从头开始写入新数据。a
:以追加方式打开文本文件。文件不存在时创建;存在时则定位到文件末尾,新写入的数据会追加在原有内容之后。- 返回值:函数调用成功时返回一个指向
FILE
类型的指针,后续对文件的读写操作可通过该指针进行;若打开失败则返回NULL
。
FILE- 与操作系统交互:
fopen
函数依赖操作系统提供的文件管理功能,其文件打开模式的特性(如w
模式清空文件)是操作系统文件系统的特性,并非 C 语言本身独有。
代码示例
#include <stdio.h>
#include <stdlib.h>int main() {// 以写入模式打开文件FILE *writeFile = fopen("test.txt", "w");if (writeFile == NULL) {perror("Failed to open file for writing");return 1;}fprintf(writeFile, "This is a test content.\n");fclose(writeFile);// 以追加模式打开文件FILE *appendFile = fopen("test.txt", "a");if (appendFile == NULL) {perror("Failed to open file for appending");return 1;}fprintf(appendFile, "This content is appended.\n");fclose(appendFile);// 以只读模式打开文件FILE *readFile = fopen("test.txt", "r");if (readFile == NULL) {perror("Failed to open file for reading");return 1;}char buffer[100];while (fgets(buffer, sizeof(buffer), readFile) != NULL) {printf("%s", buffer);}fclose(readFile);return 0;
}
上述代码中:
- 首先以
w
模式打开文件test.txt
,写入一行文本,此时若文件存在会被清空。- 接着以
a
模式打开同一文件,追加写入一行文本。- 最后以
r
模式打开文件,读取并打印文件内容,展示了不同打开模式的效果。每次操作完成后,都使用fclose
函数关闭文件,以释放相关资源。
fwrite
函数原型为size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
,其中ptr
是指向要写入的数据块的指针;size
是每个数据块的大小(以字节为单位);count
是要写入的数据块的数量;stream
是指向目标文件的指针。返回值是实际写入的数据块数目。fprintf
函数原型为int fprintf(FILE *stream, const char *format, ...)
,stream
是指向要写入的文件的指针;format
是格式化字符串。
2.2 标准输入输出流
C 默认打开stdin
(标准输入) 0 、stdout
(标准输出) 1 和stderr
(标准错误) 2 三个流,它们的类型都是FILE*
。可以使用fwrite
、printf
、fprintf
等函数向stdout
输出信息,不同函数在输出方式和格式化上各有特点。
2.3 文件打开模式
文件打开模式决定了文件的访问权限和初始位置,如r
表示只读打开,w
表示只写打开并截断文件,a
表示追加写等。正确选择打开模式对文件操作的准确性和安全性至关重要。
三、系统文件 I/O 详解
3.1 系统调用接口与标志位传递
系统文件 IO 提供了底层的文件访问方式,以open
函数为例,它可以通过标志位指定打开文件的方式。标志位采用位运算进行组合,如O_RDONLY
(只读)、O_WRONLY
(只写)、O_CREAT
(创建文件)等,开发者可根据实际需求进行灵活设置。
#include <stdio.h>
// 定义标志位 ONE,对应的二进制为 0000 0001
#define ONE 0001
// 定义标志位 TWO,对应的二进制为 0000 0010
#define TWO 0002
// 定义标志位 THREE,对应的二进制为 0000 0100
#define THREE 0004 // 该函数用于根据传入的标志位判断包含哪些特定标志并输出信息
void func(int flags) {// 通过位与运算判断 flags 中是否包含 ONE 标志位if (flags & ONE) printf("flags has ONE! ");// 通过位与运算判断 flags 中是否包含 TWO 标志位if (flags & TWO) printf("flags has TWO! ");// 通过位与运算判断 flags 中是否包含 THREE 标志位if (flags & THREE) printf("flags has THREE! ");// 换行printf("\n");
}int main() {// 调用 func 函数,传入 ONE 标志位func(ONE);// 调用 func 函数,传入 THREE 标志位func(THREE);// 调用 func 函数,传入通过位或运算组合的 ONE 和 TWO 标志位func(ONE | TWO);// 调用 func 函数,传入通过位或运算组合的 ONE、TWO 和 THREE 标志位func(ONE | THREE | TWO);// 程序正常结束返回 0return 0;
}
open
函数是用于打开或创建文件的系统调用
函数原型:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
参数解释
pathname
:这是一个字符串,代表要打开或创建的文件的路径。它可以是绝对路径(例如/home/user/file.txt
),也可以是相对路径(例如file.txt
)。flags
:该参数是一个整数,用来指定文件的打开方式。以下是一些常见的标志:
O_RDONLY
:以只读模式打开文件。O_WRONLY
:以只写模式打开文件。O_RDWR
:以读写模式打开文件。O_CREAT
:若文件不存在,则创建该文件。使用此标志时,需要提供第三个参数mode
来指定文件的权限。O_EXCL
:与O_CREAT
一起使用时,如果文件已经存在,则open
调用会失败。O_TRUNC
:若文件存在且以写模式打开,则将文件截断为长度为 0。O_APPEND
:以追加模式打开文件,写入数据时会追加到文件末尾。mode
:当使用O_CREAT
标志时,需要提供这个参数来指定新创建文件的权限。它是一个八进制数,例如0644
表示文件所有者有读写权限,而组用户和其他用户只有读权限。
返回值
- 若
open
调用成功,会返回一个新的文件描述符(一个非负整数),后续可使用该文件描述符进行文件操作。- 若调用失败,会返回 -1,并设置
errno
来指示错误类型。
3.2 文件描述符
文件描述符是一个小整数,Linux 进程默认有 0(标准输入)、1(标准输出)、2(标准错误)三个缺省打开的文件描述符。文件描述符本质是进程打开文件表中对应文件指针数组的下标,通过它可以找到对应的文件。其分配规则是在数组中寻找当前未使用的最小下标,这一特性在文件操作中具有重要意义。(高效利用资源)
3.3 重定向原理与实现
重定向是改变文件描述符默认指向的操作,常见的重定向符号有>
(输出重定向)、>>
(追加输出重定向)、<
(输入重定向)。
通过关闭特定的文件描述符并重新打开文件,可以实现重定向。
// 标准输出重定向函数
void redirect_stdout(const char *filename) {// 关闭标准输出文件描述符close(STDOUT_FILENO);// 以写入和创建模式打开文件,若文件存在则截断内容int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 此时新打开的文件会占用之前关闭的标准输出文件描述符(1)printf("这行内容会被重定向到文件中。\n");close(fd);
}
dup2
系统调用也可用于实现重定向,它能将一个文件描述符的内容复制到另一个文件描述符,从而改变数据的流向。
下面将详细介绍 dup2
函数的用法:
函数原型
#include <unistd.h>int dup2(int oldfd, int newfd);
参数解释
oldfd
:这是已存在的文件描述符,⭐dup2
会将这个文件描述符所引用的文件表项复制到newfd
所代表的文件描述符上。newfd
:这是目标文件描述符,dup2
会把oldfd
的文件表项复制到这里。如果newfd
之前已经打开了一个文件,dup2
会先关闭newfd
对应的文件,然后再进行复制操作。
返回值
- 若调用成功,
dup2
会返回newfd
,也就是复制后的文件描述符。- 若调用失败,会返回 -1,并设置
errno
来指示具体的错误类型。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>int main() {int fd;// 以写入模式打开文件,如果文件不存在则创建,存在则截断内容fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open");return 1;}// 使用 dup2 将标准输出(文件描述符为 1)重定向到新打开的文件if (dup2(fd, STDOUT_FILENO) == -1) {perror("dup2");close(fd);return 1;}// 关闭原文件描述符,因为已经完成复制close(fd);// 此时 printf 的输出会重定向到文件中printf("这行内容会被重定向到 output.txt 文件中。\n");return 0;
}
那重定向的本质是什么呢?
⭐重定向的实现原理:
重定向的核心是改变文件描述符对应的数据流向。在操作系统中,每个进程有标准输入(文件描述符 0,默认连键盘)、标准输出(文件描述符 1,默认连屏幕)和标准错误输出(文件描述符 2,默认连屏幕)。重定向操作就是修改这些文件描述符的连接目标:
- 输出重定向:
>
将标准输出重定向到文件,覆盖原有内容;>>
同样重定向到文件,但追加内容。- 输入重定向:
<
把标准输入从键盘重定向到文件。- 错误输出重定向:
2>
将标准错误输出重定向到文件。
四、“一切皆文件” 的深度剖析
在 Linux 系统中,不仅常规文件,进程、硬件设备、管道、套接字等都被视为文件。操作系统为每个打开的文件创建file
结构体,其中的f_op
指针指向file_operations
结构体,该结构体中的函数指针对应着各种系统调用,如read
、write
等。这种机制使得开发者可以用统一的文件操作接口来访问不同类型的资源,极大地简化了开发过程,提高了代码的通用性和可维护性。
上图中的外设,每个设备都可以有自己的 read、write,但一定是对应着不同的操作方法!😎 但通过
struct file
下file_operation
中的各种函数回调,让我们开发者只用 file 便可调取 Linux 系统中绝大部分的资源!👏 这便是 “linux 下一切皆文件” 的核心理解。😄
五、缓冲区机制探究
5.1 引入一些奇怪的现象
- 现象 1:在向文件写入时,write 函数的内容会先被打印出来。通过如下代码验证:
#include <stdio.h>
#include <string.h>
#include <unistd.h>int main()
{const char *fstr = "hello fwrite\n";const char *str = "hello write\n";printf("hello printf\n"); // stdout -> 1fprintf(stdout, "hello fprintf\n"); // stdout -> 1fwrite(fstr, strlen(fstr), 1, stdout); // fread, stdout->1write(1, str, strlen(str)); // 1return 0;
}
当直接运行程序时,输出顺序为:
当将输出重定向到文件(./text > log.txt
)后,用 cat log.txt
查看,输出顺序变为:
这是因为 printf
、fprintf
、fwrite
这些 C 库函数有缓冲区,数据先存缓冲区,而 write
是系统调用,直接操作,所以先被打印。重定向时,缓冲区刷新策略改变,之前在缓冲区的数据后被刷新到文件。
变化如下:
输出到显示器时
此时标准输出采用行缓冲策略,即:
- 数据先写入用户空间的缓冲区,当遇到换行符(
\n
)、缓冲区被填满、程序正常结束 ,或者调用了fflush
等刷新函数时,缓冲区中的数据才会被刷新到内核缓冲区,进而显示在屏幕上。在代码printf("hello printf\n");
、fprintf(stdout, "hello fprintf\n");
、fwrite(fstr, strlen(fstr), 1, stdout);
中,输出的内容带有换行符,满足行缓冲的刷新条件,所以会依次输出。- 像
write
这类系统调用函数,它直接操作内核缓冲区,不经过 C 库的用户缓冲区,数据会立即被写入,所以write
的内容也能及时显示 ,因此运行程序时看到的输出顺序是按代码顺序来的。重定向到普通文件时
这种情况下标准输出采用全缓冲策略,即:
printf
、fprintf
、fwrite
这类 C 库函数写入的数据先暂存于用户缓冲区,直到缓冲区被填满,或者程序结束,又或者主动调用fflush
函数时,数据才会被刷新到内核缓冲区,最终写入文件。在重定向输出时,printf
、fprintf
、fwrite
这几个函数输出的数据因为缓冲区未满且未主动刷新,所以一直留在缓冲区中 。- 而
write
作为系统调用,不依赖 C 库缓冲区,会直接将数据写入文件,所以在使用cat
查看重定向文件内容时,write
的内容先出现。直到程序结束,缓冲区统一刷新,printf
、fprintf
、fwrite
对应的数据才依次写入文件,这就导致用cat
查看文件时出现了和直接在终端运行程序不同的输出顺序。
- 现象 2:加入
fork
之后,向文件写入时 C 接口会被调两次,且write
先被打印。代码如下:
int main()
{const char *fstr = "hello fwrite\n";const char *str = "hello write\n";printf("hello printf\n"); fprintf(stdout, "hello fprintf\n"); fwrite(fstr, strlen(fstr), 1, stdout); write(1, str, strlen(str));
/*函数原型:ssize_t write(int fd, const void *buf, size_t count)fd:文件描述符,通过open等函数打开文件或设备得到,用于指定要写入的目标。buf:指向要写入数据的缓冲区的指针,可以是字符数组等。count:要写入的字节数。返回值:成功时返回实际写入的字节数(可能小于count);失败时返回-1 */fork();return 0;
}
和现象 1 类似,前三个 C 接口数据存缓冲区,write
先输出。
fork
时,子进程复制父进程缓冲区数据,当进程退出刷新缓冲区,所以 C 接口数据被打印两次。
- 现象 3:关闭文件描述符 1(
close(1)
)后,就没有结果输出。代码如下:
int main()
{const char *str = "hello write";write(1, str, strlen(str)); fprintf(stdout,str);close(1); return 0;
}
这段代码运行时没有完整输出结果,主要是因为标准输出缓冲区和文件描述符关闭机制的影响,下面为你详细解释:
1. 标准输出的缓冲机制
在 C 语言中,标准输出(
stdout
,文件描述符为 1)存在缓冲区。当你使用printf
、fprintf
等 C 库函数进行输出时,数据并不会立即被输出到终端,而是先被存储在用户空间的缓冲区中。缓冲区的刷新时机取决于不同的缓冲策略,常见的有行缓冲、全缓冲和无缓冲:
- 行缓冲:当遇到换行符(
\n
)、缓冲区满或者手动调用fflush
函数时,缓冲区中的数据会被刷新到内核,进而输出到终端。标准输出连接到终端时默认采用行缓冲策略。- 全缓冲:只有当缓冲区满、程序正常结束或者手动调用
fflush
函数时,缓冲区中的数据才会被刷新。标准输出重定向到文件时通常采用全缓冲策略。- 无缓冲:数据会立即被输出,不会进行缓冲。标准错误输出(
stderr
)通常采用无缓冲策略。2. 代码中
write
函数的执行情况在代码里,
write
是一个系统调用函数,它直接将数据写入内核,不经过 C 库的用户缓冲区。当执行write(1, str, strlen(str));
时,"hello write"
会被直接写入到标准输出对应的内核缓冲区。但由于字符串末尾没有换行符,在行缓冲策略下,这些数据可能还没有被刷新到终端。3.
close(1)
的影响
close(1)
会关闭标准输出的文件描述符。文件描述符是操作系统用来标识打开文件的整数,关闭文件描述符后,后续无法再通过该文件描述符进行读写操作。由于之前write
写入的数据还在标准输出的内核缓冲区中,没有被刷新到终端,关闭文件描述符后,这些数据就无法再被输出,因此看不到完整的输出结果。解决方案
若要确保数据能完整输出,可以在关闭文件描述符之前手动刷新缓冲区。以下是修改后的代码:
#include <stdio.h> #include <unistd.h> #include <string.h>int main() {const char *str = "hello write\n"; // 添加换行符,触发行缓冲刷新write(1, str, strlen(str));fprintf(stdout,str);// 或者使用 fflush(stdout); 手动刷新标准输出缓冲区close(1);return 0; }
![]()
在上述代码中,给字符串添加了换行符
\n
,这样在执行write
时,由于行缓冲策略,数据会被立即刷新到终端。或者使用fflush(stdout);
手动刷新标准输出的缓冲区,也能确保数据完整输出。
5.2 缓冲区不在操作系统内部
通过现象 3 可知,
close
作为系统调用接口不能在关闭文件前刷新缓冲区,说明操作系统看不到这个缓冲区。printf
、fprintf
、fwrite
等 C 库函数提供了一个缓冲区,先将内容存于此,需要刷新时才调用write
函数写入。进程退出时会刷新缓冲区,但close
后,文件描述符关闭,即使调用write
也无法写入,缓冲区数据被丢弃。
5.3 缓冲区的刷新策略
- 无缓冲:数据直接刷新,常见于
stderr
,比如fputs
操作直接刷新到显示器文件。- 行缓冲:遇到换行符时刷新,像标准输出到显示器默认是行缓冲 ,数据先存缓冲区,遇到换行才写入。
- 全缓存:缓冲区写满或者调用
fflush
等函数强制刷新时,数据才写入,普通文件默认是全缓存。
不同策略是为满足不同场景需求。显示器行刷新可及时显示信息,普通文件全缓存可减少系统调用次数提升效率。
5.4 为什么要有缓冲区
- 方便使用:如同寄快递,不用自己长途运送物品,交给快递站更省心。数据先存缓冲区,不用每次小量数据就直接操作硬件,使用更便捷。
- 提高效率:攒够一定量数据再操作硬件,类似装满一袋快递再运送,减少操作次数,提高整体效率。
- 配合格式化:比如 C 语言中整数格式化后再写入,可在缓冲区完成格式化操作,减少对硬件的直接频繁操作。
5.5 用户层缓冲区在哪
exit
函数会调用 fflush
刷新缓冲区数据。fflush
函数操作的是 FILE*
类型指针指向的流对应的缓冲区。FILE
结构体不仅封装了文件描述符 fd
信息,还维护了对应文件的缓冲区字段和文件信息。打开一个文件就有专属缓冲区,通过 fprintf
等函数操作文件时,数据先进入该缓冲区。
5.6 内核缓冲区在哪
内核缓冲区由操作系统的 file
结构体维护,和用户层缓冲区类似。用户一般无需关心其刷新时间,只要数据刷新到内核,就能到达硬件 ,因为现代操作系统会高效管理,避免浪费资源。
通过对 Linux 基础 IO 各个方面的梳理,我们对文件操作、系统调用、缓冲区机制等有了更深入的理解。这些知识是 Linux 系统开发的重要基础,对于开发者编写高效、稳定的程序具有重要指导意义。在实际开发中,应根据具体需求合理选择文件操作方式和缓冲区策略,以充分发挥 Linux 系统的优势。
相关文章:
深入理解 Linux 基础 IO:从文件操作到缓冲区机制
亲爱的读者朋友们😃,此文开启知识盛宴与思想碰撞🎉。 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 在 Linux 系统中,文件输入输出(IO)…...
汇编语言高级编程技巧:从基础到进阶
前言 汇编语言作为底层编程语言,直接操作硬件,执行效率高,但编写复杂逻辑时往往显得繁琐。通过使用汇编伪指令和宏,我们可以实现类似于高级语言的结构,如条件判断、循环、结构体和函数等,从而提升代码的可读…...
Android Studio常见问题解决
一、环境配置问题 1. 安装失败 问题描述:在安装过程中,可能会遇到硬件要求不符合、网络问题、安装包损坏、权限不足或安装路径问题等,导致安装失败。 解决方法: 硬件要求:确保设备满足最低硬件要求。 网络问题&…...
【RHCE】LVS-NAT模式负载均衡实验
目录 题目 IP规划 配置IP RS1 RS2 RS3 LVS client 配置RS 配置LVS 安装lvs软件 启动ipvsadm服务 lvs规则匹配 ipvsadm部分选项 客户端测试 总结 题目 使用LVS的 NAT 模式实现 3 台RS的轮询访问,IP地址和主机自己规划。 IP规划 主机IP地址RS1-nat模…...
MacOS下的IntelliJ IDEA突然无法访问本机的虚拟机
今天在开发的过程中,突然遇到一个怪事,之前运行的好好的程序,突然间报无法连接redis服务器,一开始以为是网络问题,在OS的terminal里又是ping 又是telnet的,一切正常,可是程序就是连不上。 挠了半…...
【渗透测试】Fastjson 反序列化漏洞原理(一)
目录 一、Fastjson 是什么二、Fastjson 工作原理三、反序列化漏洞原理1. 反序列化漏洞的定义2. Fastjson 的反序列化机制3. 漏洞成因关注以下几点(1) 动态类型解析(2) 自动调用方法(3) 信任用户输入 4. 漏洞利用过程(1) 寻找可利用的类(也称为 "Gadget"&a…...
BM100-K系列开关量输入信号隔离器
1. 产品概述 BM100-K系列开关量输入信号隔离器是一款高性能的信号处理设备,专为工业自动化控制系统设计。该产品支持干接点或NAMUR型接近开关输入,并通过继电器或晶体管实现隔离输出。其核心功能包括输入输出逻辑控制(同相/反相可调…...
c++11 | 细说智能指针
💓个人主页:mooridy 💓专栏地址:C 关注我🌹,和我一起学习更多计算机的知识 🔝🔝🔝 什么是智能指针? 智能指针是 C 中一种用于管理动态内存的机制。它提供了一…...
谷歌大型推理模型曝光!击败Claude-3.7-Thinking
哎!最近推特上的网友在LMSYS Arena 发现了个泄漏的大模型 Nebula,效果据说特别好,打败了o1、o3-mini、Claude 3.7 Thinking等模型: 网友们通过询问和分析 API,发现这似乎是谷歌正在秘密测试的新推理模型!推…...
Python FastAPI面试题及参考答案
目录 FastAPI 的优缺点是什么?列举典型应用场景。 解释 FastAPI 的路由机制,如何定义路径参数和查询参数? Pydantic 模型在 FastAPI 中的作用是什么?如何进行数据验证与序列化? FastAPI 如何自动生成 OpenAPI 文档?Swagger UI 和 ReDoc 的区别? 什么是 ASGI?FastAP…...
C++(初阶)(八)——string
string string遍历下标[]迭代器iterator反向迭代器 范围for修改 Capacitysize和lengthmax_sizecapacityclearcapacity的扩容reserveresize Element accessoperator[]和at **Modifiers**:appendinserterasereplace String operationsc_strsubstr和findfind_first_ofgetline 题目…...
计算机操作系统处理机调度(1)
系列文章目录 第三章:处理机调度与死锁 文章目录 系列文章目录前言一、作业和资源:二、处理机调度的层次: 1.高级调度2.初级调度3.中级调度 三、作业调度算法举例:总结 前言 在多道程序的环境下,内存中存在着多个进…...
ctfshow REVERSE re2 萌新赛 内部赛 七夕杯 WP
目录 re2 萌新赛 flag白给 签退 数学不及格 内部赛 批量生产的伪劣产品 来一个派森 好好学习 天天向上 屏幕裂开了 七夕杯 逆向签到 easy_magic re2 ida分析主函数,将flag.txt内容加密写入enflag.txt 这是密钥加密过程 标准rc4加密 简单异或解…...
云服务器怎么设置端口禁用呢?
在云服务器上禁用特定端口是提升安全性的重要措施,可通过云平台安全组和服务器本地防火墙双重配置实现。以下是详细操作指南: 一、通过云平台安全组禁用端口(优先推荐) 1. 莱卡云/腾讯云/华为云等操作步骤 登录云控制台 进入ECS实…...
V8引擎源码编译踩坑实录
背景 为了解决 view8 代码没有指定版本的 v8 引擎问题GitHub - suleram/View8: View8 - Decompiles serialized V8 objects back into high-level readable code. 但是打出来了exe文件也没啥用,不清楚这个view8是解决啥逆向用的,如果想逆向electron的j…...
享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术来高效地支持大量细粒度对象的复用。 一、基础 1 意图 运用共享技术有效地支持大量细粒度的对象 减少内存中对象的数量,节省系统资源 2 适用场景 一个应用程序使用了大量对象 由于对象数量庞大造成很大的…...
RAG(Retrieval-Augmented Generation)基建之PDF解析的“魔法”与“陷阱”
嘿,亲爱的算法工程师们!今天咱们聊一聊PDF解析的那些事儿,简直就像是在玩一场“信息捉迷藏”游戏!PDF文档就像是个调皮的小精灵,表面上看起来规规矩矩,但当你想要从它那里提取信息时,它就开始跟…...
搭建小程序该如何选择服务器?
当企业选择开发属于自己的小程序,则需要服务器的支持,服务器可以帮助加速小程序的上线速度,影响小程序后面的运行是否流畅,同时还会影响用户访问网站时的速度,所以,企业在搭建小程序时该如何选择合适的服务…...
【腾讯云架构师技术沙龙2025.03.22】
大模型技术演进与行业影响分析 日期:2025年3月22日 主讲人:李建忠 《DeepSeek实战驱动行业智变—AI应用寒武纪》 整理:飞书语音转化DeepSeek分析汇总 一、技术演进:从快思考到慢思考 1. 早期争议与能力局限(2022-202…...
【jvm】垃圾回收的并行和并发
目录 1. 说明2. 并行(Parallel)2.1 定义2.2 特点2.3 示例 3. 并发(Concurrent)3.1 定义3.2 特点3.3 示例 4. 并行与并发的比较 1. 说明 1.在JVM(Java虚拟机)的垃圾回收机制中,并行(…...
Flowable基础表结构
工作流程的相关操作都是操作存储在对应的表结构中,为了能更好的弄清楚Flowable的实现原理和细节,我们有必要先弄清楚Flowable的相关表结构及其作用。在Flowable中的表结构在初始化的时候会创建相关表结构,具体如下: ACT_EVT&…...
为什么不同的损失函数可以提升模型性能?
不同的损失函数可以提升模型性能的原因在于,损失函数是模型优化的核心目标,它直接定义了模型在训练过程中需要最小化的误差或偏差。通过设计不同的损失函数,可以针对具体任务的特点、数据分布的特性以及模型的目标需求进行更精确的优化&#…...
git上传文件到远程库
1.git init 把这个目录变成git可以管理的仓库 2.git status查看文件追踪的情况(工作区的文件是红色) 3.git add . 添加工作区所有文件到暂存区 再git status(此时文件都变成绿色) 4.git commit -m 描述性文字 5.git push -u o…...
【产品小白】需求分析的进阶
在产品经理的职业发展中,需求分析能力的提升至关重要。普通和进阶在需求分析层面,往往存在从表面需求到本质问题的认知差异。以下从几个方面探讨这一进阶过程: 1. 需求理解的深度 普通:通常停留在用户表达的显性需求层面&#…...
机试题汇总
万能头文件 #include<bits/stdc.h> 输入一个年份和月份,输出该月的天数 1.3.5.7.8.10.12 -- 31天 闰年判断: year % 400 0 || (year % 4 0 && year % 100 ! 0) 输入字符串,反转输出 #include<iostream&g…...
软件公司高新技术企业代办:机遇与陷阱并存-优雅草卓伊凡
软件公司高新技术企业代办:机遇与陷阱并存-优雅草卓伊凡 在科技飞速发展的当下,软件公司如雨后春笋般涌现,众多企业渴望通过申请高新技术企业来获得政策支持与发展助力。随之而来的,是高新技术企业代办业务的兴起。然而ÿ…...
C#中3维向量的实现
c#中默认不带库三维向量,需要自己安装第三方库,或者可以手动实现一个简易的三维向量。 public struct Vector3D {public double X { get; set; }public double Y { get; set; }public double Z { get; set; }public Vector3D(double x, double y, doubl…...
使用腾龙边缘计算网关内置的AIoTedge+NodeRED接入西门子PLC
腾龙边缘计算网关一体机凭借其强大的性能和丰富的功能,为企业提供了一种高效、灵活的解决方案。本文将详细介绍如何使用腾龙边缘计算网关一体机内置的AIoTedgeNodeRED接入西门子PLC,实现数据的采集、处理与传输。 一、硬件准备与环境搭建 在开始之前&am…...
基于MLA的人类语音情感分类
《DeepSeek大模型高性能核心技术与多模态融合开发(人工智能技术丛书)》(王晓华)【摘要 书评 试读】- 京东图书 随着信息技术的不断发展,如何让机器识别人类情绪,这个问题受到了学术界和工业界的广泛关注。目前,情绪识…...
Codeforces Round 1012 (Div. 2)
AB略 C 没看懂题意,翻译的问题。t0代表这个人必须找一个没有人的桌子且座位离他最近,t1代表这个人只要找一个空座位就可以了。一个桌子四个座位,t0肯定会坐左下角的那个。首先建立两个小根堆q1代表左下角的座位,q2代表一个桌子的…...
FPGA时钟约束
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Create_clock 前言 时钟周期约束,就是对时钟进行约束。 一、Create_clock create_clock -name <name> -period <period> -waveform …...
二分查找------练习3
1. 题目 2. 思路和题解 这道题看到这个复杂度,就想到应该是使用二分查找进行求解。为了使二分查找的次数尽可能的少,我们需要对较短的数组进行查找,假设就在nums1上进行操作,因此在开始时,要对两个数组的长度进行一个…...
拆解美团2024年报,业务协同、生态共赢、科技创新
从早期的千团大战开始,到后来外卖和社区团购们的激烈角逐,再到现在即时零售战场的群雄争霸,本地生活的硝烟从来都没有真正消散过。 作为本地生活服务领域的“领头羊”——美团,也一直都是其他平台们的挑战目标,几乎所…...
EMS小车技术特点与优势:高效灵活的自动化输送解决方案
北成新控伺服技术丨EMS小车调试视频 EMS小车是一种基于单轨运行的电动输送系统,通过电力驱动实现物料的高效搬运和输送,具有高效灵活、节能环保、多功能集成、行业适配性强等特性,广泛应用于汽车制造、工程机械、家电生产、仓储物流等行业自动…...
GESP2025年3月认证解析
GESP一级 一、单选题 答案:D 解析:DeepSeek 是字节跳动公司开发的人工智能,它具备生成文本的能力,所以可以根据《哪吒 2》的场景生成剧情脚本。A 选项中《哪吒 2》是贺岁片,并非新型操作系统;B 选项 Deep…...
尝试在软考62天前开始成为软件设计师-信息系统安全
安全属性 保密性:最小授权原则(能干活的最小权限)、防暴露(隐藏)、信息加密、物理保密完整性(防篡改):安全协议、校验码、密码校验、数字签名、公证 可用性:综合保障( IP过滤、业务流控制、路由选择控制、审计跟踪)不可抵赖性:数字签名 对称加密 DES :替换移位 3重DESAESR…...
Dify - 架构、部署、扩展与二次开发指南
本文详细解析 Dify 的架构、部署流程、高可用中间件的独立部署方法,以及二次开发流程,帮助开发者更高效地管理和扩展 Dify。 1. 本地DEMO部署 安装Docker,执行下面脚本,可能需要配置镜像。 git clone https://github.com/langge…...
用DrissionPage升级网易云音乐爬虫:更稳定高效地获取歌单音乐(附原码)
一、传统爬虫的痛点分析 原代码使用requests re的方案存在以下局限性: 动态内容缺失:无法获取JavaScript渲染后的页面内容 维护成本高:网页结构变化需频繁调整正则表达式 反爬易触发:简单请求头伪造容易被识别 资源消耗大&am…...
详细Linux中级知识(不断完善)
Nginx服务配置 基于主机名配置 映射IP和主机名 [rootlocalhost ~]# vim /etc/hosts 192.168.72.135 www.chengke.com chengke[rootlocalhost ~]# echo "192.168.72.135 www.xx.com" >> /etc/hosts以上是两种方法,前面是你的IP地址,后…...
Softmax温度调节与注意力缩放:深度神经网络中的平滑艺术
Softmax温度调节与注意力缩放:深度神经网络中的平滑艺术 在深度学习的精密机械中,有些细微的调整机制往往被视为理所当然,却实际上蕴含着深刻的数学洞察和巧妙的工程智慧。今天,我们将探讨两个看似独立却本质相通的机制ÿ…...
python打包辅助工具
python打包辅助工具 PyInstaller 是一个非常流行的 Python 应用程序打包工具,它可以将 Python 脚本及其依赖项打包成独立的可执行文件,方便在没有 Python 环境的机器上运行。关于PyInstaller,可参见:https://blog.csdn.net/cnds1…...
jangow靶机攻略
配置网卡 VMware需要配置,不配置扫不到ip,VirtualBox正常打开ip会直接显示出来 网卡配置都改成NAT 打开虚拟机,第一个框选第二行,回车 选第二个,按e键 进入下一个框后,将ro 后面的修改为 rw signin init/bin/bash 按…...
【大模型LLM第十四篇】Agent学习之anthropic-quickstarts Agent
前言 对于anthropic api的快速使用,在github上有几个example Customer Support Agent:由 Claude 提供支持的客户支持代理。该项目演示了如何利用 Claude 的自然语言理解和生成功能来创建可访问知识库的 AI 辅助客户支持系统。Financial Data Analyst &…...
MonIo部署
1、命令行安装 访问monio官网下载应用程序 # wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20250228095516.0.0-1.x86_64.rpm -O minio.rpm # sudo dnf install minio.rpm # mkdir ~/minio # minio server ~/minio --console-address :90012、dock…...
深入理解智能家居领域中RS485、Modbus、KNX 和 Zigbee协议概念
首先详细介绍一下 RS485 和 Modbus 这两个在工业自动化和数据通讯领域中非常重要的概念。 RS485 1. 定义与特点 RS485 标准:RS485 是一种串行通信标准,也称为TIA-485标准,主要用于数据传输。它规定了物理层的电气特性,与数据格式…...
Spring Boot深度解析:从核心原理到最佳实践
一、Spring Boot概述 Spring Boot作为Spring生态中的"游戏规则改变者",自2014年发布以来彻底改变了Java企业级应用的开发方式。它通过四大核心特性显著提升了开发效率: 自动配置:基于类路径和已有Bean的智能默认配置起步依赖:简化Maven/Gradle依赖管理的Starter…...
MapReduce过程中reduce task的数量是如何确定的?
在Hadoop MapReduce及Hive中,numReduceTasks(Reduce任务数量)的确定由用户显式设置、框架自动估算、作业特性约束三方面共同决定。以下是详细解析及示例: 1. 用户显式设置 用户可以通过代码或配置参数直接指定Reduce任务数&#…...
【euclid】21 3D包围盒模块(box3d.rs)
box3d.rs文件定义了一个三维轴对齐的矩形框(Box3D),使用最小和最大坐标来表示。矩形框在坐标类型(T)和单位(U)上是泛型的。代码提供了多种方法来操作和查询矩形框,包括求交集、并集、…...
用selenium+ChromeDriver豆瓣电影 肖申克的救赎 短评爬取(pycharm 爬虫)
一、豆瓣电影 肖申克的救赎 短评url=https://movie.douban.com/subject/1292052/comments 二、基本知识点讲解 1. Selenium 的基本使用 Selenium 是一个用于自动化浏览器操作的库,常用于网页测试和爬虫。代码中使用了以下 Selenium 的核心功能: webdriver.Chrome: 启动 Chr…...
mysql入门操作
目录 一,MySQL简述 1,什么是MySQL 2,什么是SQL 3,SQL的分类 二,数据库的数据存储类型 1,数值类型 2,字符串类型 3,时间和日期类型 三,数据库的基本操作 1&…...