根据linux设备驱动一书的介绍,除了最基本printk打印调试以外,还可以
通过创建proc接口进行内核代码的调试。
在具体的驱动程序里,可以将read函数嵌套在某个函数里面,选择自己打印的内容进行打印。
(1)通过struct proc_ops
proc_create创建proc接口(头文件,#include<linux/proc_fs.h>)
proc.c
#include<linux/module.h>
#include<linux/init.h>
#include<linux/string.h>
#include<linux/proc_fs.h>
#include<linux/seq_file.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Tan xujia");
MODULE_VERSION("V1");
char *str = "hello proc\n";
int
hp_open(struct inode *inode, struct file *filp)
{
printk(KERN_INFO "open %ld\n", strlen(str));
return 0;
}
ssize_t
hp_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos)
{
ssize_t retval = 0;
int n = strlen(str);
if(*f_pos >= n)
goto out;
/*将剩下的字节返回即可*/
if(*f_pos + count > n)
count = n - *f_pos;
/*拷贝数据到用户空间*/
if(copy_to_user(buff, str, count)) {
retval = -EFAULT;
goto out;
}
/*更新偏移量*/
*f_pos += count;
return count;
out:
return retval;
}
/*仅实现open和read功能*/
struct proc_ops hp_ops = {
.proc_open = hp_open,
.proc_read = hp_read,
};
static int
__init hello_init(void)
{
printk(KERN_INFO "hello_init\n");
/*创建这个接口,通过proc目录可以看到这个接口*/
proc_create("hello_proc", 0, NULL, &hp_ops);
return 0;
}
static void
__exit hello_exit(void)
{
remove_proc_entry("hello_proc",NULL);
printk(KERN_INFO "hello_exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m :=proc.o
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.mod *.order *.symvers
(2)通过
struct seq_operations
proc_create_seq() 创建proc接口(头文件,#include<linux/seq_file.h>)
proc.c
#include<linux/module.h>
#include<linux/init.h>
#include<linux/uaccess.h>
#include<linux/string.h>
#include<linux/proc_fs.h>
#include<linux/seq_file.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Tan xujia");
MODULE_VERSION("V1");
char *str = "hello proc\n";
void*
hp_seq_start(struct seq_file *m, loff_t *pos)
{
printk(KERN_INFO "seq start\n");
if(*pos >= strlen(str))
return NULL;
return &str[*pos];
}
/*stop函数里面不做什么事情,如果在start函数里面有
例如申请什么内存之类的,可以在stop函数里面进行释放*/
void
hp_seq_stop(struct seq_file *m, void *v)
{
printk(KERN_INFO "seq stop\n");
}
void*
hp_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
printk(KERN_INFO "seq next\n");
(*pos)++;
if(*pos >= strlen(str))
return NULL;
return &str[*pos]; /*这个一般是传给show函数的v形参*/
}
int
hp_seq_show(struct seq_file *m, void *v)
{
printk(KERN_INFO "seq_show\n");
seq_putc(m,*(char*)v); /*cat时,将字符串打印出来*/
return 0;
}
/*一般是实现这几个函数*/
const struct seq_operations seq_ops={
.start = hp_seq_start,
.stop = hp_seq_stop,
.next = hp_seq_next,
.show = hp_seq_show,
};
static int
__init hello_init(void)
{
printk(KERN_INFO "hello_init\n");
proc_create_seq("seq_proc", 0, NULL, &seq_ops);
return 0;
}
static void
__exit hello_exit(void)
{
remove_proc_entry("seq_proc", NULL);
printk(KERN_INFO "hello_exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m :=proc.o
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.mod *.order *.symvers