Linux系统:Ext系列文件系统(软件篇)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

    • @[TOC](文章目录)
  • 一,ext2文件系统
    • 1-1 宏观认识
    • 1-2 Block Group
    • 1-3 块组内部构成
      • 1-3-1 超级块(Super Block)
      • 1-3-2 块组描述符表GDT(Group Descriptor Table)
      • 1-3-3 块位图(Block Bitmap)
      • 1-3-4 inode位图(Inode Bitmap)
      • 1-3-5 i节点表(Inode Table)
      • 1-3-6 Data Block
    • 1-4 inode和datablock映射
      • 1-4-1 作用
    • 1-5 目录与文件名
    • 1-6 路径解析
    • 1-7 路径缓存
    • 1-8 挂载分区
  • 二,软硬链接
    • 2-1 硬链接
    • 2-2 软链接
    • 2-3 软硬链接对比

前言

本文阅读需要先掌握Ext系列文件系统(硬件篇)

一,ext2文件系统

1-1 宏观认识

  • 所有的准备工作已经完成,是时候认识一下文件系统了。我们想要在硬盘上存储文件,必须先将硬盘格式化为某种格式的文件系统,才能进行文件的读写操作。文件系统的作用就是组织和管理硬盘中的文件和数据
  • 在 Linux 系统中,最常见的是 ext 系列的文件系统。它的早期版本是 ext2,后来发展出了 ext3ext4。虽然 ext3 和 ext4 对 ext2 做了许多增强和优化,但其核心设计并没有发生根本性变化,因此我们仍然以较早的 ext2 作为讲解对象。
  • ext2 文件系统会将整个分区划分成若干个大小相同的块组(Block Group),如下图所示。只要能够管理一个分区,就能够管理所有分区,也就能实现对整个磁盘中文件的统一管理。

在这里插入图片描述

  • 在硬盘结构中,最前面的启动块(Boot Block 或 Boot Sector)大小是固定的,为 1KB,这是由 PC 标准所规定的。启动块用于存储磁盘的分区信息(如分区表)以及启动引导程序(Bootloader),是整个系统启动过程中的关键区域。
  • 由于启动块的作用十分重要,任何文件系统都不能覆盖或修改它。这也是文件系统在格式化分区时,都会从启动块之后的位置开始布局自身结构的原因。
  • 因此,在启动块之后,才是 ext2 文件系统的起始区域,包括超级块(Super Block)组描述符表(Group Descriptor Table)块位图inode 位图inode 表等核心结构。

1-2 Block Group

  • Block Group 是 Ext 文件系统为了提升效率而设计的“磁盘管理单元”,类似把大仓库分成多个小房间,每个房间独立管理自己的物品

1-3 块组内部构成

一个块组由超级块副本组描述符副本块位图inode位图inode表数据块组成,用于局部管理文件系统的元数据和文件数据。


1-3-1 超级块(Super Block)

  • 超级块(Super Block)是一个结构体用于存放文件系统本身的结构信息,描述整个分区的文件系统状态和配置。它记录了大量关键数据,包括:blockinode 的总数、未使用的 blockinode 数量、每个 blockinode 的大小、文件系统创建和挂载的时间、上一次写入数据的时间、上一次进行文件系统检查(fsck)的时间等其他重要的文件系统元信息。
  • 由于超级块在整个文件系统中的地位至关重要,一旦其信息被破坏,就可能导致整个文件系统无法识别和使用,因此可以说超级块的损坏等同于文件系统结构的损坏
  • 超级块(Super Block)在每个块组的开头都会保存一份备份拷贝(第一个块组必须包含,后续块组则可以选择是否备份)。为了确保文件系统在磁盘某些扇区出现物理损坏时依然能够正常工作,文件系统会将超级块的信息备份到多个块组中。这些超级块备份区域的数据会保持一致,从而提高文件系统的可靠性和容错能力

超级块源代码

struct ext2_super_block {__le32  s_blocks_count;         /* 总的 block 数量 */__le32  s_inodes_count;         /* 总的 inode 数量 */__le32  s_free_blocks_count;    /* 未使用的 block 数量 */__le32  s_free_inodes_count;    /* 未使用的 inode 数量 */__le32  s_log_block_size;       /* 一个 block 的大小 */__le16  s_inode_size;           /* 一个 inode 的大小 */__le32  s_mtime;                /* 最近一次挂载时间 */__le32  s_wtime;                /* 最近一次写入数据的时间 */__le32  s_lastcheck;            /* 最近一次检验磁盘的时间 */....
};

1-3-2 块组描述符表GDT(Group Descriptor Table)

块组描述符表是一个数组用于描述各个块组的属性信息。整个分区被划分为多个块组,因此块组描述符的数量与块组数相同。每个块组描述符记录该块组的关键信息,比如 inode 表的起始位置数据块的起始位置,以及空闲的 inode 数据块数量等。为了提高文件系统的可靠性,块组描述符表会在每个块组的开头保存一份备份拷贝

struct ext2_group_desc {__le32  bg_block_bitmap;      /* 块位图所在块号 */__le32  bg_inode_bitmap;      /* inode 位图所在块号 */__le32  bg_inode_table;       /* inode 表起始块号 */__le16  bg_free_blocks_count; /* 该块组中空闲块数 */__le16  bg_free_inodes_count; /* 该块组中空闲 inode 数 */__le16  bg_used_dirs_count;   /* 该块组中已使用的目录数量 */__le16  bg_flags;             /* 标志位 */__le32  bg_exclude_bitmap_lo; /* 用于防止碎片的排除位图(低32位) */__le16  bg_block_bitmap_csum_lo; /* 块位图校验和低16位 */__le16  bg_inode_bitmap_csum_lo; /* inode 位图校验和低16位 */__le16  bg_itable_unused;     /* 未使用的 inode 计数 */__le16  bg_checksum;          /* 描述符校验和 *//* ext4 扩展字段(高32位校验和等)省略 */
};

1-3-3 块位图(Block Bitmap)

Block Bitmap 是位图数组记录了数据块(Data Block)使用情况,用于标示哪个数据块已经被占用,哪个数据块仍然是空闲的


1-3-4 inode位图(Inode Bitmap)

inode位图是一个数组每个bit表⽰⼀个inode是否空闲可⽤


1-3-5 i节点表(Inode Table)

Inode 表(Inode Table)是一个由结构体数组组成的表,每个 inode 结构体存储一个文件或目录的元数据信息(如大小、权限、时间戳、数据块指针等)。


1-3-6 Data Block

数据块(Data Block)是用于存放实际文件内容的区域,不同类型的文件,其数据在数据块中的组织方式有所不同:

  • 普通文件(Regular File):文件的实际内容直接保存在数据块中。文件较大时,可能需要多个数据块。
  • 目录文件(Directory):目录下的所有子文件名和子目录名保存在数据块中。数据块中保存的是目录项(Directory Entry),每个目录项包含文件名和对应的 inode 编号。至于 ls -l 等命令显示的权限、大小、时间等信息,则存储在对应文件的 inode 中。
  • 符号链接、设备文件等特殊文件:其存储结构可能不同,视具体实现而定。

1-4 inode和datablock映射

1-4-1 作用

  • 在 inode 结构中,存在一个数组字段:__le32 i_block[EXT2_N_BLOCKS],其中 EXT2_N_BLOCKS = 15,该数组用于指向文件实际存储的数据块(block),实现 inode 到数据块的映射关系。

  • 因此,对于文件而言,“文件 = 内容 + 属性” 的结构通过 inode 得以完整表示,其中内容通过 i_block 定位到数据块,属性则直接保存在 inode 中。

  • 一个文件的数据可能分布在多个数据块(block)中

  • 因为一个数据块大小固定(通常是 1KB、2KB 或 4KB),如果文件很大,就必须使用多个块

  • 为了实现从 inode 到这些数据块的映射,inode 中有一个字段:

