13.基础IO(1)

文章目录

  • 13.基础IO(1)
    • 文件的基本概念:内容与属性
    • 文件的打开机制:fopen 和 open
    • 被打开的文件与磁盘文件的区别
    • 文件的内核数据结构
    • 文件与进程的交互方式
    • 标准输入/输出/错误与文件流
    • 系统调用与文件描述符
    • 文件打开模式(r/w/a/a+)与权限控制
    • C 语言与系统调用在文件管理中的应用
    • 权限控制与 `umask` 的影响
    • 位图与标志位参数传递的机制

文件的基本概念:内容与属性

在 Linux 中,文件是操作系统存储数据的基本单位,它包含两部分:内容(即数据本身)和属性(metadata)。属性包括文件名、类型、大小、所有者、权限、创建/修改时间等元信息。据讲稿与相关资料指出,任何文件都包含内容和属性,即使一个文件没有任何内容(空文件),它仍具有名称、权限等属性,并且这些属性也需要占用磁盘空间。例如,用 ls -l 可以看到空文件大小为 0,但目录中仍保留了它的 inode 信息和属性;这是因为文件的属性也记录在磁盘上。

文件的内容则存储在磁盘的数据块中,当文件被打开后才会被加载到内存供进程访问。根据冯诺依曼体系结构,CPU 只能直接访问内存而无法直接访问磁盘,因此要访问一个文件,必须先将文件加载到内存,这个过程即为“打开文件”。综上,文件 = 内容 + 属性,而文件的属性往往保存在 inode 等结构中。

【课外补充】在 Linux 文件系统中,每个文件在磁盘上用 inode(索引节点)来记录其元数据和数据块位置,包括权限、类型、大小、时间戳、硬链接数等信息。例如,ls -il 显示的第一列就是 inode 编号,通过 inode 可以获取文件的各种属性。

文件的打开机制:fopen 和 open

在编程中访问文件时,必须显式地打开文件。C 语言标准库提供 fopen 函数(位于 <stdio.h>)来打开文件,返回一个 FILE* 类型的文件指针供后续读写使用;而在系统调用层面,Linux 提供了 open 系统调用(位于 <fcntl.h>)来打开文件,返回一个非负整数的文件描述符(file descriptor)。两者的主要区别是:fopen 是库函数,会对调用参数进行封装并返回 FILE*open 是直接与内核交互的系统调用,需要传入文件路径、标志位 (flags) 和权限模式 (mode),返回一个 int 型文件描述符。

只有当程序执行到打开文件的语句时,文件才真正被加载到内存中。例如,在下面代码段中,只有当 fopenopen 运行时,文件才被打开:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {// 使用 fopen 打开文件,返回 FILE*FILE *fp = fopen("example.txt", "w");if (fp == NULL) {perror("fopen");return 1;}fputs("Hello, world!\n", fp);fclose(fp);// 使用 open 打开文件,返回文件描述符int fd = open("example2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd < 0) {perror("open");return 1;}write(fd, "Hello, world!\n", 14);close(fd);return 0;
}

在上例中,直到程序运行到 fopenopen 并执行成功时,文件才真正被打开并加载到内存中。执行 fopen 返回 FILE* 后,可以通过 fread/fwrite/fputs 等接口对文件内容进行读写;执行 open 返回的文件描述符可以与 readwritelseek 等系统调用配合使用。如果打开失败,fopen 返回 NULLopen 返回 -1,并设置相应的错误码。

被打开的文件与磁盘文件的区别

磁盘上的文件被打开的文件是两个不同的概念。磁盘上的文件是静态存在的,包含文件内容和元数据(属性),但尚未加载到内存。只有当进程调用 fopenopen 并成功时,文件才被打开,它的内容和属性才被加载到内存,并由内核为其分配数据结构以供访问。这种加载过程类似将文件从磁盘映射到内核空间,使得 CPU 可以直接操作它。

简言之:未打开的文件只能在磁盘上存在;被打开的文件则在内存中有对应结构体供进程访问。根据讲稿和资料的描述,当我们打开一个文件时,操作系统会把文件的内容和属性加载到内存中。在内存中的文件通常用文件对象(如 Linux 内核中的 struct file)来表示,该结构体包含文件的各种属性以及指向文件数据的指针。相比之下,磁盘上的文件只是存储在文件系统上的数据块和 inode 信息。

因此,在一个系统中存在大量磁盘文件,但只有当进程需要时才会打开其中的少数文件。例如,一个 Linux 系统可能有上万文件,但同时被打开的可能只有几百个。操作系统需要跟踪管理哪些文件已打开、对应哪个进程以及何时关闭,保障文件访问的正确性和资源回收。

文件的内核数据结构

在 Linux 内核中,每个被打开的文件都会对应内核级数据结构来表示其状态和属性。常见的结构有 struct file(表示已打开的文件实例)和 struct inode(表示磁盘上的文件元数据)。讲稿中提到,文件在内核中本质上也等于 内容 + 属性,即有对应的结构体来描述,包括文件大小、权限、读写位置等信息。我们可以把 struct file 理解为文件的“内核镜像”,它会保存文件当前位置(offset)、文件系统操作函数指针、引用计数等,当进程通过文件描述符读写文件时,实际上是通过这些结构体进行操作的。

操作系统如何管理被打开的文件呢?每个进程都有一个 task_struct,其中包含一个指向 struct files_struct 的指针。files_struct 中维护了一个文件描述符数组 fd_array,该数组的每个元素指向一个内核中的 struct file 结构。当进程调用 open 打开新文件时,内核会在这个数组中找到一个空闲的下标(例如 3、4、5 等)分配给该文件,并返回该下标作为文件描述符。可以说,系统层面访问文件的唯一途径就是文件描述符。例如,进程启动时默认占用 0、1、2 三个文件描述符(分别对应 stdinstdoutstderr),后续打开的第一个文件会获得描述符 3

此外,struct file 结构中还包含一个引用计数,用以记录有多少个文件描述符或进程引用该文件。这意味着同一个文件可以被多个描述符(甚至不同进程)共享读取或写入。文件操作(读/写/关闭)最终都会通过这些内核结构执行,内核维护的这种数据结构保证了对文件的并发访问和正确释放。

文件与进程的交互方式

在 Linux 中,进程是访问和操作文件的主体。只有进程才能调用 fopenopen 等接口来操作文件。讲稿强调,当程序中出现了 fopenopen 语句,并且进程实际执行到这一句时,文件才被打开。也就是说,即便源代码中有 fopen 调用,如果程序尚未运行或者未执行到该行,文件也不会被打开。执行完成后,进程会得到一个文件指针或文件描述符,通过它可以进行后续的读写操作,最后再调用 fcloseclose 关闭文件释放资源。

一个进程可以同时打开多个文件。实际上,每个进程启动时就自动打开了三个标准流(stdin,stdout,stderr),而用户程序可以根据需要继续打开其他文件。操作系统为每个进程维护独立的文件描述符表,确保各进程对文件的操作互不干扰。当进程结束或主动关闭文件时,内核会关闭对应的 struct file,更新引用计数,并回收内存和描述符。

总之,文件操作的发生总是伴随着一个进程:访问文件的始终是进程,而非静态的代码文本。进程运行时必须先打开文件,此时操作系统将文件加载到内存,并返回用于标识该文件的文件描述符或 FILE*。后续对文件内容的读写,都是通过该进程内的指针或描述符发起的。进程关闭文件后,文件可以从内存中卸载,相关资源被释放。

标准输入/输出/错误与文件流

每个进程默认启动时都会打开三个标准流,用于与外界(键盘、显示器等)进行交互:标准输入stdin,通常对应键盘,文件描述符 0)、标准输出stdout,通常对应显示器,文件描述符 1)和标准错误stderr,也对应显示器或终端,文件描述符 2)。在 C 语言中,这三个标准流都是 FILE* 类型指针,分别指向 stdin,stdout,stderr。例如,printf 默认向 stdout 写入,而 scanf 则从 stdin 读取。虽然键盘和显示器是硬件设备,但 C 标准库将它们抽象为文件流(通过底层的系统调用与操作系统交互),因此对它们的读写操作与普通文件类似。

标准流的具体对应关系如下:

  • stdin:标准输入(键盘),文件描述符 0。
  • stdout:标准输出(显示器或终端),文件描述符 1。
  • stderr:标准错误(显示器或终端),文件描述符 2。

例如,下面的代码会从标准输入读取一行,然后再通过标准输出打印出来:

#include <stdio.h>int main() {char buf[100];// 从标准输入(stdin)读一行if (fgets(buf, sizeof(buf), stdin)) {// 将读取到的内容打印到标准输出(stdout)printf("你输入了: %s", buf);}return 0;
}

