proc_create的使用方法


proc_create的使用方法

proc文件系統是個有用的東東。
創建一個proc虛擬文件,應用層通過讀寫該文件,即可實現與內核的交互
proc虛擬文件是如何創建的呢?

先看看比較簡單的,創建proc文件夾。
調用以下函數,即可實現proc文件夾的創建:
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);
name就是要創建的文件夾名稱。
parent是要創建節點的父節點。也就是要在哪個文件夾之下創建新文件夾,需要將那個文件夾的proc_dir_entry傳入。
如果是在/proc目錄下創建文件夾,parent為NULL。
例如:

struct proc_dir_entry *mytest_dir = proc_mkdir("mytest", NULL);

 

然后來看看proc文件的創建。
創建方法是調用以下函數:

static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);

 


name就是要創建的文件名。
mode是文件的訪問權限,以UGO的模式表示。
parent與proc_mkdir中的parent類似。也是父文件夾的proc_dir_entry對象
proc_fops就是該文件的操作函數了
例如:

struct proc_dir_entry *mytest_file = proc_create("mytest", 0x0644, mytest_dir, mytest_proc_fops);

還有一種方式:

struct proc_dir_entry *mytest_file = proc_create("mytest/mytest", 0x0644, NULL, mytest_proc_fops);

如果文件夾名稱和文件名定義為常量:

#define MYTEST_PROC_DIR "mytest"
#define MYTEST_PROC_FILE "mytest"

第二種方式為:

struct proc_dir_entry *mytest_file = proc_create(MYTEST_PROC_DIR"/"MYTEST_PROC_FILE, 0x0644, NULL, mytest_proc_fops);

 

接下來看看mytest_proc_fops的定義。

static const struct file_operations mytest_proc_fops = {
 .open  = mytest_proc_open,
 .read  = seq_read,
 .write  = mytest_proc_write,
 .llseek  = seq_lseek,
 .release = single_release,
};

以seq_和single_為前綴的函數都是kernel中現成的。
可以參考文檔:Documentation\filesystems\seq_file.txt
關於single_開頭的函數,有以下說明:

The extra-simple version

For extremely simple virtual files, there is an even easier interface.  A
module can define only the show() function, which should create all the
output that the virtual file will contain. The file's open() method then
calls:

 int single_open(struct file *file,
                 int (*show)(struct seq_file *m, void *p),
                 void *data);

 

When output time comes, the show() function will be called once. The data
value given to single_open() can be found in the private field of the
seq_file structure. When using single_open(), the programmer should use
single_release() instead of seq_release() in the file_operations structure
to avoid a memory leak.

根據以上這段說明,在mytest_proc_open函數中,只需要調用single_open函數,並傳入一個show函數即可。
例如:

static int mytest_proc_open(struct inode *inode, struct file *file)
{
 return single_open(file, mytest_proc_show, inode->i_private);
}

 


其中第三個參數,也就是single_open的data參數,內核中有些地方傳入的NULL,有些地方傳入的inode->i_private,也有傳入其他值的。
來看看data在single_open函數中如何被使用的:
  if (!res)
   ((struct seq_file *)file->private_data)->private = data;
這與前面的英文說明一致,data是seq_file結構體的private成員。
那么data如何真正被使用的呢?
發現show函數的第一個參數為seq_file類型,在show函數中,可以將seq_file的private成員轉換成對應的類型進行使用。

下面來看看mytest_proc_show函數如何實現。
傳遞給single_open的show函數指針,將在proc file輸出時被調用。
例如,cat /proc/mytest/mytest時,mytest_proc_show函數將會被調用。
假設我們的mytest只是記錄了一個標志,內核中會根據該標准執行不同的操作。
來看看mytest_proc_show的實現:

static int task_lifecycle_proc_show(struct seq_file *seq, void *v)
{
 seq_puts(seq, mytest_flag ? "true\n" : "false\n");
 
 return 0;        
}

 

接下來再看看mytest_proc_write函數的實現。
顧名思義,mytest_proc_write函數會在寫mytest文件時被調用。
功能就是記錄寫入數據到mytest文件。
實現也不麻煩:

static ssize_t task_lifecycle_proc_write(struct file *file, const char __user *buffer,
        size_t count, loff_t *pos)
{
 char mode;
 
 if (count > 0) {
  if (get_user(mode, buffer))
   return -EFAULT;

   mytest_flag = (mode != '0');
 }

 return count;
}

 

至此,proc文件創建完畢。
通過讀寫mytest文件,即可實現對mytest_flag的控制。
更深層次的原理,即proc文件系統是如何實現的,就先不討論了。
不然又成懶婆娘的裹腳了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM