Linux驱动学习 —— 在/sys下面创建目录示例

有时我们需要在/sys下面创建一些目录, 下面给出了一个示例。 在加载驱动模块后, 在/sys下面会创建一个名为sysfs_demo的目录,并在其中在创建几个文件和目录。

[[email protected] mnt]# ls -R /sys/sysfs_demo/
/sys/sysfs_demo/:
node_one      node_two      sysfs_demo_2

/sys/sysfs_demo/sysfs_demo_2:
node_four   node_three

这里用到的两个函数分别是: kobject_create_and_add 和 sysfs_create_group。前一个函数用于在/sys下面创建目录, 后一个函数用于创建文件。

示例驱动:

  1 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
  2
  3 #include <linux/init.h>
  4 #include <linux/module.h>
  5 #include <linux/kobject.h>
  6 #include <linux/device.h>
  7
  8 static struct kobject *k_obj = NULL;
  9 static struct kobject *k_obj_2 = NULL;
 10
 11 static char node_one_buf[20] = {0};
 12
 13 static ssize_t sysfs_demo_show_node_one(struct kobject *kobj, struct kobj_attribute *attr, char * buf)
 14 {
 15     pr_info("enter, node: %s\n", attr->attr.name);
 16     return sprintf(buf, "%s: %s\n", attr->attr.name, node_one_buf);
 17 }
 18
 19 static ssize_t sysfs_demo_store_node_one(struct kobject *kobj, struct kobj_attribute *attr, const char * buf, size_t n)
 20 {
 21     pr_info("enter, node: %s\n", attr->attr.name);
 22
 23     sprintf(node_one_buf, "%s", buf);
 24
 25     return n;
 26 }
 27
 28 static struct kobj_attribute node_one_attribute =
 29     __ATTR(node_one, S_IWUSR|S_IRUGO, sysfs_demo_show_node_one, sysfs_demo_store_node_one);
 30
 31 static ssize_t sysfs_demo_show_node_two(struct kobject *kobj, struct kobj_attribute *attr, char * buf)
 32 {
 33
 34     return sprintf(buf, "%s\n", attr->attr.name);
 35 }
 36
 37 static struct kobj_attribute node_two_attribute =
 38     __ATTR(node_two, S_IWUSR|S_IRUGO, sysfs_demo_show_node_two, NULL);
 39
 40 static struct attribute *sysfs_demo_attributes[] = {
 41     &node_one_attribute.attr,
 42     &node_two_attribute.attr,
 43     NULL
 44 };
 45
 46 static const struct attribute_group sysfs_demo_attr_group = {
 47     .attrs = sysfs_demo_attributes,
 48 };
 49
 50 static char node_three_buf[20] = {0};
 51
 52 static ssize_t sysfs_demo_show_node_three(struct kobject *kobj, struct kobj_attribute *attr, char * buf)
 53 {
 54     pr_info("enter, node: %s\n", attr->attr.name);
 55     return sprintf(buf, "%s: %s\n", attr->attr.name, node_three_buf);
 56 }
 57
 58 static ssize_t sysfs_demo_store_node_three(struct kobject *kobj, struct kobj_attribute *attr, const char * buf, size_t n)
 59 {
 60     pr_info("enter, node: %s\n", attr->attr.name);
 61
 62     sprintf(node_three_buf, "%s", buf);
 63
 64     return n;
 65 }
 66
 67 static struct kobj_attribute node_three_attribute =
 68     __ATTR(node_three, S_IWUSR|S_IRUGO, sysfs_demo_show_node_three, sysfs_demo_store_node_three);
 69
 70 static ssize_t sysfs_demo_show_node_four(struct kobject *kobj, struct kobj_attribute *attr, char * buf)
 71 {
 72
 73     return sprintf(buf, "%s\n", attr->attr.name);
 74 }
 75
 76 static struct kobj_attribute node_four_attribute =
 77     __ATTR(node_four, S_IWUSR|S_IRUGO, sysfs_demo_show_node_four, NULL);
 78
 79 static struct attribute *sysfs_demo2_attributes[] = {
 80     &node_three_attribute.attr,
 81     &node_four_attribute.attr,
 82     NULL
 83 };
 84
 85 static const struct attribute_group sysfs_demo2_attr_group = {
 86     .attrs = sysfs_demo2_attributes,
 87 };
 88
 89 static int __init sysfs_demo_init(void)
 90 {
 91     if ((k_obj = kobject_create_and_add("sysfs_demo", NULL)) == NULL ) {
 92         pr_err("sysfs_demo sys node create error \n");
 93         goto out;
 94     }
 95
 96     if(sysfs_create_group(k_obj, &sysfs_demo_attr_group) ) {
 97         pr_err("sysfs_create_group failed\n");
 98         goto out2;
 99     }
100
101     if ((k_obj_2 = kobject_create_and_add("sysfs_demo_2", k_obj)) == NULL ) {
102         pr_err("hwinfo sys node create error \n");
103         goto out3;
104     }
105
106     if(sysfs_create_group(k_obj_2, &sysfs_demo2_attr_group) ) {
107         pr_err("sysfs_create_group failed\n");
108         goto out4;
109     }
110
111     pr_info("enter.\n");
112     return 0;
113 out4:
114     kobject_put(k_obj_2);
115 out3:
116     sysfs_remove_group(k_obj, &sysfs_demo_attr_group);
117 out2:
118     kobject_put(k_obj);
119 out:
120     return -1;
121 }
122 module_init(sysfs_demo_init);
123
124 static void __exit sysfs_demo_exit(void)
125 {
126     pr_info("enter.\n");
127
128     if (k_obj) {
129         sysfs_remove_group(k_obj, &sysfs_demo_attr_group);
130         if (k_obj_2) {
131             sysfs_remove_group(k_obj_2, &sysfs_demo2_attr_group);
132             kobject_put(k_obj_2);
133         }
134         kobject_put(k_obj);
135     }
136
137 }
138 module_exit(sysfs_demo_exit);
139
140 MODULE_LICENSE("GPL");
时间: 2024-09-27 04:31:39

Linux驱动学习 —— 在/sys下面创建目录示例的相关文章

linux 驱动学习笔记01--Linux 内核的编译

由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make config(基于文本的最为传统的配置界面,不推荐使用)#make menuconfig(基于文本菜单的配置界面)#make xconfig(要求 QT 被安装)#make gconfig(要求 GTK+被安装)在配置 Linux 2.6 内核所使用的 make config. make menuconfig. mak

Linux驱动学习之Linux-2.6.20.4内核移植

最近一段时间一直在学习向TQ2440开发板移植内核.移植驱动.真心觉得这方面的知识有很大的难度.但是从另一角度去看,难度越大,能力提升的空间就越大!! 1.解压源码 从网上下载一个Linux 内核,我是用的是Linux-2.6.20.4.然后用命令解压.建议解压到"/home/用户名"目录下.我的内核源码存放在: 2.添加对ARM的支持 因为所用的是TQ2440开发板,属于ARM9.因此要在系统中添加对ARM的支持. 方法:进入内核源码目录, 修改"Makefile"

linux驱动学习之tasklet分析

tasklet是中断处理下半部分最常用的一种方法,驱动程序一般先申请中断,在中断处理函数内完成中断上半部分的工作后调用tasklet.tasklet有如下特点: 1.tasklet只可以在一个CPU上同步地执行,不同的tasklet可以在不同地CPU上同步地执行. 2.tasklet的实现是建立在两个软件中断的基础之上的,即HI_SOFTIRQ和TASKLET_SOFTIRQ,本质上没有什么区别,只不过HI_SOFTIRQ的优先级更高一些 3.由于tasklet是在软中断上实现的,所以像软中断一

Linux驱动学习之TQ2440 DM9000E网卡驱动移植(Linux-2.6.30.4)

引言 在之前的文章中,我们介绍了如何使用Scala IDE也就是eclipse中集成的Scala开发插件来进行Scala语言程序的开发,在使用了一段时间之后,发现eclipse对Scala的支持并不是很好.用户体验比较差,比如联想速度比较慢等.由于在公司一直使用的Scala开发工具是Intellij IDEA(好吧,其实我使用Scala IDE的目的就是想试一下这两个各有什么优缺点),各方面感觉还不错,所以在此介绍一下这个开发环境. Intellij IDEA是jetbrain开发的一个IDE,

linux驱动学习(1)——字符设备驱动开发

(一)驱动程序介绍 (a)Linux驱动程序学习 知识结构: 1. Linux驱动程序设计模式(40%) 2. 内核相关知识(30%) 3. 硬件相关知识(30%) (b)驱动分类: ①字符设备: 字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现 open, close,read和 write 系统调用. ②块设备: 在大部分的 Unix 系统, 块设备不能按字节处理数据,只能一次传送一个或多个长度是512字节( 或一个更大的 2 次幂的数 )的整块数据,而Lin

Linux驱动学习步骤(转载)

1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod, rmmod. 在驱动的init函数里打印hello world, insmod后应该能够通过dmesg看到输出. 5. 写一完整驱动, 加上read, write, ioctl, polling等各种函数的驱动实现. 在ioctl里完成从用户空间向内核空间传递结构体的实现. 6. 写一bl

Linux驱动学习之常用的模块操作命令

1.常用的模块操作命令 (1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 (2)insmod(install module,安装模块),功能是向当前内核中去安装一个模块,用法是insmod xxx.ko (3)modinfo(module information,模块信息),功能是打印出一个内核模块的自带信息.,用法是modinfo xxx.ko,注意要加.ko,也就是说是一个静态的文件形式. (4)rmmod(remove module,卸载

【Linux驱动学习】SD卡规范学习

摘要: 学习SD卡的相关规范,包括定义,硬件特性,数据传输,命令系统等.不涉及代码. 文章针对Linux驱动开发而写,以助于理解SD卡驱动,不会涉及过多硬件内容. 纲要: 1. SD卡介绍 2. SD卡硬件规范 3. SD卡指令规范 4. SD卡寄存器 1. SD卡介绍 1.1 各类型储存卡/接口 首先了解一下我们在SD卡驱动学习中会碰到的主要几个储存卡名词: SD:Security Digital Memory Card,新一代多媒体储存卡,高速,安全(但安全机制貌似很少用到)MMC:Mult

Linux驱动学习之驱动开发准备工作

一.开启驱动开发之路 1.驱动开发的准备工作 (1)正常运行linux系统的开发板.要求开发板中的linux的zImage必须是自己编译的,不能是别人编译的.原因在于在安装模块的时候会进行安全性校验 (2)内核源码树,其实就是一个经过了配置编译之后的内核源码.我们需要内核源码编译自己的模块 (3)nfs挂载的rootfs,主机ubuntu中必须搭建一个nfs服务器.这对于驱动开发前期是不可或缺的,能够提高我们的开发效率. 2.驱动开发的步骤 (1)驱动源码编写.Makefile编写.编译 (2)