Linux中《基礎IO》詳細介紹

目錄

  • 理解"文件"
    • 狹義理解
    • 廣義理解
    • 文件操作的歸類認知
    • 系統角度
      • 文件類別
  • 回顧C文件接口
    • 打開文件
    • 寫文件
    • 讀文件
      • 稍作修改,實現簡單cat命令
    • 輸出信息到顯示器,你有哪些方法
    • stdin & stdout & stderr
    • 打開文件的方式
  • 系統?件I/O
    • ?種傳遞標志位的方法
    • 系統調用
      • 理解文本寫入和二進制寫入
      • FILE介紹
    • open函數返回值
    • 文件描述符fd
      • ?件描述符的分配規則
    • 重定向
    • 使用 dup2 系統調用
    • 為什么會有標準錯誤和標準輸錯呢?還指向同一個顯示器(文件)?
  • 理解“?切皆文件”
    • 緩沖區
    • 什么是緩沖區
    • 為什么要引入緩沖區機制
    • FILE
    • 緩沖類型

理解"文件"

狹義理解

? ?件在磁盤?
? 磁盤是永久性存儲介質,因此?件在磁盤上的存儲是永久性的
? 磁盤是外設(即是輸出設備也是輸?設備)
? 磁盤上的?件 本質是對?件的所有操作,都是對外設的輸?和輸出簡稱 IO

廣義理解

Linux 下?切皆?件(鍵盤、顯?器、?卡、磁盤…… 這些都是抽象化的過程)

文件操作的歸類認知

? 對于 0KB 的空?件是占?磁盤空間的
? ?件是?件屬性(元數據)和?件內容的集合(?件 = 屬性(元數據)+ 內容)
? 所有的?件操作本質是?件內容操作和?件屬性操作

系統角度

? 對?件的操作本質是進程對?件的操作
? 磁盤的管理者是操作系統
? ?件的讀寫本質不是通過 C 語? / C++ 的庫函數來操作的(這些庫函數只是為??提供?便),?是通過?件相關的系統調?接?來實現的.
在這里插入圖片描述

文件類別

"內存級(被打開)"文件
磁盤級文件

回顧C文件接口

打開文件

在這里插入圖片描述
打開的log.txt?件在哪個路徑下?
在程序的當前路徑下,那系統怎么知道程序的當前路徑在哪?呢?
(會把當前路徑和文件名進行拼接,來創建文件)
可以使? ls /proc/[進程id] -l 命令查看當前正在運?進程的信息:
在這里插入圖片描述
打開?件,本質是進程打開,所以,進程知道??在哪?,即便?件不帶路徑,進程也知道。由此OS就能知道要創建的?件放在哪?。

寫文件

在這里插入圖片描述

在這里插入圖片描述

讀文件

在這里插入圖片描述

稍作修改,實現簡單cat命令

在這里插入圖片描述

輸出信息到顯示器,你有哪些方法

在這里插入圖片描述

stdin & stdout & stderr

  • C默認會打開三個輸?輸出流,分別是stdin, stdout, stderr
  • 仔細觀察發現,這三個流的類型都是FILE*, fopen返回值類型,文件指針
#include <stdio.h>
extern FILE *stdin;//標準輸入 -- 鍵盤文件
extern FILE *stdin;//標準輸出 -- 顯示器文件
extern FILE *stderr;//標準錯誤 -- 顯示器文件

程序啟動時,默認會打開這三個文件(編譯器做的),為什么呢?
因為我們的程序是做數據處理的,打開stdin,stdin是為了給程序提供默認的數據源和數據結果。這三個默認打開的文件,自己是可以手動關掉的。

打開文件的方式

在這里插入圖片描述

如上,是我們之前學的?件相關操作。還有 fseekftellrewind的函數
在這里插入圖片描述

細節注意:不要把\0寫入文件,它是C語言的規定,和文件沒有關系,有時候會出現亂碼。

系統?件I/O

打開?件的?式不僅僅是fopen,ifstream等流式,語?層的?案,其實系統才是打開?件最底層的?案。不過,在學習系統?件IO之前,先要了解下如何給函數傳遞標志位,該?法在系統?件IO接?中會使?到。

