调试技术(/proc、/sys、/dev、strace)
一、在/proc中实现文件
当某个进程读取我们的/proc文件时,内核会分配一个内存页,即PAGE_SIZE字节的内存块。
驱动程序可以将数据通过这个内存页返回到用户空间。
第一种方法,不采用seq_file int write_proc(struct file *file, const char *buffer, size_t count, loff_t *ppos){ } int read_proc(struct file *file, char *buffer, size_t count, loff_t *ppos){ } static const struct file_operations proc_fops = { .write = write_proc, .read = read_proc }; proc_create("name", 0660, NULL, >_upgrade_proc_fops); 第二种方法,采用seq_file 1.先实现seq_operations中的四个方法。 static const struct seq_operations my_seq_ops = { .start = pfkey_seq_start, .next = pfkey_seq_next, .stop = pfkey_seq_stop, .show = pfkey_seq_show, }; 2.构造一个file_operation结构 只要构造一个open函数即可,其他的均使用默认函数。 static int my_seq_open(struct inode *inode, struct file *file) { return seq_open(file, &my_seq_ops); } static const struct file_operations my_proc_ops = { .open = my_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; 3.创建文件 proc_create("name", 0, null, &pfkey_proc_ops);
二、strace命令
strace命令是一个功能非常强大的工具,它可以显示由用户空间程序发出的所有系统调用。
它不仅可以显示调用,而且还能显示调用参数以及用符号形式表示的返回值。
命令行选项:
-t: 显示调用发生的时间;
-T: 显示调用所花费的时间;
-e: 限定被跟踪的调用类型;
-o: 将输出重定向到一个文件中。
strace可以跟踪一个正在运行的进程。
三、设备文件的创建
不要与在sysfs下创建访问节点相互混淆,这个仅仅是为了在/sys/class 目录下生成相应的文件,供uevent机制自动生成/dev下的设备文件;
后面会介绍创建sysfs下访问节点的方法。
static struct class *my_class; struct device* temp; my_class = class_create(THIS_MODULE, "class_name"); temp = device_create(my_class, misc->parent, dev, misc, "%s", misc->name); 根据创建的device就可以自动生成/dev目录下的设备文件 #define class_create(owner, name) { //仅仅是个宏而已 __class_create(owner, name, &__key);{ __class_register(cls, key);{ kset_register(&cp->subsys);{ kobject_add_internal(&k->kobj);{ create_dir(kobj);{ sysfs_create_dir(kobj); populate_dir(kobj);{ sysfs_create_file(kobj, attr); } } } } add_class_attrs(class_get(cls));{ class_create_file(cls, &cls->class_attrs[i]);{ sysfs_create_file(&cls->p->subsys.kobj, &attr->attr); } } } } } device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); //函数原型
修改自动创建的设备节点的权限、所有者和所属组:
修改system/core/rootdir/ueventd.rc文件即可,在其中加入将要创建的设备节点的相关属性。
例:
/dev/stpgps 0660 gps gps
四、/sys下创建属性文件的方法:
在已有的目录下创建属性文件:
/************************************************************/ 该方法创建驱动的属性,一般存放在/sys/bus/platform/drivers/相应驱动/目录下面 int driver_create_file(struct device_driver *drv, const struct driver_attribute *attr); sysfs_create_file(&drv->p->kobj, &attr->attr); /************************************************************/ 该方法创建设备的属性,一般存放在/sys/devices/相应设备/目录下面。 int device_create_file(struct device *dev, const struct device_attribute *attr); sysfs_create_file(&dev->kobj, &attr->attr);
在/sys/目录下创建新的目录,并创建默认的属性文件:
/************************************************************/ ssize_t mtk_uart_attr_show(struct kobject *kobj, struct attribute *attr, char *buffer) { struct mtuart_entry *entry = container_of(attr, struct mtuart_entry, attr); return entry->show(kobj, buffer); } ssize_t mtk_uart_attr_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size) { struct mtuart_entry *entry = container_of(attr, struct mtuart_entry, attr); return entry->store(kobj, buffer, size); } struct sysfs_ops mtk_uart_sysfs_ops = { .show = mtk_uart_attr_show, .store = mtk_uart_attr_store, }; struct mtuart_entry { struct attribute attr; ssize_t (*show)(struct kobject *kobj, char *page); ssize_t (*store)(struct kobject *kobj, const char *page, size_t size); }; struct mtuart_entry conse_entry = { { .name = "conse", .mode = S_IRUGO | S_IWUSR }, mtk_uart_conse_show, mtk_uart_conse_store, }; .... struct attribute *mtk_uart_attributes[] = { &conse_entry.attr, /*console setting*/ #if defined(ENABLE_DEBUG) &debug_entry.attr, &sysrq_entry.attr, &vffsz_entry.attr, &vff_en_entry.attr, &lsr_status_entry.attr, &history_entry.attr, #endif NULL, }; struct kobj_type mtk_uart_ktype = { .sysfs_ops = &mtk_uart_sysfs_ops, .default_attrs = mtk_uart_attributes, }; struct mtuart_sysobj { struct kobject kobj; atomic_t sysrq; atomic_t vffLen[UART_NR*UART_VFIFO_NUM]; atomic_t console_enable; } mtk_uart_sysobj = { .console_enable = ATOMIC_INIT(1), }; struct mtuart_sysobj *obj = &mtk_uart_sysobj; obj->kobj.parent = kernel_kobj; kobject_init_and_add(&obj->kobj, &mtk_uart_ktype, NULL, "mtuart");{ kobject_add_varg(kobj, parent, fmt, args);{ kobject_add_internal(kobj);{ create_dir(kobj);{ sysfs_create_dir(kobj); populate_dir(kobj);{ sysfs_create_file(kobj, attr); } } } } }