可以看到,我们使用 stdinstdout 完成了输入输出。由于它们都是 FILE*,底层实际上对应文件描述符 0 和 1。总之,标准输入/输出/错误在实现上也是文件,只是内核默认为每个新进程打开了这三个文件流。

系统调用与文件描述符

在 Linux 中进行文件操作的系统调用有 openclosereadwrite 等。文件描述符是内核为进程打开文件后分配的整数句柄,用于索引进程的文件描述符表。调用 open 时,如果成功,内核返回一个非负整数(通常从 3 开始,因为 0、1、2 已被标准流占用)。这个整数就是文件描述符。例如:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd < 0) {perror("open失败");return 1;}printf("打开文件得到文件描述符: %d\n", fd);// 可以使用 write(fd, ..., ...) 和 close(fd)close(fd);return 0;
}

上例中,如果 log.txt 打开成功,将打印出类似 3 这样的文件描述符值。打开失败时 fd-1,并通过 perror 输出错误信息。我们注意到文件描述符是一个索引,它指向内核中某个 struct file 结构。只有通过文件描述符,系统调用才能找到对应的文件资源。

此外,所有针对文件的系统调用(如 readwritelseekclose 等)都以文件描述符作为参数。内核通过进程的 files_struct 中的 fd_array 找到对应的内核文件对象,然后执行操作。因此,系统层面上访问文件的唯一途径就是文件描述符。正因如此,FILE* 之类的用户态结构内部也保存了一个文件描述符(可通过 fp->_fileno 获取),以便通过系统调用完成实际的读写。

在这里插入图片描述

⽽现在知道,⽂件描述符就是从0开始的⼩整数。当我们打开⽂件时,操作系统在内存中要创建相应的数据结构来描述⽬标⽂件。于是就有了file结构体。表⽰⼀个已经打开的⽂件对象。⽽进程执⾏open系统调⽤,所以必须让进程和⽂件关联起来。每个进程都有⼀个指针*files, 指向⼀张表files_struct,该表最重要的部分就是包含⼀个指针数组,每个元素都是⼀个指向打开⽂件的指针!所以,本质上,⽂件描述符就是该数组的下标。所以,只要拿着⽂件描述符,就可以找到对应的⽂件。

在这里插入图片描述

文件打开模式(r/w/a/a+)与权限控制

在 C 标准库的 fopen 中,文件打开模式通过模式字符串指定,常用模式包括:

  • "r":以只读方式打开文件,文件必须存在;读操作从文件开头开始。
  • "r+":以读写方式打开文件,文件必须存在;操作位置在开头。
  • "w":以写方式打开文件,如果文件不存在则创建;如果文件存在则清空原内容,相当于截断文件再写入。
  • "w+":以读写方式打开,效果类似于 w
  • "a":以追加方式打开文件,如果文件不存在则创建;写入时总是追加到文件末尾。
  • "a+":以读写方式打开,写操作追加到末尾。

例如,上述代码示例中 fopen("log.txt", "w") 会创建新文件或清空已有文件,并将数据写入。如果改为 "a" 模式,则不会清空原文件,而是将内容追加到末尾。这些模式与 shell 中的重定向符号类似:> 对应清空写入,>> 对应追加写入。

对于系统调用 open,访问模式和标志通过参数 flags 指定。常见的标志包括:

  • 访问模式:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)
  • 创建模式:O_CREAT(如果文件不存在则创建)、O_EXCL(配合 O_CREAT 使用,如果文件已存在则打开失败)
  • 截断追加:O_TRUNC(如果文件存在则清空其内容)、O_APPEND(写操作追加到末尾)

这些标志是 位标志,可以通过按位或组合多个选项(位图方式)。每个宏对应一个二进制位,例如 O_CREAT = 0x40。我们可以写 O_WRONLY | O_CREAT 来同时设置只写和创建标志。例如:

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

上述调用试图以读写模式打开 data.txt,如果不存在则创建,并在打开时清空原有内容。权限参数 0666 指定新文件的初始权限(随后会受 umask 掩码的影响,详见下一节)。

需要注意的是,open 系统调用本身并不设置文件访问权限,它只是使用提供的参数和当前进程的 umask 决定文件的最终权限。如果我们只读打开已有文件(不需要创建),可以省略权限参数,只传两个参数即可。

C 语言与系统调用在文件管理中的应用

