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
英文地址,請注明出處:http://en.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. 實…