首頁/ 汽車/ 正文

深度講解Linux proc檔案系統介紹

最初開發/proc檔案系統是為了提供有關係統中程序的資訊。但是由於這個檔案系統非常有用,因此核心中的很多元素也開始使用它來報告資訊,或啟用動態執行時配置。

/proc檔案系統包含了一些目錄(用作組織資訊的方式)和虛擬檔案。虛擬檔案可以向用戶呈現核心中的一些資訊,也可以用作一種從使用者空間向核心傳送資訊的手段。實際上我們並不會同時需要實現這兩點,但是本文將向您展示如何配置這個檔案系統進行輸入和輸出。

儘管像本文這樣短小的一篇文章無法詳細介紹/proc的所有用法,但是它依然對這兩種用法進行了展示,從而可以讓我們體會一下/proc是多麼強大。圖1是對/proc中部分元素進行一次互動查詢的結果。它顯示的是/proc檔案系統的根目錄中的內容。注意,在左邊是一系列數字編號的檔案。每個實際上都是一個目錄,表示系統中的一個程序。由於在GNU/Linux中建立的第一個程序是init程序,因此它的process-id為1。然後對這個目錄執行一個 ls命令,這會顯示很多檔案。每個檔案都提供了有關這個特殊程序的詳細資訊。例如,要檢視init的command-line項的內容,只需對cmdline檔案執行cat命令。

深度講解Linux proc檔案系統介紹

/proc中另外一些有趣的檔案有:cpuinfo,它標識了處理器的型別和速度;pci:顯示在PCI總線上找到的裝置;modules:標識了當前載入到核心中的模組。

圖2展示了對/proc中的一個虛擬檔案進行讀寫的過程。這個例子首先檢查核心的TCP/IP棧中的IP轉發的目前設定,然後再啟用這種功能。

深度講解Linux proc檔案系統介紹

另外,我們還可以使用sysctl來配置這些核心條目。

順便說一下,/proc檔案系統並不是GNU/Linux系統中的惟一一個虛擬檔案系統。在這種系統上,sysfs是一個與/proc類似的檔案系統,但是它的組織更好(從 /proc 中學習了很多教訓)。不過 /proc 已經確立了自己的地位,因此即使sysfs與/proc相比有一些優點,/proc也依然會存在。還有一個debugfs檔案系統,不過(顧名思義)它提供的更多是除錯介面。debugfs的一個優點是它將一個值匯出給使用者空間非常簡單(實際上這不過是一個呼叫而已)。

更多linux核心影片教程文件資料免費領取後臺私信

【核心】

自行獲取。

深度講解Linux proc檔案系統介紹

Linux核心原始碼/記憶體調優/檔案系統/程序管理/裝置驅動/網路協議棧-學習影片教程-騰訊課堂

/proc目錄下常見的檔案介紹:

/proc/apm

高階電源管理(APM)版本資訊及電池相關狀態資訊,通常由apm命令使用;

proc/buddyinfo

用於診斷記憶體碎片問題的相關資訊檔案;

/proc/cmdline

在啟動核心時傳遞至核心的相關引數資訊,這些資訊通常由lilo或grub等啟動管理工具進行傳遞;

深度講解Linux proc檔案系統介紹

/proc/cpuinfo

處理器的相關資訊的檔案;

/proc/crypto

系統上已安裝的核心使用的密碼演算法及每個演算法的詳細資訊列表;

/proc/devices

系統已經載入的所有塊裝置和字元裝置的資訊,包含主裝置號和裝置組(與主裝置號對應的裝置型別)名;

/proc/dma

每個正在使用且註冊的ISA DMA通道的資訊列表;

/proc/fb

幀緩衝裝置列表檔案,包含幀緩衝裝置的裝置號和相關驅動資訊;

/proc/filesystems

當前被核心支援的檔案系統型別列表檔案,被標示為nodev的檔案系統表示不需要塊裝置的支援;通常mount一個裝置時,如果沒有指定檔案系統型別將透過此檔案來決定其所需檔案系統的型別;

/proc/interrupts

ARM體系架構系統上每個IRQ相關的中斷號列表;

深度講解Linux proc檔案系統介紹

