网站推广外包公司/在线网站分析工具

网站推广外包公司,在线网站分析工具,鹤壁seo,女生做网站编辑怎么样在 Linux 操作系统中,文件 I/O(输入/输出)是程序与文件系统交互的基础。理解文件 I/O 的工作原理对于编写高效、可靠的程序至关重要。本文将深入探讨系统文件 I/O 的机制。 一种传递标志位的方法 在 Linux 中,文件的打开操作通常…

在 Linux 操作系统中,文件 I/O(输入/输出)是程序与文件系统交互的基础。理解文件 I/O 的工作原理对于编写高效、可靠的程序至关重要。本文将深入探讨系统文件 I/O 的机制。


一种传递标志位的方法

在 Linux 中,文件的打开操作通常使用标志位来指定文件的访问模式。open() 系统调用用于打开文件,其原型如下:

int open(const char *pathname, int flags, mode_t mode);
  • pathname:要打开的文件路径。
  • flags:打开文件时的标志位,指定文件的访问模式和行为。
  • mode:文件权限,仅在创建新文件时使用。

常见的标志位包括:

参数必须包括以下三个访问方式之一。

- `O_RDONLY`:只读模式。
- `O_WRONLY`:只写模式。
- `O_RDWR`:读写模式。

其他的访问模式。

- `O_CREAT`:如果文件不存在,则创建文件。
- `O_TRUNC`:如果文件存在,则将其长度截断为零。
- `O_APPEND`:每次写入都追加到文件末尾。

标志位的原理:

原理就是位图。不同的访问模式位图上的标记位置不同,传参是通过或操作( | )即可得到需要访问模式的位图所有标记位置。然后再打开或操作文件时就会按照传入的访问模式进行。

文件权限mode

新创建文件的最终权限 = mode & ~umask

例如,以下代码以读写模式打开文件 example.txt,如果文件不存在则创建:

int fd = open("example.txt", O_RDWR | O_CREAT, 0666);

在此,0666 是文件的权限掩码,表示文件所有者、所属组和其他用户均具有读写权限。


hello.c 写文件

在 C 语言中,使用 open() 打开文件后,可以使用 write() 系统调用向文件写入数据。以下是一个示例:

#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd == -1) {// 错误处理return 1;}const char *text = "Hello, Linux!";ssize_t bytes_written = write(fd, text, strlen(text));if (bytes_written == -1) {// 错误处理close(fd);return 1;}close(fd);return 0;
}

fd中写入buf,一次最多count个。

在此示例中:

  • open() 以写入模式打开文件 example.txt,如果文件不存在则创建,权限为 0666
  • write() 将字符串 "Hello, Linux!" 写入文件。
  • close() 关闭文件描述符,释放资源。

每次写入字符串不用留'\0'的位置,文件本身可以看做数组,如果中间存在'\0',则在读取文件时会造成错误。

当向文件内写入内容时,可以进行文本写入和二进制写入,两者的区别写入是语言层面的概念,系统不会关心类型,只要写入内容就会直接写入。

hello.c 读文件

读取文件的过程与写入类似,使用 read() 系统调用从文件中读取数据。示例如下:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("example.txt", O_RDONLY);if (fd == -1) {// 错误处理return 1;}char buffer[128];ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);if (bytes_read == -1) {// 错误处理close(fd);return 1;}buffer[bytes_read] = '\0'; // 确保字符串以 null 结尾printf("File content: %s\n", buffer);close(fd);return 0;
}

fd中读取,拷贝到buf中,最多读取countbytes(sizeof(buf) - 1( - 1是为了在buf的末尾存贮'\0'))。

在此示例中:

  • open() 以只读模式打开文件 example.txt
  • read() 从文件中读取数据到缓冲区 buffer
  • close() 关闭文件描述符。

open 函数返回值

区分两个概念:**系统调用****库函数**

  • fopen``fclose``fread``fwrite等都是C标准库中的函数,称之为库函数(libc)
  • open``close``read``write``lseek等属于系统提供的接口,称之为系统调用接口

通过上图可以理解库函数和系统调用之间的关系。可以认为f*系列的函数是对系统调用的封装,方便二次开发。


open() 函数的返回值是一个文件描述符(fd),用于标识打开的文件。成功时返回非负整数,失败时返回 -1,并设置 errno 以指示错误类型。常见的错误包括:

  • EACCES:权限不足。
  • ENOENT:文件不存在。
  • EINVAL:无效的标志位。

例如:

int fd = open("example.txt", O_RDONLY);
if (fd == -1) {perror("Error opening file");return 1;
}

文件描述符 fd

文件描述符(fd)是一个非负整数,用于标识进程打开的文件。标准输入、标准输出和标准错误分别对应文件描述符 0、1 和 2。文件描述符的分配规则如下:

  • 默认情况下,标准输入、标准输出和标准错误分别占用 0、1 和 2。
  • 通过 open() 打开的文件从 3 开始分配。

所以当我们查看在程序中打开的文件的fd时发现都是3之后的,就是因为在程序运行前就有自动升层的代码在开头打开了三个标准流文件,已经占据了0,1,2。

0 & 1 & 2

  • 0:标准输入(stdin),通常对应键盘输入。
  • 1:标准输出(stdout),通常对应屏幕输出。
  • 2:标准错误(stderr),用于输出错误信息。

通过6可知

通过6中关于FILE的讲解,当向open等函数返回值fd实际上就是进程内管理文件的数组的下标。所以当传入close等函数调用时就会通过下标来找寻这个文件,然后进行文件操作。

而对于库函数来说,返回值为FILE,作为将fd包装好的结构体,在函数内部使用系统调用的时候会自行进行处理。

FILE

FILE是什么呢?

在 C 语言标准库中,FILE 是一个用于描述文件的结构体,通常由 stdio.h 提供。它提供了一种便捷的接口,让我们可以操作文件而无需直接涉及底层的文件描述符。

FILE 结构体的内部实现

FILE 结构体并不是操作系统原生的,而是由 C 标准库(如 GNU C 库)定义的,它封装了文件的元数据,并提供了缓冲机制以提高 I/O 操作的效率。虽然不同的系统和编译器可能有不同的实现,以下是 FILE 结构体的一种典型实现:

struct _iobuf {char *_ptr;       // 指向缓冲区的指针int _cnt;         // 缓冲区的剩余字节数char *_base;      // 缓冲区的起始位置int _flag;        // 文件状态标志(如是否可读、是否可写)int _file;        // 文件描述符int _charbuf;     // 读缓存区的状态int _bufsiz;      // 缓冲区大小char *_tmpfname;  // 临时文件名
};
typedef struct _iobuf FILE;

重要字段解释:

  • _ptr:指向当前缓冲区位置的指针,文件数据会存储在这里。
  • _cnt:缓冲区中剩余的可用空间字节数。
  • _base:缓冲区的起始位置。
  • _flag:存储文件的状态标志,如文件是否处于读写模式等。
  • _file:该文件对应的系统级文件描述符,这是最直接的文件标识。
  • _bufsiz:缓冲区的大小。
  • _tmpfname:如果文件是临时的,存储其文件名。

FILE 结构体内部使用缓冲机制,这使得每次文件 I/O 操作时,程序并不直接与磁盘交互,而是将数据存入内存中的缓冲区,等缓冲区满时才将数据批量写入磁盘,从而提高 I/O 性能。

缓冲机制具体本文不做解释,之后文章会讲解。


task_structfile_struct

Linux 中的进程是由 task_struct 结构体来描述的。每个进程的 task_struct 中都包含一个 *file指向一个file_struct,这个结构体管理着该进程打开的文件。

task_struct 和文件操作的联系

task_struct 结构体代表一个进程。每个进程有自己的文件描述符表,文件描述符表由一个 file_struct 来表示。file_struct 存储了进程打开的所有文件的描述符、文件指针等信息。

