当前位置:首页 > 嵌入式 > 嵌入式软件

作者:刘洪涛,华清远见嵌入式培训中心高级讲师,ARM公司授权ATC讲师。

在上篇《利用udev、sys动态创建设备结点》的记录中,设备驱动中主要依靠下面两个功能完成的:

1、在/sys/class下创建farsight_class类

my_class =class_create(THIS_module, "farsight_class");

2、在farsight_class中创建新的class设备

class_device_create(my_class,NULL, devno, NULL,"farsight_dev");

然后会在/sys中出现如图的文件结构:


其中”dev”和uevent都是“属性”,可以读取dev获取设备的主次设备号;也可以对uevent操作;让内核发出“add”事件用于热插拔。如:




注:这里写入任何值都会导致“add”事件的产生,udevmonitor检测时现象如下:

UEVENT[1220019773.507374] add????? /class/farsight_class/farsight_dev (farsight_class)

那么上述功能实现的原理是什么呢?现在就要过度到本文的主题ktype的使用了。先认识下这个结构

kype的结构定义为:

STruct kobj_type {

void (*release)(struct kobject *);

struct sysfs_ops *sysfs_ops;/*提供实现以下属性的方法*/

struct attribute **default_attrs; /*用于保存类型属性列表(指针的指针) */

};

其中 attribute定义为:

struct attribute {

char *name;/*属性的名字(在kobject的sysfs 目录中显示,如上文的dev、uvent)*/

struct module *owner;/*指向模块的指针(如果有), 此模块负责实现这个属性*/

mode_t mode; /*属性的保护位,modes 的宏定义在 <linux/stat.h>:例如S_IRUGO 为只读属性等等*/

}; /*default_attrs 列表中的最后一个元素必须用 0 填充*/

sysfs 系统中的属性读写是由 kobj_type->sysfs_ops 成员中的函数完成的:

struct sysfs_ops {

ssize_t (*show)(struct kobject *kobj, struct attribute *attr, char *buffer);

ssize_t (*store)(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size);

};

当用户空间读取一个属性时(如:#cat dev),内核会使用指向 kobject 的指针(kobj)和正确的属性结构(*attr)来调用show 方法,该方法将给定属性值编码进缓冲(buffer)(注意不要越界( PAGE_SIZE 字节)), 并返回实际数据长度。

也可对所有 kobject (通常指在一个kset关联的范围内)关联的属性使用同一个 show 方法,用传递到函数的 attr 指针来判断所请求的属性。有的 show 方法包含对属性名字的检查。有的show 方法会将属性结构嵌入另一个结构(本文举的例子就是用的这种方法), 这个结构包含需要返回属性值的信息,这时可用container_of 获得上层结构的指针以返回属性值的信息。

当用户空间写入一个属性时(如echo “hello” > event)内核会使用指向 kobject 的指针(kobj)和正确的属性结构(*attr)来调用store 方法。

store 方法将存在缓冲(buffer)的数据( size为数据的长度,不能超过 PAGE_SIZE )解码并保存新值到属性(*attr), 返回实际解码的字节数。store 方法只在拥有属性的写权限时才能被调用。此时注意:接收来自用户空间的数据一定要验证其合法性。如果到数据不匹配, 返回一个负的错误值。

每一个 kobject 需要有一个关联的 kobj_type 结构,指向这个结构的指针能在 2 个不同的地方找到:

(1)kobject 结构自身包含一个成员(ktype)指向kobj_type ;

struct kobject {

……

struct kobj_type * ktype;/*负责对该kobject类型进行跟踪的struct kobj_type的指针*/

……

}

(2)如果这个 kobject 是一个 kset 的成员, kset 会提供kobj_type 指针。

struct kset {

struct kobj_type * ktype; /*指向该kset对象类型的指针*/

……

}

访问属性的时候到底是用的哪个kobj_type呢?

下面这个函数用以查找指定kobject的kobj_type 指针:

static inline struct kobj_type * get_ktype(struct kobject * k)

{

if (k->kset && k->kset->ktype)

return k->kset->ktype;

else

return k->ktype;

}

上面可以看出,kset中的ktype这个类型优先于 kobject 自身中的 ktype 。因此在典型的应用中, 在 struct kobject 中的 ktype 成员被设为 NULL, 而 kset 中的ktype是实际被使用的。

下面通过跟踪class_device_create(my_class,NULL, devno, NULL,"farsight_dev");来确定ktype的使用。

1、

struct class_device *class_device_create(……)

{

……

retval = class_device_register(class_dev);

}

2、

int class_device_register(struct class_device *class_dev)

{

class_device_initialize(class_dev);

return class_device_add(class_dev);

}

3、

void class_device_initialize(struct class_device *class_dev)

{

kobj_set_kset_s(class_dev, class_obj_subsys);

kobject_init(&class_dev->kobj);

INIT_LIST_HEAD(&class_dev->node);

}

4、

#define kobj_set_kset_s(obj,subsys)

(obj)->kobj.kset = &(subsys).kset

从中可以看出名为“farsight_dev”的kobject对应的kset是class_obj_subsys.kset

5、

看看class_obj_subsys的定义

static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);

