【Linux 系統】基礎IO——Linux中對文件的理解

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個插件時的快樂&…