?種傳遞標志位的方法

#include <stdio.h>
#define ONE 0001 //0000 0001
#define TWO 0002 //0000 0010
#define THREE 0004 //0000 0100void func(int flags) {if (flags & ONE) printf("flags has ONE! ");if (flags & TWO) printf("flags has TWO! ");if (flags & THREE) printf("flags has THREE! ");printf("\n");
}int main() {func(ONE);func(THREE);func(ONE | TWO);func(ONE | THREE | TWO);return 0;
}

以位圖的形式傳遞。

操作?件,除了上?節的C接?(當然,C++也有接?,其他語?也有),我們還可以采?系統接?來進??件訪問, 先來直接以系統代碼的形式,實現和上??模?樣的代碼:
在這里插入圖片描述

系統調用

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int open(const char *pathname, int flags);//打開已經創建的文件
int open(const char *pathname, int flags, mode_t mode);//打開未創建的文件flags(這里挑選幾個常用的標記位)
O_CREAT:不存在就創建
O_RDNOIY:只讀
O_WRNOLY:只寫(不會清空內容)
O_APPEND:追加
O_TRUNC:清除

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

 #include <unistd.h>int close(int fd);//fd是open函數的返回值
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);//返回值是寫入的字節數

理解文本寫入和二進制寫入

文本寫入:將數據以文本形式存儲,通常是以人類可讀的字符形式(如ASCII或UTF-8編碼)寫入文件。例如,普通的文本文件(如.txt文件)就是以文本方式存儲的。數據以字符編碼的形式存儲。例如,字符’A’在ASCII編碼中對應十進制的65,存儲時會以01000001的形式寫入文件。

二進制寫入:將數據以二進制形式存儲,即直接將數據的二進制表示寫入文件。這種方式通常用于存儲程序的可執行文件、庫文件、圖像文件等,這些文件的內容對人類來說是不可直接閱讀的,但計算機可以直接解析和處理。數據以原始的二進制形式存儲,不經過字符編碼轉換。例如,一個整數65在內存中以二進制形式存儲為01000001,直接將這個二進制形式寫入文件。

總結:文本寫入和二進制寫入都是語言層面的概念,系統只認二進制,格式化輸出時,只是把二進制轉成你想要的格式,你想要輸出什么格式,需要你自己轉。
在這里插入圖片描述

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);//返回值是讀到的字節數

在這里插入圖片描述

FILE介紹

FILE:是C語言標準庫中定義的一個結構體類型(struct),用來表示一個“文件流”,結構體里面封裝了文件描述符fd,在操作系統的接口中,只認文件操作符fd。

open函數返回值

在認識返回值之前,先來認識?下兩個概念: 系統調? 和 庫函數

? 上?的 fopen fclose fread fwrite 都是C標準庫當中的函數,我們稱之為庫函數(libc)。
? ? open close read write lseek 都屬于系統提供的接?,稱之為系統調?接?
? 回憶?下我們講操作系統概念時,畫的?張圖:
在這里插入圖片描述

系統調?接?和庫函數的關系,??了然。
所以,可以認為, f# 系列的函數,都是對系統調?的封裝,?便?次開發。

文件描述符fd

通過對open函數的學習,我們知道了?件描述符就是?個?整數

  • Linux進程默認情況下會有3個缺省打開的?件描述符,分別是標準輸?0, 標準輸出1, 標準錯
    誤2.
  • 0,1,2對應的物理設備?般是:鍵盤,顯?器,顯?器
    所以輸?輸出還可以采?如下?式:
    在這里插入圖片描述

在這里插入圖片描述
進程執?open系統調?,所以必須讓進程和?件關聯起來。每個進程都有?個指針*files, 指向?張表files_struct,該表最重要的部分就是包含?個指針數組,每個元素都是?個指向打開?件的指針!所以,本質上,?件描述符就是該數組的下標。所以,只要拿著?件描述符,就可以找到對應的?件。
在這里插入圖片描述

?件描述符的分配規則

在這里插入圖片描述
可?,?件描述符的分配規則:在files_struct數組當中,找到當前沒有被使用的最小的?個下標,作為新的?件描述符。

重定向

