Linux内核---57.sysfs的读写操作

一. 驱动层
1.1 关于sys文件系统
a.对于DEVICE_ATTR,其定义是#define DEVICE_ATTR(_name, _mode, _show, _store)
  填充DEVICE_ATTR: 名称、权限位、读函数、写函数   
  static DEVICE_ATTR( power_on , S_IRUGO | S_IWUSR,NULL, hello_set_power);
  DEVICE_ATTR中名称是power_on,即在/sys目录下创建了一个叫power_on的文件
b. 创建接口
当DEVICE_ATTR中名称是power_on,则构体struct attribute *dev_attrs[]中
其中的名字必须是&dev_attr_ power_on .attr,如下蓝色所示
    static struct attribute * hello_attributes [] = {
      &dev_attr_ power_on .attr,
      NULL
    };
c. 然后再封装到atrribute_group中去
   static const struct attribute_group hello_attr_group = {
    .attrs =  hello_attributes ,
   };   
d. 最后调用sysfs_create_group(&pdev->dev.kobj, &hello_attr_group);创建接口
f. 上层应用调用sys接口时,只需在/sys/device/platform/hello/目录中, echo 1 > ./power_on就完成了一次 write操作,对应到 kernel,调用了驱动中的 "store"。同理,cat ./power_on时就调用调用 "show"
1.2 驱动代码
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/device.h>
  4. #include <linux/ioport.h>
  5. #include <linux/errno.h>
  6. #include <linux/workqueue.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/types.h>
  9. #include <linux/io.h>

  10. typedef struct {
  11.     int num;
  12. }hello_priv;
  13. //当上导调用 echo 111 > ./power_on时, buf的内容就是这个字符串“111”,即参数
  14. static ssize_t hello_set_power(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
  15. {
  16.     hello_priv* prv = dev_get_drvdata(dev);
  17.     if ('0' == buf[0])     //shutdown
  18.     { 
  19.       printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s, prv->num=%d", __FILE__,__FUNCTION__, __LINE__,buf, prv->num); 
  20.     }else if ('1' == buf[0])  //poweron
  21.     { 
  22.       printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s, prv->num=%d", __FILE__,__FUNCTION__, __LINE__,buf, prv->num); 
  23.     }
  24.     return count;
  25. }
  26. //1. 设置DEVICE_ATTR: 名称power_on必须与attribute中的名称对应,
  27. static DEVICE_ATTR(power_on, S_IRUGO | S_IWUSR,NULL, hello_set_power);  //show接口为空,只有store接口,即只支持写不技持读
  28. //2. 设置DEVICE_ATTR
  29. static struct attribute *hello_attributes[] = {
  30.     &dev_attr_power_on.attr,          //dev_attr_****.attr中间的××××必须与DEVICE_ATTR中的名称对应
  31.     NULL
  32. };
  33. //3. 封装到attribute_group中去
  34. static const struct attribute_group hello_attr_group = {
  35.     .attrs = hello_attributes,
  36. };

  37. static int __init hello_probe(struct platform_device *pdev)
  38. {
  39.     int rc;
  40.     hello_priv* prv;

  41.     prv = devm_kzalloc(&pdev->dev, sizeof(hello_priv), GFP_KERNEL);
  42.     if (!prv) {
  43.         dev_err(&pdev->dev, "failed to allocate hello\n");
  44.         return -ENOMEM;
  45.     }

  46.     prv->num = 2;

  47.     platform_set_drvdata(pdev,prv);

  48.     rc = sysfs_create_group(&pdev->dev.kobj, &hello_attr_group);    //4.调用sysfs_create_group创建/sys下的文件
  49.     if (rc) {
  50.         dev_err(&pdev->dev,"failed to create hello sysfs group\n");
  51.         goto fail;
  52.     }

  53.     return 0;
  54. fail:
  55.     return rc;
  56. }

  57. struct platform_driver hello_driver = {
  58.     .driver = {
  59.         .name = "hello",
  60.         .owner = THIS_MODULE,
  61.     },
  62.     .probe = hello_probe,
  63. };

  64. static struct platform_device hello_device =
  65. {
  66.     .name = "hello",
  67.     .id = -1,
  68. };

  69. static int __init hello_init(void)
  70. {
  71.     int ret;

  72.     ret = platform_device_register(&hello_device);
  73.     if (ret != 0)
  74.       printk(KERN_NOTICE "cong: %s:%s[%d]: error", __FILE__,__FUNCTION__, __LINE__); 

  75.     ret = platform_driver_register(&hello_driver);
  76.     return ret;
  77. }

  78. static void __init hello_exit(void)
  79. {
  80.     platform_driver_unregister(&hello_driver);
  81. }

  82. module_init(hello_init);
  83. module_exit(hello_exit);

  84. MODULE_DESCRIPTION("GPIO Controller Driver");
  85. MODULE_AUTHOR("cong");
  86. MODULE_LICENSE("GPL");
1.3 代码打包
sys.rar (下载后改名为sys.rar)

二. 应用层
2.1 说明
测试时可以直接调用echo 1 > /sys/devices/platform/hello/power_on
代码中open --> /sys/devices/platform/hello/power_on
write 即可
2.2 代码
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <sys/time.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <sys/ioctl.h>
  9. #include <linux/ioctl.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>

  13. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)    

  14. #define POWER_ON "power_on"

  15. int usage()
  16. {
  17.     printf("usage:\n");
  18.     printf("./test power_on <0/1> : 0-->poweron; 1-->poweroff \n"); 
  19.     return 0;
  20. }

  21. int power_on(char* arg)
  22. {
  23.     int fd;
  24.     if( ('0'!=arg[0]) && ('1'!=arg[0]))
  25.     {
  26.         dbmsg("bad args");
  27.         return -1;
  28.     }
  29.     fd = open("/sys/devices/platform/hello/power_on", O_RDWR);
  30.     if(fd < 0)
  31.     {
  32.         dbmsg("open error");
  33.         return -1;
  34.     }
  35.     dbmsg("arg=%s", arg);
  36.     write(fd, arg, 1);
  37.     return 0;
  38. }

  39. int main ( int argc, char *argv[] )
  40. {
  41.     int ret;
  42.     int num;
  43.     int fd_gpio;
  44.     if(argc < 2)
  45.     {
  46.         usage();
  47.         return -1;
  48.     }

  49.     if(strncmp(argv[1],POWER_ON, sizeof(POWER_ON)) == 0)
  50.     {
  51.         dbmsg("%s", POWER_ON);
  52.         if(argc != 3)
  53.         {
  54.             usage();
  55.             return -1;
  56.         }
  57.         power_on(argv[2]); 
  58.     }
2.3 代码打包
app.rar (下载后改名为app.tar.gz)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值