在做内核驱动开发的时候,可以使用/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 var static 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 next return 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 var static 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赋值给str kfree(str); str = tmp; return count; } // global var static 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" file file = proc_create_data( "jif", // name 0666, // mode NULL, // parent dir_entry &proc_seq_fops, // file_operations NULL // 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.o KERNEL := /lib/modules/`uname -r`/build #for mint/ubuntu #KERNEL := /lib/modules/`uname -r`/source #for redhat all: make -C $(KERNEL) M=`pwd` modules install: make -C $(KERNEL) M=`pwd` modules_install depmod -A clean: make -C $(KERNEL) M=`pwd` clean
测试结果:
ubuntu/linux mint 创建proc文件的三种方法(三)
时间: 2024-10-29 19:08:52