Linux驱动小技巧 使用DRIVER_ATTR实现调用内核函数
发布时间:2023-09-28 13:02:47 所属栏目:Linux 来源:
导读: 1. 前言
很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数。
比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等。
如果每一个参数
很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数。
比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等。
如果每一个参数
1. 前言 很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数。 比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等。 如果每一个参数都通过字符设备的ioctl接口,增加对应的cmd,会比较麻烦, 研究内核的计算机大牛门怎么会容忍这种事发生, 于是设计出了DRIVER_ATTR这个宏,完美解决这个需求。 下面一口君通过一个简单的实例,给大家讲解如何使用DRIVER_ATTR。 2. DRIVER_ATTR定义 该宏定义的文件如下:include/linux/device.h 复制 struct driver_attribute { struct attribute attr; ssize_t (*show)(struct device_driver *driver, char *buf); ssize_t (*store)(struct device_driver *driver, const char *buf, size_t count); }; #define DRIVER_ATTR(_name, _mode, _show, _store) / struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store) __ATTR定义于文件 include/linux/sysfs.h 复制 #define __ATTR(_name, _mode, _show, _store) { / .attr = {.name = __stringify(_name), .mode = _mode }, / .show = _show, / .store = _store, / } 说明 复制 _name:名称,也就是将在sys fs中生成的文件名称。 _mode:上述文件的访问权限,与普通文件相同,UGO的格式,最高权限0644,否则会报错。 _show:显示函数,cat该文件时,此函数被调用。 _store:写函数,echo内容到该文件时,此函数被调用。 3 源码 本实验代码分为两个模块 device、driver, 分别定义结构体platform_device、platform_driver并注册到platform总线。 完整源码如下: device.c 复制 #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/ioport.h> static void hello_release(struct device *dev) { return; } static struct platform_device hello_device = { .name = "duang", .id = -1, .dev.release = hello_release, }; static int hello_init(void) { printk("hello_init /n"); return platform_device_register(&hello_device); } static void hello_exit(void) { printk("hello_exit /n"); platform_device_unregister(&hello_device); return; } MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit); driver.c 复制 #include <linux/init.h> #include <linux/module.h> #include <linux/kdev_t.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> #include <asm/io.h> #include <linux/platform_device.h> #include <linux/ioport.h> static int hello_probe(struct platform_device *pdev); static int hello_remove(struct platform_device *pdev); static ssize_t peng_test_store(struct device_driver *driver, const char *buf, size_t count) { if(NULL == buf || count >255 || count == 0 || strnchr(buf, count, 0x20)) return -1; printk("buf:%s count:%d/n",buf,count); return count; } static DRIVER_ATTR(peng, 0644, NULL, peng_test_store); static struct platform_driver hello_driver = { .probe = hello_probe, .driver.name = "duang", .remove = hello_remove, }; struct resource *res; static int hello_probe(struct platform_device *pdev) { int ret; printk("match ok /n"); ret = driver_create_file(&(hello_driver.driver), &driver_attr_peng); if (ret < 0){ dev_err(&pdev->dev, "could not create sysfs files/n"); ret = -ENOENT; } return 0; } static int hello_remove(struct platform_device *pdev) { printk("hello_remove /n"); return 0; } static int hello_init(void) { printk("hello_init /n"); return platform_driver_register(&hello_driver); } static void hello_exit(void) { printk("hello_exit /n"); platform_driver_unregister(&hello_driver); return; } MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit); Makefile 复制 ifneq ($(KERNELRELEASE),) obj-m:=device.o driver.o else KDIR :=/lib/modules/$(shell uname -r)/build #KDIR :=/home/peng/linux-3.14 PWD :=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.symvers *.cmd *.mod.c *.order endif (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