在這里插入圖片描述

那重定向的本質是什么呢?更改文件描述符表
在這里插入圖片描述

使用 dup2 系統調用

#include<unistd.h>
int dup2(int oldfd,int newfd);

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

為什么會有標準錯誤和標準輸錯呢?還指向同一個顯示器(文件)?

這樣可以通過重定向的能力,把常規消息和錯誤消息進行分離。
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

理解“?切皆文件”

  • ?先,在windows中是?件的東西,它們在linux中也是?件;其次?些在windows中不是?件的東西,?如進程、磁盤、顯?器、鍵盤這樣硬件設備也被抽象成了?件,你可以使?訪問?件的?法訪問它們獲得信息;甚?管道,也是?件;將來我們要學習?絡編程中的socket(套接字)這樣的東西,使?的接?跟?件接?也是?致的。
  • 這樣做最明顯的好處是,開發者僅需要使??套 API 和開發?具,即可調取 Linux 系統中絕?部分的資源。舉個簡單的例?,Linux 中?乎所有讀(讀?件,讀系統狀態,讀PIPE)的操作都可以?read 函數來進?;?乎所有更改(更改?件,更改系統參數,寫PIPE)的操作都可以? write 函數來進?。
struct file {
...
struct inode *f_inode; /* cached value */
const struct file_operations *f_op;
...
atomic_long_t f_count; // 表?打開?件的引?計數,如果有多個?件指針指向
它,就會增加f_count的值。
unsigned int f_flags; // 表?打開?件的權限
fmode_t f_mode; // 設置對?件的訪問模式,例如:只讀,只寫等。所有
的標志在頭?件<fcntl.h> 中定義
loff_t f_pos; // 表?當前讀寫?件的位置
...
} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */

當打開?個?件時,操作系統為了管理所打開的?件,都會為這個?件創建?個file結構體。
值得關注的是 struct file 中的f_op指針指向了?個file_operations 結構體,這個結構體中的成員除了struct module* owner 其余都是函數指針。
file_operation 就是把系統調?和驅動程序關聯起來的關鍵數據結構,這個結構的每?個成員都對應著?個系統調?。讀取 file_operation 中相應的函數指針,接著把控制權轉交給函數,從?完成了Linux設備驅動程序的?作。

struct file_operations {
struct module *owner;
//指向擁有該模塊的指針;
loff_t (*llseek) (struct file *, loff_t, int);
//llseek ?法?作改變?件中的當前讀/寫位置, 并且新位置作為(正的)返回值.
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//?來從設備中獲取數據. 在這個位置的?個空指針導致 read 系統調?以 -
EINVAL("Invalid argument") 失敗. ?個?負返回值代表了成功讀取的字節數( 返回值是?個
"signed size" 類型, 常常是?標平臺本地的整數類型).
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//發送數據給設備. 如果 NULL, -EINVAL 返回給調? write 系統調?的程序. 如果?負, 返
回值代表成功寫的字節數.
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long,
loff_t);
//初始化?個異步讀 -- 可能在函數返回前不結束的讀操作.
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long,
loff_t);
//初始化設備上的?個異步寫.
int (*readdir) (struct file *, void *, filldir_t);
//對于設備?件這個成員應當為 NULL; 它?來讀取?錄, 并且僅對**?件系統**有?.
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);//mmap ?來請求將設備內存映射到進程的地址空間. 如果這個?法是 NULL, mmap 系統調?返-ENODEV.
int (*open) (struct inode *, struct file *);
//打開?個?件
int (*flush) (struct file *, fl_owner_t id);
//flush 操作在進程關閉它的設備?件描述符的拷?時調?;
int (*release) (struct inode *, struct file *);
//在?件結構被釋放時引?這個操作. 如同 open, release 可以為 NULL.
int (*fsync) (struct file *, struct dentry *, int datasync);
//??調?來刷新任何掛著的數據.
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
//lock ?法?來實現?件加鎖; 加鎖對常規?件是必不可少的特性, 但是設備驅動?乎從不實現.
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *,
int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned
long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
};

在這里插入圖片描述

緩沖區

什么是緩沖區