/proc/iomem

每個物理裝置上的記憶體(RAM或者ROM)在系統記憶體中的對映資訊;

/proc/kmsg

此檔案用來儲存由核心輸出的資訊,通常由/sbin/klogd或/bin/dmsg等程式使用,不要試圖使用檢視命令開啟此檔案;

/proc/meminfo

系統中關於當前記憶體的利用狀況等的資訊,常由free命令使用;可以使用檔案檢視命令直接讀取此檔案,其內容顯示為兩列,前者為統計屬性,後者為對應的值;

/proc/modules

當前裝入核心的所有模組名稱列表,可以由lsmod命令使用,也可以直接檢視;如下所示,其中第一列表示模組名,第二列表示此模組佔用記憶體空間大小,第三列表示此模組有多少例項被裝入,第四列表示此模組依賴於其它哪些模組,第五列表示此模組的裝載狀態(Live:已經裝入;Loading:正在裝入;Unloading:正在解除安裝),第六列表示此模組在核心記憶體(kernel memory)中的偏移量;

/proc/partitions

塊裝置每個分割槽的主裝置號(major)和次裝置號(minor)等資訊,同時包括每個分割槽所包含的塊(block)數目,如下圖所示;

深度講解Linux proc檔案系統介紹

/proc/slabinfo

在核心中頻繁使用的物件(如inode、dentry等)都有自己的cache,即slab pool,而/proc/slabinfo檔案列出了這些物件相關slap的資訊;詳情可以參見核心文件中slapinfo的手冊頁;

/proc/uptime

系統上次啟動以來的執行時間,如下所示,其第一個數字表示系統執行時間,第二個數字表示系統空閒時間,單位是秒;

深度講解Linux proc檔案系統介紹

/proc/version

當前系統執行的核心版本號,如下所示;

深度講解Linux proc檔案系統介紹

/proc/zoneinfo

記憶體區域(zone)的詳細資訊列表,資訊量較大;

要在/proc檔案系統中建立一個虛擬檔案,請使用proc_create()或proc_create_data()函式。這個函式可以接收一個檔名、一組許可權和這個檔案在/proc檔案系統中出現的位置。這兩個函式的返回值是一個proc_dir_entry型別指標(或者為NULL,說明在發生了錯誤時)。然後就可以使用這個返回的指標來配置這個虛擬檔案的其他引數,例如在對該檔案執行讀操作時應該呼叫的函式。函式的原型和proc_dir_entry結構中的一部分如下圖所示。

struct proc_dir_entry { /* * number of callers into module in progress; * negative -> it‘s going away RSN */ atomic_t in_use; atomic_t count; /* use count */ struct list_head pde_openers; /* who did ->open, but not ->release */ /* protects ->pde_openers and all struct pde_opener instances */ spinlock_t pde_unload_lock; struct completion *pde_unload_completion; const struct inode_operations *proc_iops; //Inode operations functions const struct file_operations *proc_fops; //File operations functions void *data; //私有資料指標,在操作函式中可以使用的到 unsigned int low_ino; nlink_t nlink; kuid_t uid; //檔案的user id kgid_t gid; //檔案的group id loff_t size; struct proc_dir_entry *parent; //父目錄 struct rb_root_cached subdir; struct rb_node subdir_node; umode_t mode; //訪問許可權 u8 namelen; char name[]; //建立的虛擬檔案或目錄名} __randomize_layout; struct proc_dir_entry *proc_create(const char *name, umode_t mode,struct proc_dir_entry *parent,const struct file_operations *proc_fops);struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,struct proc_dir_entry *parent,const struct file_operations *proc_fops,void *data);

建立目錄的函式原型如下:

struct proc_dir_entry *proc_mkdir(const char *name,struct proc_dir_entry *parent);struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,struct proc_dir_entry *parent, void *data);

前者不可以傳入私有資料,後者可以。關於私有資料的操作,我們後面會使用一個例子來說明。

要從/proc中刪除一個檔案,可以使用remove_proc_entry()函式。要使用這個函式,我們需要提供檔名字串,以及這個檔案在/proc檔案系統中的位置(parent)。函式原型如下:

void remove_proc_entry(const char *name, struct proc_dir_entry *parent);

當在/proc檔案系統下建立檔案之後使用者是怎麼訪問這個檔案的,其實看到proc_create()函式的最後一個引數,傳入的是一個file_operations結構體指標,其實,就是透過裡面的read和write回撥函式來實現的。下面我們來看一個具體的例子。

在/proc目錄下建立hello_proc檔案,並往裡面寫入資料或獲取裡面的資料。

#include #include #include #include #include #include #include #include #include /* 定義一個proc_dir_entry結構體型別變數*/struct proc_dir_entry *hello_proc = NULL;/* 定義一個全域性資料,用來儲存使用者空間返回的資料 */static char hello_data[20] = {}; /* 如果使用cat此節點,則傳入的count為4K,直到讀取的資料大小為4K,也就是直到此函式返回0 當此函式返回0時,讀取到的內容是不顯示的。 */static ssize_t hello_proc_read(struct file *fp, char __user *user_buf, size_t count, loff_t *ppos){ int ret = 0; /* 首先清空使用者空間的user_buf地址的內容,有可能顯示雜亂資訊 */ if (clear_user(user_buf, count)) { printk(KERN_ERR “clear error\n”); return -EIO; } /* 從hello_data陣列中讀取資料到使用者空間user_buf,讀取的長度應該是字串的大小 */ ret = simple_read_from_buffer(user_buf, count, ppos, hello_data, strlen(hello_data)); return ret;} /* 使用者空間使用echo往此節點寫入資料,只有要寫入的資料寫完之後,也就是返回count是,此函式此不會被呼叫*/static ssize_t hello_proc_write(struct file *fp, const char __user *user_buf, size_t count, loff_t *ppos){ int ret; printk(“hello_proc_write:count is %d。\n”,count); /* 寫入資料之前,將陣列清空 */ memset(hello_data,0,sizeof(hello_data)); /* 將使用者空間寫入的資料儲存到資料中 */ ret = simple_write_to_buffer(hello_data, sizeof(hello_data),ppos,user_buf,count); printk(“hello_proc_write:ret is %d。\n”,ret); printk(“hello_proc_write:user_buf is %s”,hello_data); /* 返回使用者空間寫入字串的大小 */ return count;} /* 定義一個file_operations結構體變數 */ static const struct file_operations hello_proc_fops = { 。owner = THIS_MODULE, 。read = hello_proc_read, //使用cat時的回撥函式 。write = hello_proc_write, //使用echo時的回撥函式}; /* 驅動入口函式 */static int __init proc_test_init(void){ /* 呼叫proc_create()函式建立“hello_proc”檔案 */ hello_proc = proc_create(“hello_proc”, 0,NULL,&hello_proc_fops); return 0;} /* 驅動出口函式 */static void __exit proc_test_exit(void){ /* 刪除此檔案 */ if(hello_proc) remove_proc_entry(“hello_proc”, NULL);} module_init(proc_test_init);module_exit(proc_test_exit);MODULE_LICENSE(“GPL”);MODULE_DESCRIPTION(“proc filesystem test by Haitao Cai”);

將此檔案上傳到伺服器並編譯模組,然後將此模組上傳到開發板上面。

生成的節點如下:

深度講解Linux proc檔案系統介紹

cat /proc/hello_proc的輸出資訊如下:

深度講解Linux proc檔案系統介紹

echo hello > /proc/hello_proc的輸出資訊如下:

深度講解Linux proc檔案系統介紹

再次cat /proc/hello_proc的輸出資訊如下:

深度講解Linux proc檔案系統介紹

在使用proc_create()函式建立檔案時,第二個引數是關於許可權的設定,我們這裡使用預設的0,也就是隻有讀取許可權,這裡就不再詳細介紹,如果感興趣可以自己做實驗。

導讀-最新發表 - 核心技術中文網 - 構建全國最權威的核心技術交流分享論壇

轉載地址:深度講解Linux proc檔案系統介紹 - 圈點 - 核心技術中文網 - 構建全國最權威的核心技術交流分享論壇

深度講解Linux proc檔案系統介紹

相關文章

頂部