#define decl_subsys(_name,_type,_uevent_ops)

struct subsystem _name##_subsys = {

.kset = {

.kobj = { .name = __stringify(_name) },

.ktype = _type,

.uevent_ops =_uevent_ops,

}

}

所以kset对应的ktype为ktype_class_device

6、

static struct kobj_type ktype_class_device = {

.sysfs_ops????? = &class_dev_sysfs_ops,

.release??? = class_dev_release,

};

7、

static struct sysfs_ops class_dev_sysfs_ops = {

.show???? = class_device_attr_show,

.store????? = class_device_attr_store,

};

在操作上文中的“dev”或“uevent”时都是操作这个class_dev_sysfs_ops

8、

class_device_attr_show(struct kobject * kobj, struct attribute * attr,

char * buf)

{

struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);

struct class_device * cd = to_class_dev(kobj);

ssize_t ret = 0;

if (class_dev_attr->show)

ret = class_dev_attr->show(cd, buf);

return ret;

}

class_device_attr_store(struct kobject * kobj, struct attribute * attr,

const char * buf, size_t count)

{

struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);

struct class_device * cd = to_class_dev(kobj);

ssize_t ret = 0;

if (class_dev_attr->store)

ret = class_dev_attr->store(cd, buf, count);

return ret;

}

可以看出操作函数会根据to_class_dev_attr(attr);找出对应attr的class_dev_attr并调用其对应的show或store

9、

再跟踪一下上文中的dev及uvent属性的定义及其对应的操作函数

attr->attr.name = "dev";

attr->attr.mode = S_IRUGO;

attr->attr.owner = parent_class->owner;

attr->show = show_dev;

error = class_device_create_file(class_dev, attr);

static ssize_t show_dev(struct class_device *class_dev, char *buf)

{

return print_dev_t(buf, class_dev->devt);//上文中将打印出“252:0”

}

class_dev->uevent_attr.attr.name = "uevent";

class_dev->uevent_attr.attr.mode = S_IWUSR;

class_dev->uevent_attr.attr.owner = parent_class->owner;

class_dev->uevent_attr.store = store_uevent;

error = class_device_create_file(class_dev, &class_dev->uevent_attr);

static ssize_t store_uevent(struct class_device *class_dev,

const char *buf, size_t count)

{

kobject_uevent(&class_dev->kobj, KOBJ_ADD);

return count;

}

可以看出无论写入什么值都会触发KOBJ_ADD事件,内核调用kobject_uevent函数发送netlink message给用户空间用户层,用户空间可以用udev通过取到此事件,从而处理热插拔事件。

“本文由华清远见http://www.embedu.org/index.htm提供”



华清远见

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

为了满足日益增长的数据处理需求,铁威马NAS推出了全新的性能巅峰2024年旗舰之作F4-424 Pro,并搭载了最新的操作系统--TOS 6。这款高效办公神器的问世,无疑将为企业和专业人士带来前所未有的便捷与效率。

关键字: 存储 Linux 服务器

上海2024年4月16日 /美通社/ -- 4月14日,为期四天的第89届中国国际医疗器械博览会(CMEF)盛大收官。澳鹏Appen很荣幸再次作为唯一的人工智能训练数据参展商参与此次"航母级"规模医疗...

关键字: APP 医疗器械 PEN 模型

福州2024年4月16日 /美通社/ -- 4月15日,第61届中国高等教育博览会(以下简称“高博会”)于福州隆重开幕。索贝以“视听新体验•数智向未来,让知识传递更加精准高效”为主题,携全新升级的智慧教育资源管理平台、课...

关键字: 模型 数字化 AI算法 质量评估

往复泵是一种重要的流体输送设备,广泛应用于化工、石油、制药、冶金等领域。其工作原理基于活塞在泵缸内的往复运动,通过改变泵缸内的容积来实现液体的吸入和排出。本文将详细阐述往复泵的工作原理、结构特点、性能参数以及应用领域,以...

关键字: 往复泵 泵缸 设备

未知语音经过话筒变换成电信号后加在识别系统的输入端,首先经过预处理,再根据人的语音特点建立语音模型,对输入的语音信号进行分析。

关键字: 语音识别 语音 模型

通过大量的数据,训练出一个能处理此类数据的模型,使得这个模型可以根据已知的数据,准确率很高的判断出未知的数据,从而使得人类能够采取正确的方法去处理某些事情。

关键字: 机器学习 模型 图像

双系统将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对双系统的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 双系统 Windows Linux

液相色谱法是一种高效、快速的分离分析技术,广泛应用于化学、生物、医药等领域。液相色谱仪作为实现液相色谱分析的设备,具有高效、高分辨率、高灵敏度等特点。本文将详细介绍液相色谱仪的操作步骤、原理以及应用。

关键字: 液相色谱法 分离分析技术 设备

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机
关闭
关闭