在 C 语言中,文件操作常用标准库函数,如 fopen/fclosefread/fwritefprintf/fscanf 等。这些函数在用户态提供了方便的接口,但它们底层最终都会调用相应的系统调用。简而言之:

  • C 标准库函数(例如 fopen, fclose, fread, fwrite)是一种对系统调用的封装,使用起来更方便,自动管理缓冲区。
  • 系统调用(例如 open, close, read, write)是内核提供的底层接口,功能更原始,需要程序员自己处理缓冲和错误。

讲稿总结道:

fopen, fclose, fwrite, fread —— C 库函数;
open, close, write, read —— 系统调用;
C 库函数就是系统调用的封装。

我们在前面的示例代码中就使用了 fopen/fputsopen/write 的组合。二者的使用基本相同,只是一个返回 FILE*,另一个返回 int fd。C 库函数在底层自动调用了相同功能的系统调用,并通常带有文件缓冲机制。

比如,可以用下面代码分别展示两种方法写文件:

// 使用 C 库函数 fwrite
#include <stdio.h>
int main() {FILE *fp = fopen("test.txt", "w");if (!fp) return 1;fprintf(fp, "Hello, libc!\n");fclose(fp);return 0;
}
// 使用系统调用 write
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {int fd = open("test_sys.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd < 0) return 1;const char *msg = "Hello, syscall!\n";write(fd, msg, strlen(msg));close(fd);return 0;
}

两个示例效果类似,但实现层次不同。第二个示例是直接与内核交互,第一种方式在内部会调用第二种方式并做缓冲。了解两者的差异有助于在需要精细控制时直接使用系统调用,而大部分应用开发可以继续使用更易用的 C 库函数。

权限控制与 umask 的影响

Linux 中每个文件都有访问权限设置,一般用三组 rwx 位表示属主、属组和其它用户的读写执行权限。对于新创建的文件,open 系统调用第三个参数指定了文件的初始权限(如 0666,即默认可读可写),但最终权限还会受进程的文件模式掩码umask)影响。操作系统会将给定的权限值与 umask 做按位与再取反,从而得出文件的实际权限。例如:如果进程的 umask022,新文件的默认权限 0666 会变成 0644(去掉了对“其它用户”的写权限)。

讲稿中演示了这一过程:在 open("log.txt", O_CREAT, 0666) 后发现文件权限并非 0666 而是根据掩码修正后的值。可以在程序中调用 umask(0) 来临时将掩码清零,这样之后创建文件就会严格使用指定的权限。要注意,umask 是进程级的属性,修改当前进程的 umask 不会影响其他进程。

例如:

# 进程默认 umask 为 022,创建文件时权限=0666&~022=0644
$ touch file1.txt
$ ls -l file1.txt
-rw-r--r-- # 改变 umask 后再创建
$ umask 000
$ touch file2.txt
$ ls -l file2.txt
-rw-rw-rw-  # 此时文件权限就是0666 

在上述示例中,可以看到 umask 影响了新文件的权限。此外,open 的权限参数只有在指定 O_CREAT 时才有效,如果只读打开现有文件就不需提供权限参数。

位图与标志位参数传递的机制

在许多系统调用(如 openmmapsocket 等)中,为了同时传递多个选项,Linux 通常采用**位掩码(bitmap)**的方式。即将整型参数的每一位作为独立的开关。这样我们可以用按位或(|)来组合多个选项,仅需一个参数即可表示多个布尔配置。

open 为例,其 flags 参数就是一个 32 位的位图,每个标志宏(如 O_RDONLY=0x0000O_WRONLY=0x0001O_CREAT=0x0040 等)在这个整数中只有一个位为 1。多个标志可以组合,比如 O_WRONLY | O_CREAT | O_TRUNC。下面这个示例片段演示了位掩码的原理(简化示意):

#define ONE   (1<<0)
#define TWO   (1<<1)
#define THREE (1<<2)void Test(int flags) {if (flags & ONE)   printf("ONE\n");if (flags & TWO)   printf("TWO\n");if (flags & THREE) printf("THREE\n");
}int main() {Test(ONE | THREE);  // 输出 ONE 和 THREEreturn 0;
}

open("file", O_WRONLY | O_CREAT) 的调用中,flags 参数的值就是上述位或的结果。内核读取这个整数后,通过与操作检查各个位是否被设置,从而知道用户希望启用哪些功能。这种位图传参机制非常灵活,能够支持在单个参数中传递多个选项,也避免了传递过多单独参数。对开发者来说,只需记住各个宏代表的含义,并使用按位或即可组合使用。

