自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux內(nèi)核中的proc文件系統(tǒng)

系統(tǒng) Linux
procfs文件系統(tǒng)是內(nèi)核中的一個(gè)特殊文件系統(tǒng)。它是一個(gè)虛擬文件系統(tǒng): 它不是實(shí)際的存儲(chǔ)設(shè)備中的文件,而是存在于內(nèi)存中。procfs中的文件是用來(lái)允許用戶(hù)空間的程序訪(fǎng)問(wèn)內(nèi)核中的某些信息(比如進(jìn)程信息在 /proc/[0-9]+/中),或者用來(lái)做調(diào)試用途(/proc/ksyms,這個(gè)文件列出了已經(jīng)登記的內(nèi)核符號(hào),這些符號(hào)給出了變量或函數(shù)的地址。每行給出一個(gè)符號(hào)的地址,符號(hào)名稱(chēng)以及登記這個(gè)符號(hào)的模塊。

Linux內(nèi)核中的proc文件系統(tǒng)

簡(jiǎn)介

procfs文件系統(tǒng)是內(nèi)核中的一個(gè)特殊文件系統(tǒng)。它是一個(gè)虛擬文件系統(tǒng): 它不是實(shí)際的存儲(chǔ)設(shè)備中的文件,而是存在于內(nèi)存中。procfs中的文件是用來(lái)允許用戶(hù)空間的程序訪(fǎng)問(wèn)內(nèi)核中的某些信息(比如進(jìn)程信息在 /proc/[0-9]+/中),或者用來(lái)做調(diào)試用途(/proc/ksyms,這個(gè)文件列出了已經(jīng)登記的內(nèi)核符號(hào),這些符號(hào)給出了變量或函數(shù)的地址。每行給出一個(gè)符號(hào)的地址,符號(hào)名稱(chēng)以及登記這個(gè)符號(hào)的模塊。程序ksyms、insmod和kmod使用這個(gè)文件。它還列出了正在運(yùn)行的任務(wù)數(shù),總?cè)蝿?wù)數(shù)和***分配的PID。)

這個(gè)文檔描述了內(nèi)核中procfs文件系統(tǒng)的使用。它以介紹所有和管理文件系統(tǒng)相關(guān)的函數(shù)開(kāi)始。在函數(shù)介紹后,它還展示了怎么和用戶(hù)空間通信,和一些小技巧。在文檔的***,還給出了一個(gè)完整的例子。

注意/proc/sys中的文件屬于sysctl文件,它們不屬于procfs文件系統(tǒng),被另外一套完全不同的api管理。

seq_file

procfs在處理大文件時(shí)有點(diǎn)笨拙。為了清理procfs文件系統(tǒng)并且使內(nèi)核編程簡(jiǎn)單些,引入了seq_file機(jī)制。seq_file機(jī)制提供了大量簡(jiǎn)單的接口去實(shí)現(xiàn)大內(nèi)核虛擬文件。

seq_file機(jī)制適用于你利用結(jié)構(gòu)序列去創(chuàng)建一個(gè)返回給用戶(hù)空間的虛擬文件。要使用seq_file機(jī)制,你必須創(chuàng)建一個(gè)”iterator”對(duì)象,這個(gè)對(duì)象指向這個(gè)序列,并且能逐個(gè)指向這個(gè)序列中的對(duì)象,此外還要能輸出這個(gè)序列中的任一個(gè)對(duì)象。它聽(tīng)起來(lái)復(fù)雜,實(shí)際上,操作過(guò)程相當(dāng)簡(jiǎn)單。接下來(lái)將用實(shí)際的例子展示到底怎么做。

首先,你必須包含頭文件<Linux/seq_file.h>。接下來(lái),你必須創(chuàng)建迭代器方法:start, next, stop, and show。

start方法通常被首先調(diào)用。這個(gè)方法的函數(shù)原型是:

  1. void *start(struct seq_file *sfile, loff_t *pos); 

