轉自:http://blog.csdn.net/mumufan05/article/details/45803219
學習筆記與個人理解,如有錯誤,歡迎指正。
溫馨提示:建議跟着注釋中的編號順序閱讀代碼
測試方法: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");