__le32 i_block[15]; // EXT2_N_BLOCKS = 15

i_block[15] 的结构如下:

  • 0 - 11:直接块(Direct Blocks)共 12 个,直接指向数据块
  • 12:一级间接块(Indirect Block),指向一个块,这个块中存放的是数据块的地址
  • 13:二级间接块(Double Indirect),指向一个块,该块中是一级间接块的地址
  • 14:三级间接块(Triple Indirect),原理类似,递归两次,最终指向数据块

例子:

  • 如果一个块是 1KB,一个文件大小是 20KB,那就需要 20 个块。
  • 前 12 个块可以直接由 i_block[0] 到 i_block[11] 找到。
  • 剩下的 8 个就要依赖 i_block[12](一级间接块)来继续定位。

创建一个文件
在这里插入图片描述
上图创建文件的流程如下图
在这里插入图片描述

  • 存储属性(分配 inode)
    • 内核首先从 inode 位图中寻找一个空闲 inode(例如编号为 263466),并将该文件的属性信息(如权限、所有者、时间戳、文件大小等)记录到这个 inode 中。
  • 存储数据(分配数据块)
    • 该文件需要占用 3 个数据块,内核从数据块位图中找到了空闲的数据块编号为:300、500 和 800。
      内核将缓冲区中的文件数据依次写入这些块中:
      第一个数据块 → 300
      第二个数据块 → 500
      第三个数据块 → 800
  • 记录分配情况(更新 i_block[])
    • 文件内容按顺序存放在块号 300、500 和 800 中。
      内核会将这 3 个数据块的编号写入 inodei_block[] 数组中,作为该文件的块映射信息。这样,文件的数据位置就与 inode 建立了连接。
  • 添加文件名到目录(建立文件名与 inode 的对应)
    • 新文件命名为 "abc"
      内核会在当前目录文件中添加一条目录项(目录项 = 文件名 + inode 号),即:
      (abc, 263466)
      这样,用户通过文件名 “abc” 就可以在目录中查到对应的 inode 号,从而找到文件的属性和数据内容。

总结:

  • 一个 inode 对应一个文件,而 i_block[15] 数组提供了从该 inode 到所有实际存储文件数据的 block 的完整路径。

  • 分区完成后的格式化操作,本质上是对该分区进行文件系统的初始化。它会将分区划分为若干个 Block Group(块组),并在每个块组中写入关键的管理信息,如:Super Block(SB)Group Descriptor Table(GDT)Block BitmapInode BitmapInode Table 等。这些管理信息的集合,统称为 文件系统结构

  • 只要知道一个文件的 inode 号,就能通过算法计算出该 inode 位于 哪一个块组,再根据该块组中的 inode table 精确定位到这个 inode 的位置。

  • 拿到 inode 后,就可以读取该文件的 所有属性(权限、大小、时间等),以及通过 i_block[] 数组定位到 实际存储内容的数据块,从而获取或修改文件的全部信息。


1-5 目录与文件名

目录也是一种文件,但在磁盘层面,并不存在“目录”这一独立概念,只有“文件属性”和“文件内容”这两个基本构成。

对于目录文件而言,其属性部分与普通文件类似,不再赘述;而其内容部分则保存了文件名对应 inode 编号的映射关系,用于标识该目录下包含的文件或子目录。

直接看代码

readdir.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<dirent.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc,char *argv[])
{if(argc != 2){fprintf(stderr,"Usage:%s <directory>\n",argv[0]);exit(EXIT_FAILURE);}DIR *dir = opendir(argv[1]);//DIR 是表示目录流的结构体,用于读取目录内容if(!dir){perror("opendir");exit(EXIT_FAILURE);}struct dirent *entry;//struct dirent 表示目录中的单个文件项信息while((entry = readdir(dir))!=NULL){if(strcmp(entry->d_name,".")==0 || strcmp(entry->d_name,"..")==0)//d_name 是目录项中文件或子目录的名称{continue;}printf("Filename:%s,Inode:%lu\n",entry->d_name,(unsigned long)entry->d_ino);//d_ino 是文件或目录对应的 inode 编号,用于唯一标识文件}closedir(dir);return 0;
}

演示结果

[gch@hcss-ecs-f59a day7]$ gcc -o readdir readdir.c
[gch@hcss-ecs-f59a day7]$ ./readdir /
Filename:proc,Inode:131073
Filename:usr,Inode:393223
Filename:boot,Inode:131077
Filename:mnt,Inode:131084
Filename:sys,Inode:131074
Filename:opt,Inode:131085
Filename:root,Inode:524290
Filename:var,Inode:524291
Filename:tmp,Inode:131075
Filename:media,Inode:131083
Filename:working,Inode:1835009
Filename:sbin,Inode:16
Filename:home,Inode:131082
Filename:lib64,Inode:15
Filename:CloudrResetPwdAgent,Inode:264516
Filename:lib,Inode:13
Filename:dev,Inode:393217
Filename:lost+found,Inode:11
Filename:etc,Inode:393218
Filename:.autorelabel,Inode:14711
Filename:run,Inode:524289
Filename:srv,Inode:131086
Filename:bin,Inode:17
[gch@hcss-ecs-f59a day7]$ ls -li /total 6817 lrwxrwxrwx.   1 root root     7 Jul 26  2024 bin -> usr/bin131077 dr-xr-xr-x.   5 root root  4096 Jul 15 12:58 boot264516 drwxr-xr-x    7 root root  4096 Jul 26  2024 CloudrResetPwdAgent1026 drwxr-xr-x   19 root root  3020 Jul 15 13:03 dev393218 drwxr-xr-x.  78 root root  4096 Jul 25 08:55 etc131082 drwxr-xr-x.   3 root root  4096 Jul 15 13:05 home13 lrwxrwxrwx.   1 root root     7 Jul 26  2024 lib -> usr/lib15 lrwxrwxrwx.   1 root root     9 Jul 26  2024 lib64 -> usr/lib6411 drwx------.   2 root root 16384 Jul 26  2024 lost+found131083 drwxr-xr-x.   2 root root  4096 Apr 11  2018 media131084 drwxr-xr-x.   2 root root  4096 Apr 11  2018 mnt131085 drwxr-xr-x.   2 root root  4096 Apr 11  2018 opt1 dr-xr-xr-x  123 root root     0 Jul 15 13:03 proc524290 dr-xr-x---.   5 root root  4096 Jul 15 19:33 root1259 drwxr-xr-x   24 root root   640 Jul 25 09:12 run16 lrwxrwxrwx.   1 root root     8 Jul 26  2024 sbin -> usr/sbin131086 drwxr-xr-x.   2 root root  4096 Apr 11  2018 srv1 dr-xr-xr-x   13 root root     0 Jul 15 13:05 sys131075 drwxrwxrwt.  13 root root  4096 Aug  8 15:53 tmp393223 drwxr-xr-x.  13 root root  4096 Jul 26  2024 usr524291 drwxr-xr-x.  19 root root  4096 Jul 26  2024 var
1835009 drwxrwxrwx    3 root root  4096 Jul 15 14:59 working

所以在文件系统里,访问一个文件需要经过以下步骤:

  • 打开当前目录
    因为文件名只是存在目录文件里的一个名字,目录本身也是一种文件,保存着“文件名和对应 inode 号”的映射关系。
  • 根据文件名查找 inode 号
    通过读取当前目录文件的内容,找到对应文件名所关联的 inode(文件索引节点)编号。
  • 通过 inode 访问文件内容
    inode 记录了文件的元信息和数据存储位置,系统根据 inode 可以定位到文件实际内容,从而实现文件访问。

