核心proc檔案系統與seq介面(3)---核心proc檔案底層結構淺析
前面講了proc檔案系統的程式設計,其實在使用API的時候注意一下proc檔案系統的實現也是很有益處的。在學習使用proc的時候我順便看了一下proc的底層實現,發現原理非常簡單,畢竟是一個基於記憶體的檔案系統。
首先眾所周知,所有的檔案系統都位於VFS的層,proc也不例外。在核心啟動的時,start_kernel在完成了VFS的初始化不久就呼叫了:
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
用於初始化proc檔案系統:
fs/proc/root.c
void __init proc_root_init(void)
{
struct vfsmount *mnt;
int err;
proc_init_inodecache();
err = register_filesystem(&proc_fs_type); //向VFS註冊procfs
if (err)
return;
mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
if (IS_ERR(mnt)) {
unregister_filesystem(&proc_fs_type);
return;
}
init_pid_ns.proc_mnt = mnt;
proc_symlink("mounts", NULL, "self/mounts"); //建立“mounts”符號連線檔案
proc_net_init(); //建立“net”符號連線及內部目錄樹結構
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL); //建立“sysvipc”目錄
#endif
proc_mkdir("fs", NULL); //建立“fs”目錄
proc_mkdir("driver", NULL); //建立“driver”目錄
proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
/* just give it a mountpoint */
proc_mkdir("openprom", NULL);
#endif
proc_tty_init(); //建立“tty”目錄及內部結構
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
proc_mkdir("bus", NULL); //建立“bus”目錄
proc_sys_init(); //建立“sys”目錄並初始化
}
在這之後,許多核心元件和模組就可以向proc檔案系統及其子目錄新增目錄和檔案了。其中最重要的資料結構體就是:struct proc_dir_entry,她在《核心proc檔案系統與seq介面(2)---核心proc檔案系統程式設計介面》介紹過。她相當於proc檔案系統中的資料節點,procfs中許多檔案、符號連線和目錄檔案都是由她表示的。但是請注意,並不是左右的proc檔案都對應這樣的資料結構,對於/proc/sys、/proc/${PID}/等特定目錄下的檔案時需要時動態生成的,有其自己的內部實現。而這個proc_dir_entry只對普通的proc檔案實現,及我們自己建立的proc檔案。
其根目錄的表示:
fs/proc/root.c
/*
* This is the root "inode" in the /proc tree..
*/
struct proc_dir_entry proc_root = {
.low_ino = PROC_ROOT_INO,
.namelen = 5,
.name = "/proc",
.mode = S_IFDIR | S_IRUGO | S_IXUGO,
.nlink = 2,
.count = ATOMIC_INIT(1),
.proc_iops = &proc_root_inode_operations,
.proc_fops = &proc_root_operations,
.parent = &proc_root,
};
除了這個節點的結構體在程式碼中靜態定義的之外,其他所有的節點都是系統和模組初始化產生的。也除了這個節點的mane字串是在核心映像的只讀資料段中,其他的節點的name字串都是在建立的時候緊跟在其struct proc_dir_entry之後的,如下圖:
而看了原始碼(fs/proc/generic.c)你就會很快的瞭解這個檔案系統的資料連線方式:用*next指標通過單向連結串列連線同目錄下檔案;用*parent指標指向父目錄的proc_dir_entry結構體;用*subdir指標指向本目錄中的檔案(如果這個檔案目錄的話),總體底層結構示意圖如下所示:
上圖只是一個結構示意圖,一些指標的指向不確定的,比如proc_root的*subdir肯定不是指向sys,因為初始化之後還有很多目錄和檔案要產生。但是/root目錄下單向連結串列的最後一個應該是mounts,因為他是最早註冊的(起碼在3.0上是這樣)。上圖同時示意了符號連線註冊後的一般情況。
對於一個目錄註冊後的一般如下,主要是注意*proc_iops inode操作函式和*proc_fops 檔案操作函式的註冊:
在《核心proc檔案系統與seq介面(2)---核心proc檔案系統程式設計介面》中曾經介紹過,對於建立 /proc 入口,有兩種選擇:
(1)使用proc的預設操作函式集proc_file_operations,但必須實現回撥函式*read_proc和*write_proc,示意圖如下:
(2)使用自己實現的file_operations,以下用/proc/config.gz檔案的實現做示意:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以上的解析只是對procfs的淺析,有興趣的朋友可以自己看看fs/proc/generic.c,非常簡單的檔案系統實現,是一個很好的學習樣本。RTFSC – Read The Fucking Source Code。
相關文章
- 【/proc/檔案淺析】另類辦法恢復資料檔案和控制檔案
- proc-macro-workshop:seq-3Mac
- 檔案包含之/proc/self/environ
- proc_create_data函式建立/proc/目錄下的檔案函式
- 跟我一起學.NetCore之檔案系統應用及核心淺析NetCore
- proc-macro-workshop:seq-1Mac
- proc-macro-workshop:seq-2Mac
- proc-macro-workshop:seq-4Mac
- proc-macro-workshop:seq-5Mac
- proc-macro-workshop:seq-6Mac
- proc-macro-workshop:seq-7Mac
- proc-macro-workshop:seq-8Mac
- proc-macro-workshop:seq-9Mac
- Linux中proc檔案系統是什麼意思?有什麼作用?Linux
- 圖解gzip壓縮檔案底層結構及檔案損壞的修復方法圖解
- linux 程式引數檔案 /proc/pid/cmdline 簡介Linux
- 基於常量值提取淺析elf檔案結構
- 核心必須懂(二): 檔案系統初探
- Linux核心檔案Linux
- Linux 核心101:虛擬檔案系統的使命Linux
- LiteOS-A核心中的procfs檔案系統分析
- 小白自制Linux開發板 三. Linux核心與檔案系統移植Linux
- 作業系統核心結構作業系統
- 二、Linux檔案系統結構Linux
- Linux核心啟動之根檔案系統掛載Linux
- 鴻蒙輕核心原始碼分析:檔案系統LittleFS鴻蒙原始碼
- 【核心檔案系統】原始碼閱讀stat.h原始碼
- 淺析三款大規模分散式檔案系統架構設計分散式架構
- 根檔案系統簡介與BusyBox構建根檔案系統
- Linux下的檔案系統結構Linux
- 檔案系統的物理結構分配
- Linux檔案系統目錄結構Linux
- 核心模組建立檔案
- 淺析Spring Security 核心元件Spring元件
- Android 檔案儲存淺析Android
- 淺析檔案上傳漏洞
- 淺嘗Node檔案系統
- PE檔案結構解析3