【课外补充】此处介绍的位图传参方法在很多系统调用和库接口中都很常见,不限于文件操作。例如 openfcntlmmap、网络编程的 socket 等调用都使用类似方式传递标志位。

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

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

相关文章

Go调度器的抢占机制:从协作式到异步抢占的演进之路|Go语言进阶(7)

想象一下这样的场景&#xff1a;你在餐厅排队等位&#xff0c;前面有个人点了餐却一直霸占着座位玩手机&#xff0c;后面的人只能干等着。这就是Go早期版本面临的问题——一个goroutine如果不主动让出CPU&#xff0c;其他goroutine就只能饿着。 今天我们来聊聊Go调度器是如何解…

开源模型应用落地-让AI更懂你的每一次交互-Mem0集成Qdrant、Neo4j与Streamlit的创新实践(四)

一、前言 在人工智能迅速发展的今天,如何让AI系统更懂“你”?答案或许藏在个性化的记忆管理之中。Mem0作为一个开源的记忆管理系统,正致力于为AI赋予长期记忆与个性化服务能力。通过结合高性能向量数据库Qdrant、图数据库Neo4j的强大关系分析能力以及Streamlit的高效可视化交…

基于微信小程序的校园二手交易平台、微信小程序校园二手商城源代码+数据库+使用说明,layui+微信小程序+Spring Boot

school-market 介绍 基于微信小程序的校园二手交易平台 功能结构图 软件架构 系统分为三个端&#xff0c;分别是客户端、管理端、服务端&#xff1b; 客户端&#xff1a;使用原生微信小程序实现 管理端&#xff1a;使用Layui实现 服务端&#xff1a;使用Java SpringBoot…

IDEA与Gradle构建冲突,导致java重复类的解决方案

项目构建总是报错&#xff1a;错误提示1&#xff1a;java:重复类或错误提示2&#xff1a;Internal error in the mapping processor: java.lang.RuntimeException: javax.annotation.processing.FilerException: Attempt to recreate a file排查发现build/generated/sources/an…

如何调节笔记本电脑亮度?其实有很多种方式可以调整亮度

长时间面对屏幕工作、学习或娱乐&#xff0c;很多人会感到眼睛干涩、疲劳&#xff0c;甚至出现视力下降等问题。其实&#xff0c;这些问题的背后&#xff0c;往往隐藏着一个看似简单却极易被忽视的设置—屏幕亮度。 合适的屏幕亮度不仅能提升视觉体验&#xff0c;还能有效缓解…

国际数字影像产业园创作空间升级 打造更优质营商环境

国际数字影像产业园创作空间升级后表现显著&#xff0c;聚焦设施数字化与用户体验优化。整体提升了创意生态系统的竞争力&#xff0c;有效吸引全球企业。 升级核心改进 基础设施现代化&#xff1a;引入智能硬件如5G网络和云渲染设备&#xff0c;支持高清影像处理&#xff0c;…

浅谈 webshell 构造之如何获取恶意函数

前言这篇文章主要是总结一下自己学习过的如何获取恶意函数的篇章&#xff0c;重点是在如何获取恶意函数get_defined_functions(PHP 4 > 4.0.4, PHP 5, PHP 7, PHP 8)get_defined_functions — 返回所有已定义函数的数组我们主要是可以通过这个获取危险的函数比如比如当然还有…

Python 单例模式与魔法方法:深度解析与实践应用

在 Python 编程领域,设计模式解决常见问题的通用方案,而魔法方法则是 Python 语言赋予类强大功能的特殊接口。单例模式和魔法方法看似独立,实则紧密关联,魔法方法常被用于实现单例模式。深入理解并熟练运用它们,能够帮助开发者编写出结构清晰、高效且具有高复用性的代码。…

pybind11 导出 C++ map 在 Python 层 get 访问慢的优化方案

pybind11 导出 C map 在 Python 层 get 访问慢的优化方案 问题描述 通过 pybind11 导出 C 的 std::map 或 std::unordered_map&#xff0c;在 Python 代码中频繁使用 get 方法访问 value 时&#xff0c;性能非常低下。其主要原因是&#xff1a; pybind11 的 map 绑定会导致每次…

RTC实时时钟DS1339U-33国产替代FRTC1339M