sfile沒(méi)什么作用,通常被忽略。pos參數(shù)是一個(gè)整型,表示從哪個(gè)位置開(kāi)始讀。關(guān)于位置的定義完全取決于函數(shù)實(shí)現(xiàn);它不一定要是結(jié)果文件中的一個(gè)字節(jié)位置。 由于seq_file機(jī)制通常是利用一個(gè)特定的結(jié)構(gòu)序列實(shí)現(xiàn)的,所以位置通常是一個(gè)指向序列中下一個(gè)結(jié)構(gòu)體的指針。在wing驅(qū)動(dòng)中,每一個(gè)設(shè)備表示序列中的一個(gè)結(jié)構(gòu),所以,入?yún)os代表g_pstWingDevices數(shù)組的索引。因此,在wing驅(qū)動(dòng)中start方法的實(shí)現(xiàn)為:

  1. static void *wing_seq_start(struct seq_file *s, loff_t *pos) 
  2.     if (*pos >= g_iWingDevicesNum) 
  3.         return NULL; /* No more to read */ 
  4.     return g_pstWingDevices + *pos; 

 

返回值如果不為NULL,代表一個(gè)可以被迭代器使用的私有數(shù)據(jù)。

next函數(shù)應(yīng)該移動(dòng)迭代器到下一個(gè)位置,如果序列中沒(méi)有數(shù)據(jù),返回NULL。這個(gè)方法的函數(shù)原型為:

  1. void *next(struct seq_file *sfile, void *v, loff_t *pos); 

這里,參數(shù)v代表上一個(gè)函數(shù)調(diào)用(可能是start函數(shù),或者是next函數(shù))返回的迭代器,, 參數(shù)pos是文件中的當(dāng)前位置。next函數(shù)應(yīng)該改變pos的指向,具體是逐步改變還是跳躍改變?nèi)Q于迭代器的工作機(jī)制。next函數(shù)在wing驅(qū)動(dòng)中的實(shí)現(xiàn)為:

  1. static void* wing_seq_next(struct seq_file *s, void *v, loff_t *pos) 
  2.     (*pos)++; 
  3.     if (*pos >= g_iWingDevicesNum) 
  4.         return NULL
  5.     return g_pstWingDevices + *pos; 

 

當(dāng)內(nèi)核停止了迭代器的工作,它調(diào)用stop函數(shù)清理現(xiàn)場(chǎng):

  1. void stop(struct seq_file *sfile, void *v); 

wing驅(qū)動(dòng)沒(méi)有清理工作要做,所以stop函數(shù)為空。

  1. void wing_seq_stop(struct seq_file *sfile, void *v) 

 

要是seq_file代碼在調(diào)用start和stop時(shí)不執(zhí)行睡眠或是非原子的操作,那么這種機(jī)制將毫無(wú)意義。你要保證從start函數(shù)調(diào)用到stop函數(shù)調(diào)用是很短暫的。因此,在開(kāi)始函數(shù)中獲得一個(gè)信號(hào)量或者自旋鎖是比較安全的做法。要是seq_file其他方法是原子的,整個(gè)調(diào)用鏈必須是原子的。

在這些函數(shù)調(diào)用中,內(nèi)核調(diào)用call函數(shù)向內(nèi)核空間輸出特性的信息。這個(gè)函數(shù)的函數(shù)原型是:

  1. int show(struct seq_file *sfile, void *v); 

這個(gè)方法應(yīng)該創(chuàng)建序列中由指示器v指定項(xiàng)的輸出。不能使用printk,而是使用以下這些特定函數(shù):

  1. int seq_printf(struct seq_file *sfile, const char *fmt, ...) 

這個(gè)函數(shù)是seq_file機(jī)制中類(lèi)似于printf的實(shí)現(xiàn);它使用通常的格式字符串和參數(shù)組成輸出字符串。你必須把show函數(shù)中的seq_file結(jié)構(gòu)體傳給這個(gè)函數(shù)。如果它返回一個(gè)非零的值,表示buffer已經(jīng)填充好,輸出被丟出去了。在大多數(shù)實(shí)現(xiàn)中,都選擇忽略返回值。

  1. int seq_putc(struct seq_file *sfile, char c); 
  2.  
  3. int seq_puts(struct seq_file *sfile, const char *s); 

 

這兩個(gè)函數(shù)相當(dāng)于用戶(hù)層的putc和puts。

  1. int seq_escape(struct seq_file *m, const char *s, const char *esc); 

