學習筆記與個人理解,如有錯誤,歡迎指正。
溫馨提示:建議跟著注釋中的編號順序閱讀代碼
測試方法:cat /proc/abc_proc
echo 任一字元串 >/proc/abc_pro(需root許可權)
/************************************************* 使用seq_file介面實現可讀寫proc檔案的例子 適用於3.10以後的核心 Author: ZhangN Date: 2015-5-17 *************************************************/#include <linux/module.h>#include <linux/sched.h>#include <linux/uaccess.h>#include <linux/proc_fs.h>#include <linux/fs.h>#include <linux/seq_file.h>#include <linux/slab.h>static char *str = NULL;/*5,實現show函數 作用是將核心資料輸出到使用者空間 將在proc file輸出時被調用*/static int my_proc_show(struct seq_file *m, void *v){ /*這裡不能使用printfk之類的函數 要使用seq_file輸出的一組特殊函數 詳見ldd3的91頁*/ seq_printf(m, "current kernel time is %ld\n", jiffies); seq_printf(m, "str is %s\n", str); return 0;}/*3,實現open和write函數*/static ssize_t my_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos){ char *tmp = kzalloc((count+1), GFP_KERNEL); if(!tmp) return -ENOMEM; if(copy_from_user(tmp, buffer, count)) { kfree(tmp); return EFAULT; } kfree(str); str = tmp; return count;}static int my_proc_open(struct inode *inode, struct file *file){ /*4,在open函數中調用single_open綁定seq_show函數指標 需要說明的是,ldd3中介紹的seq介面用該調用seq_open函數 其調用形式如下: return sep_open(file, &scull_seq_ops); scull_seq_ops為struct seq_operations結構體 在該結構體中綁定show函數指標 需要準備seq_operations結構體 而調用single_open函數只需直接指定show的函數指標即可 個人猜測可能是在single_open函數中實現了seq_operations結構體 至於是不是就不知道了,沒有查看具體實現 有興趣的同學可以參考文檔:Documentation\filesystems\seq_file.txt 關於第三個參數,其類型應為viod*, 核心中有些地方傳入的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成員轉換成對應的類型進行使用。 也就是說,可以通過seq_file的private成員將data參數傳遞到show函數中*/ return single_open(file, my_proc_show, NULL);}/*2,填充proc_create函數中調用的flie_operations結構體 其中my開頭的函數為自己實現的函數, seq和single開頭為核心實現好的函數,直接填充上就行 open為必須填充函數 這裡詳見ldd3的93頁*/static struct file_operations my_fops = { .owner = THIS_MODULE, .open = my_proc_open, .release = single_release, .read = seq_read, .llseek = seq_lseek, .write = my_proc_write,};static int __init my_init(void){ struct proc_dri_entry *file; /*3.10以後核心的proc檔案的新介面 需要關聯file_operations*/ /*1,首先要調用建立proc檔案的函數,需要綁定flie_operations*/ file = proc_create("abc_proc", 0644, NULL, &my_fops); if(!file) return -ENOMEM; return 0;}/*6,刪除proc檔案*/static void __exit my_exit(void){ remove_proc_entry("abc_proc", NULL); kfree(str);}module_init(my_init);module_exit(my_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("ZhangN");