緩沖區是內存空間的?部分。也就是說,在內存空間中預留了?定的存儲空間,這些存儲空間?來緩沖輸?或輸出的數據,這部分預留的空間就叫做緩沖區。緩沖區根據其對應的是輸?設備還是輸出設備,分為輸?緩沖區和輸出緩沖區。
總結:緩沖區就是一段內存空間

為什么要引入緩沖區機制

  • 讀寫?件時,如果不會開辟對?件操作的緩沖區,直接通過系統調?對磁盤進?操作(讀、寫等),那么每次對?件進??次讀寫操作時,都需要使?讀寫系統調?來處理此操作,即需要執??次系統調?,執??次系統調?將涉及到CPU狀態的切換,即從??空間切換到內核空間,實現進程上下?的切換,這將損耗?定的CPU時間,頻繁的磁盤訪問對程序的執?效率造成很?的影響。
  • 為了減少使?系統調?的次數,提?效率,我們就可以采?緩沖機制。?如我們從磁盤?取信息,可以在磁盤?件進?操作時,可以?次從?件中讀出?量的數據到緩沖區中,以后對這部分的訪問就不需要再使?系統調?了,等緩沖區的數據取完后再去磁盤中讀取,這樣就可以減少磁盤的讀寫次數,再加上計算機對緩沖區的操作? 快于對磁盤的操作,故應?緩沖區可? 提?計算機的運?速度。
  • ??如,我們使?打印機打印?檔,由于打印機的打印速度相對較慢,我們先把?檔輸出到打印機相應的緩沖區,打印機再??逐步打印,這時我們的CPU可以處理別的事情。可以看出,緩沖區就是?塊內存區,它?在輸?輸出設備和CPU之間,?來緩存數據。它使得低速的輸?輸出設備和?速的CPU能夠協調?作,避免低速的輸?輸出設備占?CPU,解放出CPU,使其能夠?效率?作。
    在這里插入圖片描述

FILE

  • 因為IO相關函數與系統調?接?對應,并且庫函數封裝系統調?,所以本質上,訪問?件都是通過fd訪問的。
  • 所以C庫當中的FILE結構體內部,必定封裝了fd。

緩沖類型

標準I/O提供了3種類型的緩沖區。

  • 全緩沖區:這種緩沖?式要求填滿整個緩沖區后才進?I/O系統調?操作。對于磁盤?件的操作通常使?全緩沖的?式訪問。
  • ?緩沖區:在?緩沖情況下,當在輸?和輸出中遇到換?符時,標準I/O庫函數將會執?系統調?操作。當所操作的流涉及?個終端時(例如標準輸?和標準輸出),使??緩沖?式。因為標準I/O庫每?的緩沖區?度是固定的,所以只要填滿了緩沖區,即使還沒有遇到換?符,也會執?I/O系統調?操作,默認?緩沖區的??為1024。
  • ?緩沖區:?緩沖區是指標準I/O庫不對字符進?緩存,直接調?系統調?。標準出錯流stderr通常是不帶緩沖區的,這使得出錯信息能夠盡快地顯示出來。

在這里插入圖片描述
在這里插入圖片描述
我們發現 printf ,fprintf和 fwrite (庫函數)都輸出了2次,? write 只輸出了?次(系統調?)。為什么呢?肯定和fork有關!

  • ?般C庫函數寫??件時是全緩沖的,?寫?顯示器是?緩沖。
  • fprintf printf fwrite 庫函數+會?帶緩沖區,當發?重定向到普通?件時,數據的緩沖?式由?緩沖變成了全緩沖
  • ?我們放在緩沖區中的數據,就不會被?即刷新,甚?fork之后
  • 但是進程退出之后,會統?刷新,寫??件當中。
  • 但是fork的時候,??數據會發?寫時拷?,所以當你?進程準備刷新的時候,?進程也就有了同樣的?份數據,隨即產?兩份數據。
  • write 沒有變化,說明沒有所謂的緩沖。
typedef _IO_FILE FILE;
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags//緩沖區相關
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer *///這些就是緩沖區
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;//管理文件緩沖區的鏈表
int _fileno; //封裝的?件描述符
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83078.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83078.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83078.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第11篇:數據庫中間件系統可配置化設計與動態規則加載機制

11.1 引言&#xff1a;為什么需要可配置化&#xff1f; 數據庫中間件在企業級環境中往往需要支持多租戶、多業務場景、多數據庫后端&#xff0c;因此固定邏輯會迅速過時或僵化。 為了提升 靈活性、可擴展性、部署效率&#xff0c;中間件系統亟需實現&#xff1a; ? 高度可配置…

C++信號處理程序解析與改進

這個程序演示了如何使用sigaction來捕獲和處理信號&#xff08;特別是SIGINT&#xff0c;即CtrlC&#xff09;。以下是關鍵點和潛在問題的分析&#xff1a; 程序功能 信號捕獲&#xff1a;注冊自定義處理函數handler來捕獲信號2&#xff08;SIGINT&#xff0c;通常由CtrlC觸發…

Go爬蟲開發學習記錄

Go爬蟲開發學習記錄 基礎篇&#xff1a;使用net/http庫 Go的標準庫net/http提供了完善的HTTP客戶端功能&#xff0c;是構建爬蟲的基石&#xff1a; package mainimport ("fmt""io""net/http" )func fetchPage(url string) string {// 創建自定…

ubuntu 系統分區注意事項

ubuntu 系統分區大小&#xff0c;注意事項&#xff1a; 安裝ubuntu系統時&#xff0c;需要進行分區&#xff0c;手動分區時&#xff0c;有一點需要注意。一開始我也沒有注意&#xff0c;長時間使用后才發現的問題。 需要注意一點&#xff0c;如果不對 /usr 進行單獨分區&…

AI知識庫調用全攻略:四種實戰方法與技術實現

本文詳細解析AI如何調用知識庫解決實際問題&#xff0c;涵蓋四種核心調用方式&#xff08;直接檢索匹配、向量檢索生成、工具調用知識庫、多輪對話知識庫&#xff09;&#xff0c;附具體業務樣例與技術實現步驟&#xff0c;最后總結常見問題解決方案&#xff0c;助你快速搭建智…

WebRTC(一):整體架構

架構總覽 模塊劃分 媒體采集模塊 使用瀏覽器 API&#xff1a;getUserMedia()。采集攝像頭&#xff08;video&#xff09;、麥克風&#xff08;audio&#xff09;。通過 MediaStreamTrack 管理單軌道。 媒體處理與編解碼 編碼器&#xff08;發送端&#xff09;&#xff1a; …

商品中心—1.B端建品和C端緩存的技術文檔二

大綱 1.商品中心的專業術語 2.商品中心的基本業務系統 3.商品中心整體架構設計以及運行流程 4.商品B端—商品編碼生成邏輯 5.商品B端—商品核心數據模型 6.商品B端—轉換建品請求數據為商品模型數據 7.商品B端—商品建品時商品編號補全與審核配置 8.商品B端—商品審核前…

網絡之交換機

定義與作用 交換機是一種為所連接的IT設備提供網絡通信的設備&#xff0c;主要作用是轉發傳輸數據&#xff0c;實現網絡設備之間的通信互聯&#xff0c;還能對網絡進行分段和隔離&#xff0c;劃分多個虛擬網段&#xff0c;提高網絡安全性&#xff0c;以及對不同端口、用戶和應用…

AI不會殺死創作,但會殺死平庸

作為一個敲了8年Java代碼的普通本科程序員&#xff0c;日常主要泡在會議后臺管理系統的開發里。從2023年底被朋友拽著試了第一把AI工具到現在&#xff0c;電腦手機上的AI軟件比外賣App還多——寫代碼的Copilot、畫時序圖的工具、聊天的ChatGPT、Deepseek&#xff0c;基本市面上…

Golang——8、協程和管道

協程和管道 1、協程1.1、進程、線程和協程1.2、goroutine的使用以及sync.WaitGroup1.3、啟動多個協程1.4、設置Golang并行運行的時候占用的cup數量1.5、goroutine統計素數 2、管道2.1、管道的操作2.2、協程和管道協同2.3、單向管道2.4、多路復用之select2.5、解決協程中出現的異…

深入理解Python內置模塊及第三方庫的使用與管理

Python 內置模塊與第三方庫 在 Python 編程中&#xff0c;模塊和庫是幫助開發者高效實現各種功能的基礎工具。Python 提供了豐富的內置模塊以及第三方庫&#xff0c;能夠支持從基礎的文件操作到復雜的數據分析和機器學習等任務。本篇文章將深入介紹 Python 的內置模塊與第三方…

二分查找-P2249 【深基13.例1】查找

文章目錄 參考代碼二分標準模板 題目來源-洛谷網 參考代碼 #include<bits/stdc.h> using namespace std; const int N 1e65; int m,n,a[N],b; int find(int t) {int l1,rn;while(l<r){int mid(lr)/2;//防止溢出 mid l (r-l) /2 ;if(a[mid]>t) rmid;//中間值比…

手寫muduo網絡庫(一):項目構建和時間戳、日志庫

引言 本文作為手寫 muduo 網絡庫系列開篇&#xff0c;聚焦項目基礎框架搭建與核心基礎工具模塊設計。通過解析 CMake 工程結構設計、目錄規劃原則&#xff0c;結合時間戳與日志系統的架構&#xff0c;為后續網絡庫開發奠定工程化基礎。文中附完整 CMake 配置示例及模塊代碼。 …

NLP學習路線圖(三十二): 模型壓縮與優化

一、 核心壓縮與優化技術詳解 1. 知識蒸餾:智慧的傳承(Knowledge Distillation, KD) 核心思想:“師授徒業”。訓練一個龐大、高性能但笨重的“教師模型”(Teacher Model),讓其指導訓練一個輕量級的“學生模型”(Student Model)。學生模型學習模仿教師模型的輸出行為(…

vue前端字典映射

1.界面展示 2.圖中狀態字段接收的數據如下 3.代碼轉換&#xff0c;添加計算屬性代碼 再在綁定屬性的地方做轉換 computed: {statusMap() {return {"-1": "已退號",1: "掛號",2: "接診",3: "已完診",};},},<m-input:spa…

基于 llama-factory進行模型微調

# GLM4-9B-chat Lora 微調. 介紹如何基于 llama-factory 框架&#xff0c;對 glm-4-9b-chat 模型進行 Lora 微調。Lora 是一種高效微調方法&#xff0c;深入了解其原理可參見博客&#xff1a;[知乎|深入淺出 Lora](https://zhuanlan.zhihu.com/p/650197598)。 ## 環境配置 在完…

不到 2 個月,OpenAI 火速用 Rust 重寫 AI 編程工具。尤雨溪也覺得 Rust 香!

一、OpenAI 用 Rust 重寫 Codex CLI OpenAI 已用 Rust 語言重寫了其 AI 命令行編程工具 Codex CLI&#xff0c;理由是此舉能提升性能和安全性&#xff0c;同時避免對 Node.js 的依賴。他們認為 Node.js “可能讓部分用戶感到沮喪或成為使用障礙”。 Codex 是一款實驗性編程代理…

Go 并發編程深度指南

Go 并發編程深度指南 Go 語言以其內置的并發原語而聞名&#xff0c;通過 goroutine 和 channel 提供了一種高效、安全的并發編程模型。本文將全面解析 Go 的并發機制及其實際應用。 核心概念&#xff1a;Goroutines 和 Channels 1. Goroutines (協程) Go 的輕量級線程實現&…

vue和uniapp聊天頁面右側滾動條自動到底部

1.vue右側滾動條自動到底部 <div ref"newMessage1"></div> <!-- 定義<div ref"newMessage1"></div>與<div v-for”item in list“>循環同級定義-->定義方法 scrollToBottomCenter(){this.$nextTick(() > {this.$re…

iOS 項目怎么構建穩定性保障機制?一次系統性防錯經驗分享(含 KeyMob 工具應用)

崩潰、內存飆升、后臺任務未釋放、頁面卡頓、日志丟失——穩定性問題&#xff0c;不一定會立刻崩&#xff0c;但一旦積累&#xff0c;就是“上線后救不回來的代價”。 穩定性保障不是某個工具的功能&#xff0c;而是一套貫穿開發、測試、上線全流程的“觀測分析防范”機制。 …