在新版本的内核中struct device 已经没有bus_id成员,取而代之的是通过dev_name和dev_set_name对设备的名字进行操作。
dev_name和dev_set_name在2.6.35.6内核中的源代码如下:
static inline const char *dev_name(const struct device *dev)
{
/* Use the init name until the kobject becomes available */
if (dev->init_name)
return dev->init_name;
return kobject_name(&dev->kobj);
}
extern int dev_set_name(struct device *dev, const char *name, ...)
__attribute__((format(printf, 2, 3)));
kernel 邮件列表
中讲了:struct device - replace bus_id with dev_name(),以后只要使用dev->bus_id的时候,改成dev_name(dev)就可以了。
第四章:linux内核模块:
4.5,模块被加载后,在/sys/module/目录下将出现以此模块名命名的目录。当“参数读/写权限”为 0 时,表示此参数不存在 sysfs 文件系统下对应的文件节点,如果此模块存在“参数读/写权限”不为 0的命令行参数,在此模块的目录下还将出现 parameters目录,包含一系列以参数名命名的文件节点,这些文件的权限值就是传入module_param()的“参数读/写权限” ,而文件的内容为参数的值。
4.6,导出符号:
模块可以使用如下宏导出符号到内核符号表:
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
导 出的 符号 将可 以 被 其 他 模块 使用 , 使用 前 声明 一 下 即 可 。
4.8,模块的使用计数
Linux 2.6 内核提供了模块计数管理接口 try_module_get(&module)和 module_put(&module),
int try_module_get(struct module *module);
该函数用于增加模块使用计数;若返回为 0,表示调用失败,希望使用的模块没有被加载或正在被卸载中。
void module_put(struct module *module);
该函数用于减少模块使用计数。
第 5 章 Linux文件系统与设备文件系统
1.file结构体
文件结构体代表一个打开的文件(设备对应于设备文件) ,系统中每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核和驱动源代码中,struct file的指针通常被命名为 file 或 filp(即 file pointer)。代码清单 5.3给出了文件结构体的定义。
2.inode结构体
VFS inode 包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间等信息。它是Linux 管理文件系统的最基本单位,也是文件系统连接任何子目录、文件的桥梁,inode结构体的定义如代码清单5.4所示。
5.4.1 udev与devfs的区别
取代 devfs的几点原因:
1.devfs所做的工作被确信可以在用户态来完成。
2.一些bug相当长的时间内未被修复。
3.devfs的维护者和作者停止了对代码的维护工作。
udev 完全在用户态工作,利用设备加入或移除时内核所发送的热插拔事件(hotplug event)来工作。在热插拔时,设备的详细信息会由内核输出到位于/sys的sysfs文件系统。udev的设备命名策略、权限控制和事件处理都是在用户态下完成的,它利用sysfs中的信息来进行创建设备文件节点等工作。
5.4.2 sysfs文件系统与Linux设备模型
1.sysfs 文件系统
sysfs把连接在系统上的设备和总线组织成为一个分级的文件, 它们可以由用户空间存取,向用户空间导出内核数据结构以及它们的属性。sysfs的一个目的就是展示设备驱动模型中各组件的层次关系,其顶级目录包括block、device、bus、drivers、class、power 和 firmware。
2.kobject内核对象
kobject是Linux 2.6 引入的设备管理机制,在内核中由kobject结构体表示,这个数据结构使所有设备在底层都具有统一的接口。kobject提供了基本的对象管理能力,是构成 Linux 2.6 设备模型的核心结构,每个在内核中注册的 kobject 对象都对应于sysfs文件系统中的一个目录。
kobject结构体的定义如代码清单 5.6所示。
1 struct kobject
2 {
3 char *k_name;
4 char name[KOBJ_NAME_LEN]; //对象名称
5 struct kref kref; //对象引用计数
6 struct list_head entry; //用于挂接该kobject对象到kset链表
7 struct kobject *parent; //指向父对象的指针
8 struct kset *kset; //所属kset的指针
9 struct kobj_type *ktype; //指向对象类型描述符的指针
10 struct dentry *dentry; //sysfs文件系统中与该对象对应的文件节点入口
11 };
内核通过 kobject 的 kref 成员实现对象引用计数管理,且提供两个函数kobject_get()、kobject_put()分别用于增加和减少引用计数;
kobj_type 数据结构包含 3 个成员:用于释放 kobject 占用的资源的release()函数、指向sysfs操作的 sysfs_ops指针和sysfs文件系统默认属性列表。
1 struct kobj_type
2 {
3 void (*release)(struct kobject *);//release函数
4 struct sysfs_ops * sysfs_ops;//属性操作
5 struct attribute ** default_attrs;//默认属性
6 };
kobj_type 结构体种的 sysfs_ops 包括 store()和 show()两个成员函数,用于实现属性的读写;
Linux内核中提供一系列操作kobject的函数:
void kobject_init(struct kobject * kobj);
该函数用于初始化 kobject,它设置kobject引用计数为1,entry域指向自身,其所属 kset引用计数加1。
int kobject_set_name(struct kobject *kobj, const char *format, ...);
该函数用于设置指定kobject的名称。
void kobject_cleanup(struct kobject * kobj) 和 void kobject_release(struct kref *kref);
该函数用于清除kobject,当其引用计数为0时,释放对象占用的资源。
struct kobject *kobject_get(struct kobject *kobj);
该函数用于将kobj 对象的引用计数加1,同时返回该对象的指针。
void kobject_put(struct kobject * kobj);
该函数用于将 kobj 对象的引用计数减 1,如果引用计数降为 0,则调用
kobject_release()释放该 kobject对象。
int kobject_add(struct kobject * kobj);
该函数用于将 kobject 对象加入 Linux 设备层次,它会挂接该 kobject 对象到 kset的 list链中,增加父目录各级kobject的引用计数,在其parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数。
int kobject_register(struct kobject * kobj);
该函数用于注册kobject, 它会先调用kobject_init()初始化kobj, 再调用kobject_add()完成该内核对象的添加。
void kobject_del(struct kobject * kobj);
这个函数是kobject_add()的反函数, 它从Linux设备层次(hierarchy)中删除 kobject对象。
void kobject_unregister(struct kobject * kobj);
这个函数是 kobject_register()的反函数,用于注销 kobject。与 kobject_register()相反,它首先调用kobject_del()从设备层次中删除该对象,再调用 kobject_put()减少该对象的引用计数,如果引用计数降为0,则释放该kobject对象。
阅读(226) | 评论(0) | 转发(0) |