struct task_struct {...struct files_struct *files;  // 文件描述符表...
};
files_struct 结构体

files_struct 是与 task_struct 相关联的结构体,存储了该进程的文件描述符表(fd_table[])。它提供了一个对文件描述符的索引和文件操作的抽象管理。每个进程的 files_struct 都有一个 fd_table[] 数组,这个数组的索引即为文件描述符(fd)。

struct files_struct {atomic_t count;               // 引用计数,表示该文件描述符表被多少个进程共享struct fdtable *fdt;          // 文件描述符表(fd_table[])spinlock_t file_lock;         // 保护文件描述符表的锁
};
fd_table[] 数组与 file_struct

fd_table[] 是一个数组,可以被看做文件描述符表,每个元素对应一个 file 结构体,表示一个文件。文件描述符(fd)就是 fd_table[] 数组的索引值。例如,文件描述符 0 对应标准输入(stdin),文件描述符 1 对应标准输出(stdout),文件描述符 2 对应标准错误(stderr)。

struct fdtable {unsigned int max_fds;         // 最大文件描述符数struct file **fd;             // 文件描述符数组,fd[i] 为进程打开的文件
};
  • fd[i] 表示索引为 i 的文件描述符指向的文件。
  • max_fds 表示文件描述符表的最大文件描述符数。
  • 不同的fd可以打开同一个文件,引用计数来维护,形成1 : n。
file 结构体

在 Linux 中,file 结构体表示一个打开的文件。它不仅包含了文件的数据指针和操作,还包含了与文件操作相关的状态信息。file 结构体的关键部分包括:

struct file
{属性mode读写位置读写选项缓冲区操作方法struct file *next; // 指向下一个fd的file结构体
}
  • f_op:文件操作结构体,包含了对文件的操作方法(如读取、写入、关闭等)。
  • f_pos:文件的当前偏移量,表示文件指针的位置。
  • f_mode:文件的访问模式(如只读、只写、读写)。
  • f_count:引用计数,表示有多少进程引用了这个文件,所以真正的文件关闭指的是引用计数为0的时候
  • 文件属性存储于结构体中,文件的内容存在缓冲区中。

文件操作的实质

从文件描述符到内核实现,文件操作的核心机制依赖于 fd_array[]file_struct

文件描述符的使用流程

每当一个进程打开文件时,内核会为文件分配一个文件描述符(fd)。这个文件描述符将作为 fd_array[] 数组的索引,指向一个 file 结构体。具体的流程如下:

  1. 文件打开:进程通过 open() 系统调用请求打开一个磁盘中的文件文件。内核会分配一个新的文件描述符(fd),并在 fd_table[] 中为该进程创建一个指向该文件的 file 结构体,属性存于结构体,内容存于结构体指向的缓冲区中。

冯诺依曼体系中,CPU不直接与硬件交互,所以需要通过内存来交互,缓冲区在内存中形成。对文件内容做任何操作,都必须先把文件加载到内核对应的文件缓冲区内,从磁盘到内存的拷贝。

  1. 文件读写:通过 read()write() 系统调用,进程会通过文件描述符访问 file 结构体中的数据,并对文件进行操作。read()本质就是内核到用户空间的拷贝函数。
  2. 文件关闭:当文件操作完成时,进程通过 close() 系统调用关闭文件。内核会减少文件描述符表中 file 结构体的引用计数,若引用计数为 0,则释放该文件描述符的资源。
通过文件描述符与 file 结构体的映射

文件描述符实际上是一个索引,它将用户空间的文件 I/O 操作映射到内核空间的 file 结构体。进程每次对文件进行读写操作时,都会通过文件描述符查找对应的 file 结构体,然后通过 file 中的操作指针(f_op)调用具体的文件操作函数,如 read(), write()flush()

文件操作的效率
  • 缓冲机制:Linux 内核使用缓冲区来提升文件 I/O 的效率。文件数据首先被写入内核缓冲区,只有缓冲区满了或程序显式调用 flush 操作时,数据才会写入磁盘。这样可以减少磁盘 I/O 的频率。
  • 文件操作锁:内核使用锁来同步文件操作,确保多个进程对同一文件的访问不会引发冲突。

