標籤:驅動開發 核心 linux mint ubuntu proc
在做核心驅動開發的時候,可以使用/proc下的檔案,擷取相應的資訊,以便調試。
大多數/proc下的檔案是唯讀,但為了樣本的完整性,都提供了寫方法。
方法一:使用create_proc_entry建立proc檔案(簡單,但寫操作有緩衝區溢位的危險);
方法二:使用proc_create和seq_file建立proc檔案(較方法三簡潔);
方法三:使用proc_create_data和seq_file建立proc檔案(較麻煩,但比較完整);
樣本四:在proc檔案中使用核心鏈表的一個樣本(用的方法三)。
--------------------------------------------------------------------------------------------------------------------
三、
proc_test03.c 源碼
#include <linux/module.h>#include <linux/sched.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/uaccess.h>#include <linux/slab.h>#define BUF_SIZE 128// global varstatic char *str = NULL;// linux/seq_file.h// void * (*start) (struct seq_file *m, loff_t *pos);// void (*stop) (struct seq_file *m, void *v);// void * (*next) (struct seq_file *m, void *v, loff_t *pos);// int (*show) (struct seq_file *m, void *v);/*** author: aran* fuction: seq_operations -> start*/static void *my_seq_start(struct seq_file *m, loff_t *pos){if (0 == *pos){++*pos;return (void *)1; // return anything but NULL, just for test}return NULL;}/*** author: aran* fuction: seq_operations -> next*/static void *my_seq_next(struct seq_file *m, void *v, loff_t *pos){// only once, so no nextreturn NULL;}/*** author: aran* fuction: seq_operations -> stop*/static void my_seq_stop(struct seq_file *m, void *v){// clean sth.// nothing to do}/*** author: aran* fuction: seq_operations -> show*/static int my_seq_show(struct seq_file *m, void *v){char buf[BUF_SIZE];int ret = 0;ret = sprintf(buf, "current kernel time is %llu\n", (unsigned long long) get_jiffies_64());ret += sprintf(buf + ret, "str is %s\n", str);seq_printf(m, "%s", buf);return 0; //!! must be 0, or will show nothing T.T}// global varstatic struct seq_operations my_seq_fops = {.start= my_seq_start,.next= my_seq_next,.stop= my_seq_stop,.show= my_seq_show,};// file_operations// int (*open) (struct inode *, struct file *)// ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)/*** author: aran* fuction: file_operations -> open*/static int proc_seq_open(struct inode *inode, struct file *file){return seq_open(file, &my_seq_fops);}/*** author: aran* fuction: file_operations -> write*/static ssize_t proc_seq_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;//將使用者態write的字串拷貝到核心空間//copy_to|from_user(to,from,cnt)if (copy_from_user(tmp, buffer, count)) {kfree(tmp);return -EFAULT;}//將str的舊空間釋放,然後將tmp賦值給strkfree(str);str = tmp;return count;}// global varstatic struct file_operations proc_seq_fops = {.owner= THIS_MODULE,.open= proc_seq_open,.read= seq_read,.write= proc_seq_write,.llseek= seq_lseek,.release= seq_release,};static int __init my_init(void){struct proc_dir_entry *file;// create "/proc/proc_seq" filefile = proc_create_data("jif",// name0666,// modeNULL,// parent dir_entry&proc_seq_fops,// file_operationsNULL// data);if (NULL == file){printk("Count not create /proc/jif file!\n");return -ENOMEM;}return 0;}static void __exit my_exit(void){remove_proc_entry("jif", NULL);kfree(str);}module_init(my_init);module_exit(my_exit);MODULE_AUTHOR("aran");MODULE_LICENSE("GPL");Makefile檔案:
obj-m:= proc_test03.oKERNEL:= /lib/modules/`uname -r`/build #for mint/ubuntu#KERNEL:= /lib/modules/`uname -r`/source #for redhatall:make -C $(KERNEL) M=`pwd` modulesinstall:make -C $(KERNEL) M=`pwd` modules_installdepmod -Aclean:make -C $(KERNEL) M=`pwd` clean
測試結果: