设备与模块
设备类型:unix系统为了统一常见设备,设定的类型
模块
内核对象
sysfs:表示设备树的文件系统
设备类型
块设备blkdevs
字符设备cdevs
网络设备
也称以太网设备,提供对网络的访问
物理适配器+特定的协议
打破了unix 一切皆文件的设计原则
通过socket api访问
杂项设备miscdevs
简化的字符设备:牺牲通用性,换取使用的方便
虚拟设备
对内核的功能扩展,伪设备pseudo devices
如随机数发生器/dev/random,空设备/dev/null,零设备/dev/zero
模块
hello, world
static int hello_init(void)
{
printk(KERN_ALERT “I bear a charmed life.\n”);
return 0;
}
/*
* hello_exit – the exit function, called when the module is removed.
*/
static void hello_exit(void)
{
printk(KERN_ALERT “Out, out, brief candle!\n”);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“Shakespeare”);
MODULE_DESCRIPTION(“A Hello, World Module”);
module_init()和module_exit()都是宏,唯一参数为初始化函数,类型为int my_init(void);
如果载入非GPL模块,不能被调试,不能调用GPL_only符号
剩下两个没啥用
构建模块
2.6内核采用kbuild,构建模块更容易,第一步选择哪里管理源码:
- 模块源码加入内核源码树
- 内核代码树外构建模块源码
安装模块
模块依赖性
必须事先生成依赖关系
depmod
生成依赖关系信息
依赖信息存放在/lib/modules/version/modules.dep
载入模块
root权限 insmod
modprobe提供了依赖性分析
modprobe module [ module paras ]
管理配置选项
对于薪资目录建立kconfig,要在存在的kconfig文件中引入
source “driver/char/fishing/Kconfig”
添加一个配置选项
config FISHING_POLE
tristate “Fish Master 3000 support”
default n
help
If you say Y here...
添加依赖型:
depends on FISH_TANK
配置系统元选项
CONFIG_BROKEN_ON_SMP:驱动非多处理器安全,用于告知风险
CONFIG——EXPERIMENTAL:告知风险
参数模块
module_param(name, type, perm);
定义的全局变量,同时出现在sysfs文件系统
perm制定了sysfs下的权限
例子
static int allow_live_bait = 1; /* default to on */
module_param(allow_live_bait, bool, 0644); /* a Boolean type */
外部参数名与内部不同:
static unsigned int max_test = DEFAULT_MAX_LINE_TEST;
module_param_named(maximum_line_test, max_test, int, 0);
导出符号表
导出内核函数,才能被模块直接使用
需要指令EXPORT_SYMBOL()和EXPORT_SYMBOL_GPL()
int get_pirate_beard_color(struct pirate *p)
{
return p->beard.color;
}
EXPORT_SYMBOL(get_pirate_beard_color);
然后get_pirate_beard_color可以被所有模块访问
确保自己的模块使用的所有接口,都被导出
设备模型
独立机制表示设备
- 重复代码最小化
- 引用计数这样的统一机制
- 所有设备以树的形式出现
- 方便关闭电源
kobject
设备模型的核心,类似对象
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent; /*构建设备树,即为sysfs*/
struct kset *kset;
struct kobj_type *ktype;
struct sysfs_dirent *sd; /*sysfs文件系统中,表示kobject的inode*/
struct kref kref; /*提供引用计数*/
...
}
通常嵌入别的结构体,如struct cdev
kobject嵌入其它机构时,该结构拥有kobject提供的标准功能
并成为层次架构的一部分
ktype
kobject type, <linux/kobject.h>中
struct kobj_type {
void (*release)(struct kobject *); /*析构函数*/
const struct sysfs_ops *sysfs_ops; //描述sysfs读写时的特性
struct attribute **default_attrs; //描述了kobject的默认属性
};
kset
kobject对象的集合体.把所有相关的kobject放到同一位置
少数的ktype,多个kset
struct kset {
struct list_head list; //链接所有kobject
spinlock_t list_lock; //保护这个链表中元素的自旋锁
struct kobject kobj; //集合元素的基类
struct kset_uevent_ops *uevent_ops; //处理集合中kobject的热插拔操作
// uevent:用户事件的缩写
};
相互关系
相同kset的kobject以独立的目录出现在文件系统
操作管理kobject
引用计数
类似inode
sysfs
虚拟文件系统,提供了kobject对象层次的视图
挂载在sys目录下
将kobject与目录项紧密联系,通过kobject中的dentry实现
目录devices
在sysfs添加删除kobject
向sysfs添加文件
1.默认属性
ktype中包含attribute结构体,定义在<linux/sysfs.h>
struct attribute{
const char *name; //属性名称,出现在sysfs中的文件名
struct module *owner;
mode_t mode; //sysfs中该文件的权限
}
sysfs_ops描述了如何使用属性
show()读属性,store()写属性
2.创建新属性
/*添加新属性,最终出现在sysfs中的文件名*/
int syss_create_file(struct kobject *kobj, const struct attribute *attr);
/*创建符号链接*/
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);
/*删除新属性*/
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
sysfs约定:
保证每个文件导出一个值,文本形式,映射为简单C类型
sysfs树形的实际用途得看源代码
17.4.3 内核事件层
内核到用户的消息通知系统
通过kobject和sysfs,能很好标识时间的源(一个sysfs路径)
int kobject_uevent(struct kobject *kobj, enum kobject_action action);
第一个参数为发送信号的kobject
第二个为描述信号的动作或动词,枚举类型,映射相应的字符串