這個(gè)函數(shù)是 seq_puts 的對(duì)等體, 除了 s 中的任何也在 esc 中出現(xiàn)的字符以八進(jìn)制格式打印. esc 的一個(gè)通用值是”\t\n\”, 它使內(nèi)嵌的空格不會(huì)搞亂輸出和可能搞亂 shell 腳本.

  1. int seq_path(struct seq_file *sfile, struct vfsmount *m, struct dentry *dentry, char *esc); 

這個(gè)函數(shù)能夠用來(lái)輸出和給定命令項(xiàng)關(guān)聯(lián)的文件名子. 它在設(shè)備驅(qū)動(dòng)中不可能有用;我們是為了完整在此包含它.

wing設(shè)備中的show函數(shù)例子:

  1. static int wing_seq_show(struct seq_file *s, void *v) 
  2.  
  3.  
  4.     ST_Wing_Dev_Type* pDev = (ST_Wing_Dev_Type* ) v; 
  5.  
  6.     seq_printf(s, "\nThis Device is %i\n", pDev->iData); 
  7.  
  8.     return 0; 
  9.  

 

在我的例子中,我將一個(gè)ST_Wing_Dev_Type結(jié)構(gòu)體表示為迭代器。

上面就是完整的迭代器操作,wing驅(qū)動(dòng)必須將它們打包到一起好連接到procfs文件系統(tǒng)。首先要做的就是利用它們組成一個(gè)seq_operations結(jié)構(gòu)體:

  1. static struct seq_operations s_stWingSeqOps = { 
  2.  
  3.     .start = wing_seq_start, 
  4.  
  5.     .next = wing_seq_next, 
  6.  
  7.     .stop = wing_seq_stop, 
  8.  
  9.     .show = wing_seq_show 
  10.  
  11. }; 

 

有了這個(gè)結(jié)構(gòu),我們必須創(chuàng)建一個(gè)內(nèi)核能理解的文件實(shí)現(xiàn)。我們不使用前面說(shuō)過(guò)的read_proc方法;在使用seq_file時(shí), ***在一個(gè)稍低的級(jí)別上連接到procfs。這意味著創(chuàng)建一個(gè)file_operations(和字符設(shè)備一樣的結(jié)構(gòu)),這個(gè)結(jié)構(gòu)實(shí)現(xiàn)了內(nèi)核對(duì)文件的reads和seeks操作。幸運(yùn)的是,這個(gè)操做很簡(jiǎn)單。首先創(chuàng)建一個(gè)把文件和seq_file方法聯(lián)接起來(lái)的open方法:

  1. static int wing_proc_open(struct inode *inode, struct file *file) 
  2.     return seq_open(file, &s_stWingSeqOps); 

 

調(diào)用seq_open函數(shù)的時(shí)候?qū)⑽募蜕厦娑x的序列操作關(guān)聯(lián)到一起。open是唯一要我們實(shí)現(xiàn)的函數(shù)接口,所以我們的file_operations結(jié)構(gòu)體是:

  1. static struct file_operations s_stWingProcFops = { 
  2.     .owner = THIS_MODULE, 
  3.     .open = wing_proc_open, 
  4.     .read = seq_read, 
  5.     .llseek = seq_lseek, 
  6.     .release = seq_release 
  7. }; 

 

***我們要在procfs文件系統(tǒng)中創(chuàng)建文件:

  1. proc_create("wingdevices", 0644, NULL, &s_stWingProcFops); 

關(guān)鍵結(jié)構(gòu)體

struct proc_dir_entry代表的是/proc目錄下的一個(gè)目錄或者文件,他是procfs文件系統(tǒng)的主要結(jié)構(gòu)體,它的定義在/fs/internal.h中:

  1. /* 
  2.  * This is not completely implemented yet. The idea is to 
  3.  * create an in-memory tree (like the actual /proc filesystem 
  4.  * tree) of these proc_dir_entries, so that we can dynamically 
  5.  * add new files to /proc. 
  6.  * 
  7.  * The "next" pointer creates a linked list of one /proc directory, 
  8.  * while parent/subdir create the directory structure (every 
  9.  * /proc file has a parent, but "subdir" is NULL for all 
  10.  * non-directory entries). 
  11.  */ 
  12. struct proc_dir_entry { 
  13.     unsigned int low_ino; 
  14.     umode_t mode; 
  15.     nlink_t nlink; 
  16.     kuid_t uid; 
  17.     kgid_t gid; 
  18.     loff_t size
  19.     const struct inode_operations *proc_iops; 
  20.     const struct file_operations *proc_fops; 
  21.     struct proc_dir_entry *next, *parent, *subdir; 
  22.     void *data; 
  23.     atomic_t count;     /* use count */ 
  24.     atomic_t in_use;    /* number of callers into module in progress; */ 
  25.             /* negative -> it's going away RSN */ 
  26.     struct completion *pde_unload_completion; 
  27.     struct list_head pde_openers;   /* who did ->open, but not ->release */ 
  28.     spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ 
  29.     u8 namelen; 
  30.     char name[]; 
  31. }; 

 