结论

通过深入分析 FILE 结构体、task_struct 中的 file_struct 以及 fd_array[] 数组的关系,我们能够更清晰地理解 Linux 系统中文件操作的底层机制。文件描述符作为用户空间与内核空间的桥梁,file 结构体封装了对文件的访问接口,而内核通过文件描述符表、缓冲区机制和文件操作锁等技术,保证了高效且可靠的文件 I/O 操作。

编程语言的可移植性

编程语言的可移植性指的是程序能否在不同的平台或操作系统上顺利运行。语言的设计、标准库的实现以及对底层硬件的抽象都直接影响着程序的可移植性。

C 语言的可移植性

C 语言作为一种接近硬件的低级编程语言,直接与操作系统的底层交互。由于各个操作系统有不同的系统调用,C 语言的标准库为不同平台提供了相对一致的接口,使得 C 语言具备一定的可移植性。

不过,C 语言标准库的实现也可能因操作系统而异。比如,Windows 和 Linux 都有 C 语言的实现,但它们的文件 I/O 操作部分会有所不同,Windows 可能使用 CreateFile(),而 Linux 使用 open()。为了增强 C 语言的可移植性,开发者常常通过条件编译来区分不同操作系统下的实现。

例如,在 Windows 和 Linux 上都需要实现文件操作的代码:

#ifdef _WIN32
#include <windows.h>
HANDLE hFile = CreateFile("log.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
#else
#include <fcntl.h>
#include <unistd.h>
int fd = open("log.txt", O_CREAT | O_WRONLY | O_APPEND, 0666);
#endif

通过使用预处理指令 #ifdef#endif,程序可以根据不同操作系统选择不同的文件打开方式,从而增加跨平台的可移植性。

语言的可移植性?

除了 C 语言,其他高级编程语言(如 C++、Java、Python、Go、PHP)也通过各自的标准库和虚拟机来增强跨平台的可移植性。

  • C++:C++ 通过标准库(如 STL)提供了一套跨平台的接口,使得程序能在不同操作系统上编译和运行。然而,当涉及到直接与操作系统底层交互时,C++ 仍然需要依赖平台特定的系统调用和 API。
  • Java:Java 提供了 Java 虚拟机(JVM),使得 Java 程序可以在不同的操作系统上运行。JVM 会屏蔽底层系统的差异,使得 Java 代码具有良好的可移植性。Java 的字节码可以在任何实现了 JVM 的操作系统上运行。
  • Python:Python 通过封装了平台特定的调用接口,提供了跨平台的标准库,如 ossys 等。Python 程序员通常不需要关心底层操作系统的细节,Python 会处理这些差异。
  • Go:Go 语言内置对多平台的支持,编译器可以直接生成不同操作系统和架构的二进制文件,从而确保 Go 程序具有较高的可移植性。
  • PHP:PHP 是一种主要用于 Web 开发的语言,它通过 Web 服务器(如 Apache、Nginx)和平台无关的接口(如数据库驱动)使得 PHP 程序具有一定的可移植性。

所以语言的移植性可以总结为:语言在底层库中的使用系统调用的函数针对不同的系统会将系统调用部分更改,更换为不同操作系统的系统调用(条件编译来解决)。

如此在上层使用语言的时候不会感受到差异,因为只是使用语言的语法,底层库的差异在语言层面进行屏蔽,增加了语言的可移植性。

语言增加可移植性让更多人愿意去使用,增加市场占有率。

不可移植性的原因?

  1. 操作系统依赖:

不同的操作系统有不同的API和系统调用。例如,Linux和windows的文件操作、内存管理、线程处理等API不同。如果现在有一个程序,在编写的时候直接调用了某个操作系统特有的API,它在其他操作系统上就无法工作。必须将调用特有API更换为要在上面执行的操作系统的API才可以正常运行。

  1. 硬件依赖:

不同平台使用的编译器可能会有不同的行为,或者某些编辑器不支持某些特性。例如,C++中某些编译器特性只在特定的编译器中有效,导致代码在其他平台或编辑器中无法运行。

重定向

文件描述符的分配规则

当进程打开文件时,操作系统会分配一个最小的未使用文件描述符。例如:

int fd = open("example.txt", O_RDONLY);

如果文件描述符 3 未被占用,则 fd 将被赋值为 3。

重定向

重定向的核心原理在于操作文件描述符。文件描述符在file_struct中的数组中存放管理,通过改变文件描述符的指向,我们可以将输入或输出流重定向到文件、设备或其他流。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h> // 包含close函数的声明int main() {// 关闭标准输出文件描述符1close(1);// 打开(或创建)一个名为"myfile"的文件,以只写方式打开// 如果文件不存在则创建,权限设置为644int fd = open("myfile", O_WRONLY | O_CREAT, 00644);if (fd < 0) {// 如果打开文件失败,输出错误信息并返回1perror("open");return 1;}// 输出文件描述符printf("fd: %d\n", fd);// 刷新标准输出缓冲区,确保输出立即显示fflush(stdout);// 关闭文件描述符close(fd);// 程序正常退出exit(0);
}

已知文件描述符的分配规则和重定向的原理,那么通过以上代码理解。先关闭fd = 1的文件,也就是标准输出流文件。此时再打开文件时就会按照文件描述符的分配规则,将新打开的文件描述符设置为按照顺序最小的下标,也就是刚关闭fd = 1。然后当使用printf进行打印的时候,该函数默认的拷贝到的文件fd1,本来是向显示屏进行打印,实际上因为新文件的占用,将内容拷贝进行新文件中。

这就是重定向,数组的下标不变,更改文件描述符的指针指向。

使用 dup2() 系统调用

在 Linux 中,dup2() 系统调用用于复制一个文件描述符,并将其指向另一个指定的文件描述符。这对于实现输入输出的重定向非常有用。

函数原型:

int dup2(int oldfd, int newfd);
  • oldfd:现有的文件描述符。
  • newfd:目标文件描述符。

功能:

  • oldfd 指向的文件复制到 newfd
  • 如果 newfd 已经打开,则先关闭它。
  • 返回新的文件描述符 newfd,如果出错则返回 -1

示例代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {// 打开文件,获取文件描述符int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd == -1) {perror("打开文件失败");return 1;}// 将标准输出重定向到文件if (dup2(fd, STDOUT_FILENO) == -1) {perror("重定向标准输出失败");close(fd);return 1;}// 关闭原始文件描述符close(fd);// 现在 printf 的输出将写入 output.txtprintf("这行文本将被写入到 output.txt 文件中。\n");return 0;
}

在上述示例中:

  • 我们首先使用 open() 打开 output.txt 文件,并获取文件描述符 fd
  • 然后,使用 dup2() 将标准输出(STDOUT_FILENO)重定向到 output.txt 文件。
  • 关闭原始的文件描述符 fd
  • 之后,所有通过 printf() 输出的内容都会写入 output.txt 文件,而不是显示器。

在 minishell 中添加重定向功能

#include <iostream>
#include <ctype.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <unordered_map>
#include <sys/stat.h>
#include <fcntl.h>#define COMMAND_SIZE 1024      // 命令行最大长度
#define FORMAT "[%s@%s %s]# " // 提示符格式// ================== 全局数据结构声明 ==================
// 1. 命令行参数表
#define MAXARGC 128
char *g_argv[MAXARGC]; // 存储解析后的命令行参数
int g_argc = 0;        // 参数个数// 2. 环境变量表
#define MAX_ENVS 100
char *g_env[MAX_ENVS]; // 存储环境变量
int g_envs = 0;        // 环境变量数量// 3. 别名映射表(当前代码未完整实现)
std::unordered_map<std::string, std::string> alias_list;// 4. 重定向相关配置
#define NONE_REDIR 0    // 无重定向
#define INPUT_REDIR 1   // 输入重定向 <
#define OUTPUT_REDIR 2  // 输出重定向 >
#define APPEND_REDIR 3 // 追加重定向 >>int redir = NONE_REDIR;      // 记录当前重定向类型
std::string filename;        // 重定向文件名// ================== 辅助函数声明 ==================
// [省略部分环境获取函数...]// ================== 环境初始化 ==================
void InitEnv() {extern char **environ;// 从父进程复制环境变量到g_env数组for(int i = 0; environ[i]; i++) {g_env[i] = strdup(environ[i]); // 使用strdup复制字符串g_envs++;}// 设置新环境变量(示例)g_env[g_envs++] = strdup("HAHA=for_test");g_env[g_envs] = NULL;// 更新进程环境变量for(int i = 0; g_env[i]; i++) {putenv(g_env[i]);}environ = g_env; // 替换全局environ指针
}// ================== 重定向处理核心函数 ==================
void TrimSpace(char cmd[], int &end) {// 跳过连续空白字符while(isspace(cmd[end])) end++;
}void RedirCheck(char cmd[]) {// 开始前先将文件操作的信息初始化redir = NONE_REDIR;filename.clear();int start = 0;int end = strlen(cmd)-1;// 从命令末尾向前扫描寻找重定向符号while(end > start) {if(cmd[end] == '<') { // 输入重定向cmd[end] = '\0';  // 截断命令字符串end++;TrimSpace(cmd, end); // 跳过空格redir = INPUT_REDIR;filename = cmd + end;break;}else if(cmd[end] == '>') {// 判断是>>还是>if(end > 0 && cmd[end-1] == '>') { // 追加重定向cmd[end-1] = '\0'; // 截断命令字符串end++; // 移动到>后的位置redir = APPEND_REDIR;} else { // 普通输出重定向cmd[end] = '\0';end++;redir = OUTPUT_REDIR;}// 这时end在最后的运算符后面,然后用TrimSpace向后查找文件开头字母TrimSpace(cmd, end);filename = cmd + end; // end为文件名开头字母位置,直接cmd定位到文件名部分break;}else {end--; // 继续向前扫描}}
}// ================== 命令执行 ==================
int Execute() {pid_t id = fork();if(id == 0) { // 子进程int fd = -1;switch(redir) {case INPUT_REDIR:fd = open(filename.c_str(), O_RDONLY);dup2(fd, STDIN_FILENO); // 重定向标准输入break;case OUTPUT_REDIR:fd = open(filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0666);dup2(fd, STDOUT_FILENO); // 重定向标准输出break;case APPEND_REDIR:fd = open(filename.c_str(), O_CREAT|O_WRONLY|O_APPEND, 0666);dup2(fd, STDOUT_FILENO);break;default: // 无重定向不做处理break;}if(fd != -1) close(fd); // 关闭不再需要的文件描述符execvp(g_argv[0], g_argv); // 执行程序exit(EXIT_FAILURE); // exec失败时退出}// 父进程等待子进程int status = 0;waitpid(id, &status, 0);lastcode = WEXITSTATUS(status); // 记录退出状态return 0;
}// ================== 主循环 ==================
int main() {InitEnv(); // 初始化环境变量while(true) {PrintCommandPrompt(); // 打印提示符char commandline[COMMAND_SIZE];if(!GetCommandLine(commandline, sizeof(commandline))) continue;RedirCheck(commandline); // 重定向解析if(!CommandParse(commandline)) continue; // 命令解析if(CheckAndExecBuiltin()) continue; // 内建命令Execute(); // 执行外部命令}return 0;
}

总结

通过深入探讨文件描述符(fd)的使用,以及如何在 C 语言中实现文件的重定向功能,我们可以更好地理解 Linux 系统文件 I/O 的工作原理。掌握这些概念和技术,对于编写高效、可靠的系统级程序具有重要意义。

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

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

相关文章

滚动弹幕案例

滚动弹幕案例 一、需求 1.页面上漂浮字体大小不一、颜色不一&#xff0c;从左向右滚动的弹幕&#xff1b; 2.底部中间有一个发送功能&#xff0c;可以发送新的弹幕&#xff1b; 3.底部的发送部分可以向下收起和弹出。 二、html <div class"container"><…

【wiki知识库】08.添加用户登录功能--后端SpringBoot部分

目录 一、今日目标? 二、SpringBoot后端实现 2.1 新增UserLoginParam 2.2 修改UserController 2.3 UserServiceImpl代码 2.4 创建用户上下文工具类 2.5?通过token校验用户&#xff08;重要&#xff09; 2.6 创建WebMvcConfig 2.7 用户权限校验拦截器 一、今日目标 上…

在nodejs中使用RabbitMQ(六)sharding消息分片

RabbitMQ 的分片插件&#xff08;rabbitmq_sharding&#xff09;允许将消息分布到多个队列中&#xff0c;这在消息量很大或处理速度要求高的情况下非常有用。分片功能通过将消息拆分到多个队列中来平衡负载&#xff0c;从而提升消息处理的吞吐量和可靠性。它能够在多个队列之间…

【D2】神经网络初步学习

总结&#xff1a;学习了 PyTorch 中的基本概念和常用功能&#xff0c;张量&#xff08;Tensor&#xff09;的操作、自动微分&#xff08;Autograd&#xff09;、正向传播、反向传播。通过了解认识LeNet 模型&#xff0c;定义神经网络类&#xff0c;熟悉卷积神经网络的基本结构和…

DeepSeek处理自有业务的案例:让AI给你写一份小众编辑器(EverEdit)的语法着色文件

1 DeepSeek处理自有业务的案例&#xff1a;让AI给你写一份小众编辑器(EverEdit)的语法着色文件 1.1 背景 AI能力再强&#xff0c;如果不能在企业的自有业务上产生助益&#xff0c;那基本也是一无是处。将企业的自有业务上传到线上训练&#xff0c;那是脑子进水的做法&#xff…

深入浅出Java反射:掌握动态编程的艺术

小程一言反射何为反射反射核心类反射的基本使用获取Class对象创建对象调用方法访问字段 示例程序应用场景优缺点分析优点缺点 注意 再深入一些反射与泛型反射与注解反射与动态代理反射与类加载器 结语 小程一言 本专栏是对Java知识点的总结。在学习Java的过程中&#xff0c;学习…

【算法与数据结构】并查集详解+题目

目录 一&#xff0c;什么是并查集 二&#xff0c;并查集的结构 三&#xff0c;并查集的代码实现 1&#xff0c;并查集的大致结构和初始化 2&#xff0c;find操作 3&#xff0c;Union操作 4&#xff0c;优化 小结&#xff1a; 四&#xff0c;并查集的应用场景 省份…

C语言简单练习题

文章目录 练习题一、计算n的阶乘bool类型 二、计算1!2!3!...10!三、计算数组arr中的元素个数二分法查找 四、动态打印字符Sleep()ms延时函数system("cls")清屏函数 五、模拟用户登录strcmp()函数 六、猜数字小游戏产生一个随机数randsrandRAND_MAX时间戳time() 示例 …

ShenNiusModularity项目源码学习(8:数据库操作)

ShenNiusModularity项目使用SqlSugar操作数据库。在ShenNius.Repository项目中定义了ServiceCollectionExtensions.AddSqlsugarSetup函数注册SqlSugar服务&#xff0c;并在ShenNius.Admin.API项目的ShenniusAdminApiModule.OnConfigureServices函数中调用&#xff0c;SqlSugar所…

MATLAB图像处理:图像特征概念及提取方法HOG、SIFT

图像特征是计算机视觉中用于描述图像内容的关键信息&#xff0c;其提取质量直接影响后续的目标检测、分类和匹配等任务性能。本文将系统解析 全局与局部特征的核心概念&#xff0c;深入讲解 HOG&#xff08;方向梯度直方图&#xff09;与SIFT&#xff08;尺度不变特征变换&…

小白win10安装并配置yt-dlp

需要yt-dlp和ffmpeg 注意存放路径最好都是全英文 win10安装并配置yt-dlp 一、下载1.下载yt-dlp2. fffmpeg下载 二、配置环境三、cmd操作四、yt-dlp下视频操作 一、下载 1.下载yt-dlp yt-dlp地址 找到win的压缩包点下载&#xff0c;并解压 2. fffmpeg下载 ffmpeg官方下载 …

【技术解析】MultiPatchFormer:多尺度时间序列预测的全新突破

今天给我大家带来一篇最新的时间序列预测论文——MultiPatchFormer。这篇论文提出了一种基于Transformer的创新模型&#xff0c;旨在解决时间序列预测中的关键挑战&#xff0c;特别是在处理多尺度时间依赖性和复杂通道间相关性时的难题。MultiPatchFormer通过引入一维卷积技术&…

145,【5】 buuctf web [GWCTF 2019]mypassword

进入靶场 修改了url后才到了注册页面 注测后再登录 查看源码 都点进去看看 有个反馈页面 再查看源码 又有收获 // 检查$feedback是否为数组 if (is_array($feedback)) {// 如果是数组&#xff0c;弹出提示框提示反馈不合法echo "<script>alert(反馈不合法);<…

晶闸管主要参数分析与损耗计算

1. 主要参数 断态正向可重复峰值电压 :是晶闸管在不损坏的情况下能够承受的正向最大阻断电压。断态正向不可重复峰值电压 :是晶闸管只有一次可以超过的正向最大阻断电压,一旦晶闸管超过此值就会损坏,一般情况下 反向可重复峰值电压 :是指晶闸管在不损坏的情况下能够承受的…

el-select 设置宽度 没效果

想实现下面的效果&#xff0c;一行两个&#xff0c;充满el-col12 然后设置了 width100%,当时一直没有效果 解决原因&#xff1a; el-form 添加了 inline 所以删除inline属性 即可

一款利器提升 StarRocks 表结构设计效率

CloudDM 个人版是一款数据库数据管理客户端工具&#xff0c;支持 StarRocks 可视化建表&#xff0c;创建表时可选择分桶、配置数据模型。目前版本持续更新&#xff0c;在修改 StarRocks 表结构方面进一步优化&#xff0c;大幅提升 StarRocks 表结构设计效率。当前 CloudDM 个人…

数量5 - 平面图形、立体几何

目录 一、平面几何问题1.三角形2.其他图形二、立体几何与特殊几何1.表面积2.体积3.等比放缩(简单)4.几何最值(简单)5.最短路径一、平面几何问题 平面图形: 立体图形: 1.三角形 特殊直角

CAS单点登录(第7版)7.授权

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 授权 概述 授权和访问管理 可以使用以下策略实施授权策略以保护 CAS 中的应用程序和依赖方。 服务访问策略 服务访问策略允许您定义授权和访问策略&#xff0c;以控制对向 CAS 注册的…

53倍性能提升!TiDB 全局索引如何优化分区表查询?

作者&#xff1a; Defined2014 原文来源&#xff1a; https://tidb.net/blog/7077577f 什么是 TiDB 全局索引 在 TiDB 中&#xff0c;全局索引是一种定义在分区表上的索引类型&#xff0c;它允许索引分区与表分区之间建立一对多的映射关系&#xff0c;即一个索引分区可以对…

I.MX6ull-I2C

一,I2C总线介绍 I2C(Inter-Integrated Circuit 集成电路)总线是Philips公司在八十年代初推出的一种串行、半双工的总 线&#xff0c;主要用于近距离、低速的芯片之间的通信&#xff1b;I2C总线有两根双向的信号线&#xff0c;一根数据线SDA用于收 发数据&#xff0c;一根时钟线…