FRTC1339M是一款实时时钟&#xff08;RTC&#xff09;芯片&#xff0c;由NYFEA徕飞公司制造。 FRTC13399M串行实时时钟是一种低功耗的时钟日期设备&#xff0c;具有两个可编程的每日时间警报和一个可编程的方波输出。通过2线双向总线进行串行地址和数据传输。时钟/日期提供秒、…

网络常用端口号归纳

ICMP端口号&#xff1a;1IGMP端口号&#xff1a;2TCP端口号&#xff1a;6UDP端口号&#xff1a;17FTP端口号&#xff1a;20(控制信息传输)、21&#xff08;数据传输&#xff09;SSH端口号&#xff1a;22Telnet端口号&#xff1a;23SMTP端口号&#xff1a;25IPV6端口号&#xff…

Agent learn

1.人物设定&#xff1a; 1.1塑造智能体的思维能力与问题拆解与拆解分析能力 1.2个性化&#xff1a;输出预期输出示例&#xff08;设定智能体的-》性格&#xff0c;语言风格&#xff09; 1.3插件&#xff0c;调用工具 1.4可设定结构化表达 1.5调优 1.6常见问题&#xff1a; …

五层协议介绍

层次核心功能典型协议/设备应用层为用户应用程序提供网络服务接口&#xff08;如文件传输、电子邮件、网页浏览&#xff09;HTTP、FTP、SMTP、DNS、SSH传输层提供端到端的可靠或不可靠数据传输&#xff0c;处理流量控制和差错恢复TCP&#xff08;可靠&#xff09;、UDP&#xf…

gin框架 中间件 是在判断路由存在前执行还是存在后执行的研究

最近有个需求&#xff0c;就是发现我们的验签路由中间件会在判断路由是否存在前执行。我们期望是gin框架先自己判断路由中间件是否存在&#xff0c;存在了再走后面的中间件&#xff0c;不存在直接返回404.这样能节省一定的资源。 研究了一下gin框架的源码&#xff0c; 先说一下…

AGV 无人叉车关键技术问题解析:精准定位算法 / 安全避障逻辑 / 系统对接协议全方案

AGV无人叉车作为智能物流的核心装备&#xff0c;在落地时常面临定位漂移、系统兼容性差、避障失灵等痛点。本文深度解析5大高频问题成因与解决方案&#xff0c;助企业规避运营风险&#xff0c;提升效率。 一、定位导航问题&#xff1a;行驶路径偏移怎么办&#xff1f; 1.典型…

AI Agent意图识别

意图识别&#xff1a;多维度拆解 意图识别是人机对话系统&#xff08;Conversational AI&#xff09;的“大脑皮层”&#xff0c;负责理解用户言语背后的真实目的。它将用户的自然语言输入映射到一个预定义的意图类别上。可以说&#xff0c;意图识别的准确性&#xff0c;直接决…

.net 8 项目 一天快速入门

这里有一个解决方案 这里有一个接口类的项目 这会呢如果还想在建一个项目 我们在解决方案这里右键,添加,新建项目 点击 我现在要建立一个类库,所以就搜一下类库,这里的第一个就是我们需要创建的类库 起个名字,计算类 进来了 可以看到这里有多了一个项目,但是他们…

语音大模型速览(一)F5-TTS

F5-TTS: A Fairytaler that Fakes Fluent and Faithful Speech with Flow Matching 论文链接&#xff1a;https://arxiv.org/pdf/2410.06885代码链接&#xff1a;https://SWivid.github.io/F5-TTS/ 一段话总结 本文提出了 F5-TTS&#xff0c;一种基于流匹配和扩散 Transform…

Codeforces 2021 C Those Who Are With Us

[Problem Discription]\color{blue}{\texttt{[Problem Discription]}}[Problem Discription] 给定一个 nmn \times mnm 的表格 ai,ja_{i,j}ai,j​&#xff0c;你可以恰好进行一次如下操作&#xff1a; 选择一个格点 (r,c)(r,c)(r,c)。对于所有满足 iririr 或者 jcjcjc 的格点 (…

chrome插件合集

最近一段时间呢(不到一年)&#xff0c;实现了大概二十几个chrome插件。很多人不知道的是&#xff0c;其实开发插件很解压&#xff0c;就好像是我喜欢沿着公园的小路散步一样&#xff0c;每开发一个插件带给我的成就感和快乐都是独特的。我依然记得自己开发出第1个插件时的快乐&…