加入收藏 | 设为首页 | 会员中心 | 我要投稿 汽车网 (https://www.0577qiche.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux驱动小技巧 使用DRIVER_ATTR实现调用内核函数

发布时间:2023-09-28 13:02:47 所属栏目:Linux 来源:
导读: 1. 前言

  很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数。

  比如将某个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
  

(编辑:汽车网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章