核心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虛擬檔案系統與系統核心引數修改方法
- Linux核心模組程式設計/proc 檔案系統(轉)Linux程式設計
- 理解 Proc 檔案系統(轉)
- 【/proc/檔案淺析】另類辦法恢復資料檔案和控制檔案
- proc檔案系統相關內容
- Linux/proc檔案系統操作指南Linux
- 【AIX 學習】檔案系統之 PROCAI
- 使用 /proc 檔案系統來控制系統(轉)
- 使用 /proc 檔案系統來控制系統 (zt)
- Linux系統下/proc/[pid] 目錄各檔案簡析Linux
- proc-macro-workshop:seq-3Mac
- <解說linux下proc檔案系統>Linux
- linux /proc/cpuinfo檔案分析LinuxUI
- 檔案包含之/proc/self/environ
- 深入理解linux系統下proc檔案系統內容Linux
- proc_create_data函式建立/proc/目錄下的檔案函式
- /proc/sysrq-trigger檔案
- 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
- Solaris核心proc目錄簡介(轉)
- linux proc 檔案系統下 entry 的解釋(轉)Linux
- 圖解gzip壓縮檔案底層結構及檔案損壞的修復方法圖解
- 跟我一起學.NetCore之檔案系統應用及核心淺析NetCore
- 驅動載入到proc檔案下
- Linux中proc檔案系統是什麼意思?有什麼作用?Linux
- 簡單案例教你用PROC檔案系統獲取程式資訊薦
- linux /proc/sys/vm下核心引數解析Linux
- Linux中/proc目錄下檔案詳解Linux
- Linux /proc 目錄下檔案粗談(轉)Linux
- Linux如何在系統執行時修改核心引數(/proc/sys 與 /etc/sysctl.conf)Linux
- 核心必須懂(二): 檔案系統初探
- 淺析 Linux 的共享記憶體與 tmpfs 檔案系統Linux記憶體