重点是:

  • 文件系统访问文件不是直接通过文件名,而是先打开包含该文件的目录,读取目录内容找到文件对应的 inode。

  • 因此,必须知道“当前工作目录”(即当前所在的目录),才能打开它,查找目标文件的 inode,才能访问文件。


1-6 路径解析

  • 访问文件时,必须先打开当前工作目录文件,查看其内容,因为目录文件保存着文件名与 inode 号的映射关系。当前工作目录本身也是一个目录文件,要访问它,必须知道它的 inode 号。

  • 因此,要访问当前工作目录,需要先打开它的上级目录。上级目录也是目录文件,访问它同样需要知道其 inode,进而访问其上级目录。如此形成了一个递归过程,需要依次解析路径中的所有目录,直到根目录 /

  • 实际上,任何文件都有一个完整路径,例如 /home/whb/code/test/test/test.c。访问目标文件时,必须从根目录开始,依次打开每一级目录,根据目录名找到对应目录,逐级向下,直到定位到目标文件。这一过程称为 Linux 路径解析

  • 由此可见,访问文件必须提供目录和文件名,即完整路径。根目录的文件名和 inode 号是固定的,系统启动后即已知,无需查找。

  • 路径信息由进程提供,进程维护当前工作目录(CWD),用户在访问文件时通过指令或工具提供路径。

  • Linux 设计根目录以及众多默认目录,是为了构建完整的路径体系。用户也可以自行新建目录,任何新建文件都依附于某个目录,这样天然形成了路径结构。系统和用户共同构建了 Linux 的路径层级结构。


1-7 路径缓存

  • Linux磁盘中不存在真正的目录磁盘上只有文件,文件由文件属性和文件内容组成。

  • 访问任何文件都需要从根目录 / 开始进行路径解析。原则上路径解析是逐层进行的,但为了提高效率,Linux 会缓存历史路径结构

  • 目录的概念由操作系统产生,当打开的文件是目录时,操作系统会在内存中维护路径信息。

在 Linux 内核中,用于维护树状路径结构的核心数据结构是 struct dentry

struct dentry {struct inode *d_inode;         // 指向该目录项对应的 inode,表示文件或目录的元信息struct dentry *d_parent;       // 指向父目录的 dentry,形成目录树的层级结构struct qstr d_name;            // 目录项的名称,包含名字字符串及其长度、哈希值struct list_head d_lru;        // 用于管理 dentry 缓存的 LRU 链表节点struct list_head d_subdirs;    // 链表头,指向当前 dentry 的所有子目录项,维护目录的子节点链表// ... 结构体中还有其他成员
};
  • 每个文件其实都会对应一个 dentry 结构体,包括普通文件也是这样。这样一来,所有打开过的文件在内存里就能组成一棵完整的树。

  • 这棵树的节点同时会被放进一个叫做 LRU(最近最少使用)的结构里,方便系统淘汰不常用的节点,节省内存。

  • 另外,这些节点还会被放进哈希表里,方便快速查找。

  • 更重要的是,这整棵树其实就是 Linux 的路径缓存。每次访问文件时,系统会先在这棵树里根据路径查找对应的节点,如果找到了,就直接返回文件的 inode内容;找不到的话,就从磁盘加载对应路径,创建新的 dentry 结构,缓存起来。

在这里插入图片描述


1-8 挂载分区

  • 我们已经可以根据 inode 号在指定的分区中定位文件,也能够通过目录文件的内容找到对应的 inode,因此在同一个分区内,文件访问是没有限制的,可以自由操作

  • 但是,inode 编号在不同分区之间并不通用,不能跨分区使用。而 Linux 系统通常会包含多个分区,这就带来了一个问题:在访问文件时,系统必须明确知道当前所处的是哪个分区。

  • 为了解决这个问题,Linux 文件系统会为每个挂载的分区(也就是文件系统)维护一个挂载点,并记录每个分区的根 inode挂载路径。通过这些挂载信息,系统就可以确定路径中每一级目录属于哪个分区,从而正确地解析每个目录项和 inode 的对应关系,实现跨分区的路径解析。

