国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Linux > 正文

Linux驅(qū)動小技巧 利用DRIVER_ATTR實現(xiàn)調(diào)用內(nèi)核函數(shù)

2024-08-27 23:54:43
字體:
供稿:網(wǎng)友
  1. 前言
  很多朋友在調(diào)試驅(qū)動的時候,都會遇到這樣一個場景:修改一個參數(shù),然后調(diào)用某個內(nèi)核中的函數(shù)。
 
  比如將某個gpio的值拉高/拉低,修改某個寄存器的值等等。
 
  如果每一個參數(shù)都通過字符設(shè)備的ioctl接口,增加對應(yīng)的cmd,會比較麻煩,
 
  研究內(nèi)核的計算機大牛門怎么會容忍這種事發(fā)生,
 
  于是設(shè)計出了DRIVER_ATTR這個宏,完美解決這個需求。
 
  下面一口君通過一個簡單的實例,給大家講解如何使用DRIVER_ATTR。
 
  2. DRIVER_ATTR定義
  該宏定義的文件如下:include/linux/device.h
 
  復(fù)制
  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
 
  復(fù)制
  #define __ATTR(_name, _mode, _show, _store) {    /
   .attr = {.name = __stringify(_name), .mode = _mode },  /
   .show = _show,      /
   .store = _store,      /
  }
   說明
 
  復(fù)制
   _name:名稱,也就是將在sys fs中生成的文件名稱。
   _mode:上述文件的訪問權(quán)限,與普通文件相同,UGO的格式,最高權(quán)限0644,否則會報錯。
   _show:顯示函數(shù),cat該文件時,此函數(shù)被調(diào)用。
   _store:寫函數(shù),echo內(nèi)容到該文件時,此函數(shù)被調(diào)用。
   3. 使用步驟定義一個寫操作的回調(diào)函數(shù):
 
  復(fù)制
  static ssize_t peng_test_store(struct device_driver *driver,
       const char *buf, size_t count)
  {
  //對參數(shù)進行檢查
   if(NULL == buf || count >255 || count == 0 || strnchr(buf, count, 0x20))
    return -1;
 
   printk("buf:%s count:%d/n",buf,count);
 
   return count;
  }
   聲明該函數(shù)與文件節(jié)點關(guān)系
 
  復(fù)制
  static DRIVER_ATTR(peng, 0644, NULL, peng_test_store);
  1.
  創(chuàng)建文件節(jié)點:
 
  復(fù)制
   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;
   }
   這幾個名字之間關(guān)系如下:
 
 
 
  4. 源碼
  本實驗代碼分為兩個模塊 device、driver, 分別定義結(jié)構(gòu)體platform_device、platform_driver并注冊到platform總線。
 
  完整源碼如下:
 
  device.c
  復(fù)制
  #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
  復(fù)制
  #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
  復(fù)制
  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
   5. 編譯運行
  第一步:編譯
 
  第二步:加載模塊驅(qū)動 第三步:查看生成的文件節(jié)點:
 
  第四步:通過下面命令向節(jié)點輸入一個數(shù)字(要管理員權(quán)限):
 
  復(fù)制
  echo 1 > peng
  
 
  由結(jié)果可知,我們通過向文件peng寫入一個字符,實現(xiàn)了調(diào)用函數(shù)peng_test_store(),并且字符1傳遞給了參數(shù)buf,字符個數(shù)傳遞給了count。
 
  其中目錄duang是由結(jié)構(gòu)體變量hello_driver 給出:
 
  復(fù)制
  static struct platform_driver hello_driver =
  {
   .driver.name = "duang",
  };
   6. 一次注冊多個節(jié)點
  需要借助結(jié)構(gòu)體
 
  復(fù)制
  drivers/input/touchscreen/ads7846.c
  1.
  復(fù)制
  static ssize_t ads7846_pen_down_show(struct device *dev,
           struct device_attribute *attr, char *buf)
  {
   struct ads7846 *ts = dev_get_drvdata(dev);
 
   return sprintf(buf, "%u/n", ts->pendown);
  }
 
  static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
 
  static ssize_t ads7846_disable_show(struct device *dev,
           struct device_attribute *attr, char *buf)
  {
   struct ads7846 *ts = dev_get_drvdata(dev);
 
   return sprintf(buf, "%u/n", ts->disabled);
  }
 
  static ssize_t ads7846_disable_store(struct device *dev,
           struct device_attribute *attr,
           const char *buf, size_t count)
  {
   struct ads7846 *ts = dev_get_drvdata(dev);
   unsigned int i;
   int err;
 
   err = kstrtouint(buf, 10, &i);
   if (err)
    return err;
 
   if (i)
    ads7846_disable(ts);
   else
    ads7846_enable(ts);
 
   return count;
  }
  static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
 
  static struct attribute *ads784x_attributes[] = {
   &dev_attr_pen_down.attr,
   &dev_attr_disable.attr,
   NULL,
  };
 
  static struct attribute_group ads784x_attr_group = {
   .attrs = ads784x_attributes,
  };
   復(fù)制
  err = sysfs_create_group(&mydevice->dev.kobj, &ads784x_attr_group);

(編輯:武林網(wǎng))

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 东乌珠穆沁旗| 英德市| 五指山市| 竹溪县| 册亨县| 乐清市| 义马市| 新丰县| 龙海市| 万安县| 徐州市| 海宁市| 蓬溪县| 焉耆| 宽甸| 保山市| 黄骅市| 卫辉市| 泸溪县| 彭山县| 邹城市| 常山县| 米脂县| 三江| 巢湖市| 无极县| 南江县| 栾川县| 娄烦县| 元谋县| 襄垣县| 灵璧县| 贡觉县| 汾阳市| 土默特左旗| 宜春市| 盐源县| 玉环县| 太仆寺旗| 甘南县| 德江县|