主要接口

procfs應(yīng)該包含的頭文件<linux/proc_fs.h>。

在3.x內(nèi)核中procfs主要接口有:

  • proc_symlink
  • proc_mkdir
  • proc_mkdir_data
  • proc_mkdir_mode
  • proc_create_data
  • proc_create
  • proc_set_size
  • proc_set_user
  • PDE_DATA
  • proc_get_parent_data
  • proc_remove
  • remove_proc_entry
  • remove_proc_subtree

proc_mkdir

說(shuō)明:在/proc下創(chuàng)建目錄

函數(shù)原型:

  1. struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) 

參數(shù):

  • name

要?jiǎng)?chuàng)建的目錄名稱(chēng)

  • parent

父目錄,如果為NULL,表示直接在/proc下面創(chuàng)建目錄。

proc_mkdir_data

說(shuō)明:在/proc下創(chuàng)建目錄

函數(shù)原型:

  1. struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, struct proc_dir_entry *parent, void *data) 

參數(shù):

  • name

要?jiǎng)?chuàng)建的目錄名稱(chēng)

  • mode

指定要?jiǎng)?chuàng)建目錄的權(quán)限

  • parent

父目錄,如果為NULL,表示直接在/proc下面創(chuàng)建目錄。

  • data

proc_create_data

說(shuō)明:創(chuàng)建proc虛擬文件系統(tǒng)文件

函數(shù)原型:

 

  1. 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) 

 

參數(shù):

  • name

你要?jiǎng)?chuàng)建的文件名。

  • mode

為創(chuàng)建的文件指定權(quán)限

  • parent

為你要在哪個(gè)文件夾下建立名字為name的文件,如:init_net.proc_net是要在/proc/net/下建立文件。

  • proc_fops

為struct file_operations

  • data

保存私有數(shù)據(jù)的指針,如不要為NULL。

例子:

  1. ////////////////////////test.c//////////////////////////////////////// 
  2. #include <linux/init.h>   
  3. #include <linux/module.h>   
  4. #include <linux/types.h>   
  5. #include <linux/slab.h>   
  6. #include <linux/fs.h>   
  7. #include <linux/proc_fs.h>   
  8. #include <linux/seq_file.h>   
  9. #include <net/net_namespace.h>   
  10. #include <linux/mm.h>   
  11.  
  12. MODULE_LICENSE("GPL");   
  13.  
  14. typedef struct {       
  15.     int data1;       
  16.     int data2;   
  17. }ST_Data_Info_Type;   
  18.  
  19.  
  20. static ST_Data_Info_Type g_astDataInfo[2];   
  21.  
  22.  
  23.  
  24. static int test_proc_show(struct seq_file *m, void *v) 
  25.     ST_Data_Info_Type* pInfo = (ST_Data_Info_Type*)m->private; 
  26.     if(pInfo != NULL
  27.     { 
  28.         seq_printf(m, "%d----%d\n", pInfo->data1, pInfo->data2); 
  29.     } 
  30.     return 0; 
  31.  
  32.  
  33. static int test_proc_open(struct inode *inode, struct file *file)  
  34. {   
  35.     return single_open(file, test_proc_show, PDE_DATA(inode)); 
  36. }   
  37.  
  38.  
  39. static const struct file_operations dl_file_ops = {       
  40.     .owner = THIS_MODULE,       
  41.     .open    = test_proc_open, 
  42.     .read    = seq_read, 
  43.     .llseek  = seq_lseek, 
  44.     .release = single_release, 
  45. };   
  46.  
  47. static struct proc_dir_entry *s_pstRootTestDir; 
  48.  
  49.  
  50. void init_mem(void)   
  51. {      
  52.     /* create /proc/test */ 
  53.     s_pstRootTestDir = proc_mkdir("test"NULL); 
  54.     if (!s_pstRootTestDir) 
  55.         return
  56.  
  57.     g_astDataInfo[0].data1=1;       
  58.     g_astDataInfo[0].data2=2;   
  59.     proc_create_data("proc_test1", 0644, s_pstRootTestDir, &dl_file_ops, &g_astDataInfo[0]); 
  60.  
  61.     g_astDataInfo[1].data1=3;      
  62.     g_astDataInfo[1].data2=4;   
  63.     proc_create_data("proc_test2", 0644, s_pstRootTestDir, &dl_file_ops, &g_astDataInfo[1]);   
  64. }  
  65.  
  66. static int __init test_module_init(void)   
  67. {   
  68.     printk("[test]: module init\n"); 
  69.     init_mem();       
  70.     return 0;   
  71. }   
  72.  
  73. static void __exit test_module_exit(void)   
  74. {   
  75.     printk("[test]: module exit\n"); 
  76.     remove_proc_entry("proc_test1", s_pstRootTestDir);      
  77.     remove_proc_entry("proc_test2", s_pstRootTestDir); 
  78.     remove_proc_entry("test"NULL); 
  79. }   
  80. module_init(test_module_init);   
  81. module_exit(test_module_exit); 

 

proc_create

說(shuō)明:創(chuàng)建proc虛擬文件系統(tǒng)文件

函數(shù)原型:

  1. struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops) 

參數(shù):

  • name

你要?jiǎng)?chuàng)建的文件名。

  • mode

為創(chuàng)建的文件指定權(quán)限

  • parent

為你要在哪個(gè)文件夾下建立名字為name的文件,如:init_net.proc_net是要在/proc/net/下建立文件。

  • proc_fops

為struct file_operations

注意:這個(gè)接口和proc_create_data的區(qū)別在于他不能保存私有數(shù)據(jù)指針。

PDE_DATA

獲取proc_create_data傳入的私有數(shù)據(jù)。

proc_symlink

說(shuō)明:這個(gè)函數(shù)在procfs目錄下創(chuàng)建一個(gè)從name指向dest的符號(hào)鏈接. 它在用戶(hù)空間等效為ln -s dest name。

函數(shù)原型:

  1. struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest) 

參數(shù):

  • name

原始符號(hào)。

  • parent

符號(hào)所在的目錄。

  • dest

所要?jiǎng)?chuàng)建的符號(hào)鏈接名字。

remove_proc_entry

說(shuō)明:刪除procfs文件系統(tǒng)中的文件或者目錄。

函數(shù)原型:

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

參數(shù):

  • name

要?jiǎng)h除的文件或者目錄名。

  • parent

符號(hào)所在的目錄,如果為NULL,表示在/proc目錄下。 

責(zé)任編輯:龐桂玉 來(lái)源: 嵌入式Linux中文站
相關(guān)推薦

2009-12-22 11:30:38

Linux操作系統(tǒng)

2010-03-11 17:25:17

Linux系統(tǒng)使用率proc文件系統(tǒng)

2009-12-18 16:18:15

Fedora proc

2009-12-18 15:54:44

Fedora proc

2014-05-19 09:51:35

Tux3文件系統(tǒng)Linux 內(nèi)核

2010-05-19 15:23:51

Linux 2.6.3Ceph分布式文件系統(tǒng)

2011-01-13 14:10:30

Linux文件系統(tǒng)

2009-07-02 18:16:05

Linux

2019-05-29 16:33:32

Linux虛擬系統(tǒng)

2022-12-07 15:56:33

procfsLiteOS-A

2019-05-22 09:00:16

Linux虛擬文件系統(tǒng)

2009-07-07 09:19:58

Linux

2020-07-22 14:53:06

Linux系統(tǒng)虛擬文件

2012-07-05 09:52:06

EFS文件加密

2024-01-10 21:19:09

Linux 內(nèi)核文件系統(tǒng)

2025-03-28 09:19:11

2021-06-06 16:55:22

Linux文件系統(tǒng)

2021-04-12 05:44:44

Linux文件系統(tǒng)

2020-05-08 16:39:01

內(nèi)存系統(tǒng)架構(gòu)Linux

2011-01-11 10:29:35

Linux文件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)