struct mount {struct mount *mnt_parent;       // 指向父挂载点(如 /mnt/usb 的父是 /mnt)struct dentry *mnt_mountpoint;  // 指向挂载点目录的 dentry,比如 /mntstruct vfsmount *mnt;           // 指向挂载的文件系统信息(早期叫 vfsmount)struct list_head mnt_children;  // 所有挂载在此挂载点下的子挂载点struct list_head mnt_instance;  // 用于将 mount 实例插入全局链表
};

二,软硬链接

2-1 硬链接

我们可以看到,在 Linux 中真正用来定位磁盘上文件的,其实不是文件名,而是 inode文件名只是一个“门牌号”,而 inode 才是找到文件内容的“钥匙”

实际上,Linux 允许多个不同的文件名指向同一个 inode,这意味着它们共享同一份文件内容。这种机制就叫做硬链接。换句话说,多个文件名可以像“别名”一样,共同指向同一个文件实体。

[gch@hcss-ecs-f59a day7]$ touch adc
[gch@hcss-ecs-f59a day7]$ ln adc def
[gch@hcss-ecs-f59a day7]$ ls -li
total 16
1835335 -rw-rw-r-- 2 gch gch    0 Aug  8 16:48 adc
1835335 -rw-rw-r-- 2 gch gch    0 Aug  8 16:48 def

比如 adcdef 两个文件,它们其实指向的是同一个 inode,链接状态完全一样。这种情况被称为硬链接,它们本质上是同一个文件,只是有两个不同的文件名而已。

内核会记录这个 inode 被多少个文件名引用,这个数字叫做硬链接数。比如 inode 编号为 263466 的文件,它的硬链接数是 2,就说明有两个名字(比如 abc 和 def)指向它

当我们删除一个文件时,其实做了两件事:
1.== 从目录中把这个文件名的记录删掉==;
2. 把对应 inode 的硬链接数减 1

如果减到0,说明没有任何文件名再指向这个 inode,系统就会把它对应的磁盘空间释放掉,文件内容才会真正消失。


2-2 软链接

在 Linux 中,硬链接是通过共享 inode 来引用同一个文件;也就是说,多个文件名指向同一个 inode,文件内容完全相同,彼此是“平级”的,没有主从关系。

软链接(符号链接)是通过路径名来引用另一个文件,本质上是一个独立的文件,它里面保存的是目标文件的路径。软链接的 inode 和原文件不同,可以看作是一个快捷方式

[gch@hcss-ecs-f59a day7]$ ll
total 0
-rw-rw-r-- 2 gch gch 0 Aug  8 16:48 adc
-rw-rw-r-- 2 gch gch 0 Aug  8 16:48 def
[gch@hcss-ecs-f59a day7]$ ln -s adc abc
[gch@hcss-ecs-f59a day7]$ ls -li 
total 0
1835333 lrwxrwxrwx 1 gch gch 3 Aug  8 16:58 abc -> adc
1835335 -rw-rw-r-- 2 gch gch 0 Aug  8 16:48 adc
1835335 -rw-rw-r-- 2 gch gch 0 Aug  8 16:48 def

2-3 软硬链接对比

硬连接(Hard Link)——同一个人多个名字
特点:

  • 多个文件名 → 指向 同一个 inode(身份证)

  • 内容完全一致,本质上是“同一个文件”

  • 删除任意一个文件名不会影响文件本身,除非所有名字都删掉

  • 只能用于同一个分区

比喻:
就像一个人叫“张三”,又被朋友叫“老三”。
无论你叫哪个名字,他还是同一个人(inode)。

软连接(Symbolic Link)——指向地址的快捷方式
特点:

  • 文件名中保存的是“另一个文件的路径

  • 是一个独立的文件,拥有自己的 inode

  • 被链接的目标文件如果被删除或移动,链接就失效(变成断链)

  • 可以跨分区

比喻
就像你电脑桌面上的快捷方式(.lnk 文件)。
它指向某个程序的位置,但自己不是真正的程序。
如果程序被删除,快捷方式就打不开了。

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

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

相关文章

14. isaacsim4.2教程-April Tags/给相机加噪声

1. 前言April Tags 是一种视觉标签&#xff08;类似 QR 码&#xff09;&#xff0c;用于通过相机进行定位和识别。它们通常用于计算机视觉任务中&#xff0c;帮助机器人识别和定位自己在物理空间中的位置&#xff0c;或者识别和追踪特定对象。前提条件启用 ROS 桥接&#xff1a…

Kafka + 时间轮 + 数据库实现延迟队列方案

Kafka 原生不支持延迟队列功能。而RabbitMQ、RocketMQ及Redis等其他消息队列原生支持延迟队列。 RabbitMQ RocketMQ Redis 实现方式 通过插件实现&#xff0c;消息进入延迟队列后根据配置时间过滤转发。 原生支持&#xff0c;发送消息时设置延迟级别&#xff0c;定时任务处…

力扣 hot100 Day69

287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你设计的解决方案必须 不修改…

Android 的CameraX的使用(配置,预览,拍照,图像分析,录视频)

Android Studio 版本号:2024.1.2 CameraX是Jetpack系列中的一个库,它基于Camera2 API构建,但提供了更高层次的抽象。 CameraX 三大核心用例: Preview预览 ,ImageCapture拍照和 VideoCapture录视频 一、创建项目,进行环境配置 CameraX 需要一些属于 Java 8 的方法,因此…

【机器学习深度学习】微调训练数据质量

目录 前言 一、为什么数据质量评估很重要 二、数据质量评估的核心维度 三、数据质量的可量化维度&#xff08;必须要测的指标&#xff09; 四、多答案、多类型数据的取舍与优化 场景 A&#xff1a;一个问题有多个相似回答 场景 B&#xff1a;多个类型数据&#xff0c;每…

从DeepSeek-V3到Kimi K2,大型语言模型架构对比

文章目录 摘要 **稀疏化与专家系统** **注意力机制优化** **归一化与稳定性设计** 模型架构对比详析 DeepSeek-V3 vs Llama 4 Maverick Qwen3 vs SmolLM3 Kimi 2的突破 1 DeepSeek V3/R1 1.1 多头潜在注意力(MLA) 1.2 混合专家系统(MoE) 1.3 DeepSeek 总结 2 OLMo 2 2.1 归…

Unity笔记(二)——Time、Vector3、位置位移、角度、旋转、缩放、看向

写在前面写本系列的目的(自用)是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。这里只有部分语法知识。五、Time时间相关1、时间缩放比例概念&#xff1a;可以通过UnityEngine.Time类的timeScale属性控制游戏时…

vue+vite项目中怎么定义一个环境变量可以在开发环境和生产环境使用不同的值,并且可以在vue页面和index.html通用。

首先我们需要下载一个插件vite-plugin-html然后再项目最外层和index.html同级目录下新建.env.development和.env.production两个项目并且定义你想要的环境变量名:注意要以VITE_开头VITE_APP_MAP_TOKEN1233444然后vite.config.js文件import { defineConfig,loadEnv } from vite…

Python-深度学习--2信息熵,条件熵(ID3决策树),KL散度

一、信息熵&#xff08;Entropy&#xff09;的计算与应用信息熵用于衡量一个概率分布的不确定性&#xff0c;值越大表示分布越分散&#xff08;不确定性越高&#xff09;。1. 数学定义对于离散概率分布 P&#xff0c;信息熵公式为&#xff1a;&#xff08;通常以 2 为底单位是比…

国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等

在现代办公场景中&#xff0c;Word文档已成为信息存储与交流的重要载体&#xff0c;承载着关键的业务数据、结构化表格、可视化图表以及协作批注等重要内容。面对日益增长的文档处理需求&#xff0c;传统的人工操作方式已难以满足效率与准确性的双重标准。采用Python实现Word文…

Spring IOC 原理

Spring IoC&#xff08;控制反转&#xff09;是Spring框架的核心机制&#xff0c;其原理是通过容器管理对象生命周期和依赖关系&#xff0c;实现解耦。 1. 控制反转&#xff08;IoC&#xff09;核心思想 传统模式&#xff1a;对象主动创建依赖&#xff08;如new Service()&…

VSCode:基础使用 / 使用积累

官网 Visual Studio Code - Code Editing. Redefined 记录一、更新依赖 尝试删除yarn.lock文件 记录二、“解决冲突”的方式变了 更新后&#xff0c;“解决冲突”的方式变了&#xff0c;有的时候能选中两者&#xff0c;有的时候不能 现在又更新了&#xff0c;回复到了原来…

tcp 确认应答和超时时间

1. 确认应答之间的时间&#xff08;RTT&#xff09;这是指 从发送方发送数据到接收方返回确认&#xff08;ACK&#xff09;之间的时间。它反映的是数据传输的 往返延迟。例如&#xff0c;发送方发送一个数据包&#xff0c;接收方收到后&#xff0c;回传一个确认包&#xff08;A…

图的应用-最短路径

最短路径的典型用途&#xff1a;交通网络的问题——从甲地到乙地之间是否有公路连通&#xff1f;在有多条通路的情况下&#xff0c;哪一条路最短&#xff1f;交通网络用有向网来表示&#xff1a;顶点——表示地点&#xff0c;弧——表示两个地点有路连通&#xff0c;弧上的权值…

【qt5_study】1.Hello world

模板 作为初学者我们选择第一个Application(Qt)和 Qt Widgets Application,所谓的模板就是 Qt为了方便开发程序,在新建工程时可以让用户基于一种模板来编写程序,包括 cpp文件, ui文件都已经快速的创建,而不用用户手动创建这些文件。 基类 这里默认选择的基类为 QMainWin…

项目构想|文生图小程序

Date: August 4, 2025项目介绍 &#x1f44b;&#xff0c;我们通过 Vibe Coding 做一个文字生成图片的小程序。 我们会从需求分析、技术选型、UI设计、项目构筑到最后打包&#xff0c;一路尝试 Vibe Coding 实现。 创建项目 创建文件夹&#xff1a;ai-pic-mini-app 采用 Git 进…

TiDB/MongoDB/Taosdb存储引擎概览

数据库类型存储引擎数据结构源码位置tidbRockDBLSM树https://github.com/facebook/rocksdbmongodbWiredTigerB 树/LSM树https://github.com/wiredtiger/wiredtigerTDengineTSDBBRINhttps://github.com/taosdata/TDengine 1、tidb存储引擎概览 LSM树数据结构描述LSM树(Log Str…

qt窗口--01

文章目录qt窗口--01窗口概览菜单栏工具栏状态栏浮动窗口子窗口对话框model结语很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 作者&#xff1a;٩( ‘ω’ )و260 我的专栏&#xff1a;qt&#xff0c;Li…

Neo4j 社区版 Mac 安装教程

最近用到了nebulagraph图数据库做金融反欺诈项目&#xff0c;虽然nebula属于分布式架构&#xff0c;但依然感觉nebula使用不太顺手&#xff0c;这里顺便研究一下neo4j这款数据库如何&#xff0c;这里先从安装开始&#xff1f; 一、 准备工作 确认 Java 版本要求&#xff1a; N…

Android Studio(2025.1.2)Gemini Agent 使用指南

Android Studio&#xff08;2025.1.2&#xff09;Gemini Agent 使用指南 文章目录Android Studio&#xff08;2025.1.2&#xff09;Gemini Agent 使用指南1. 什么是 Gemini Agent&#xff1f;2. 如何启用和配置 Gemini Agent2.1 获取 API Key2.2 在 Android Studio 中配置3. 实…