codecamp

14.3. 热插拔事件产生

14.3. 热插拔事件产生

一个热插拔事件是一个从内核到用户空间的通知, 在系统配置中有事情已经改变. 无论何时一个 kobject 被创建或销毁就产生它们. 这样事件被产生, 例如, 当一个数字摄像头使用一个 USB 线缆插入, 当一个用户切换控制台模式, 或者当一个磁盘被重新分区. 热插拔事件转变为一个对 /sbin/hotplug 的调用, 它响应每个事件, 通过加载驱动, 创建设备节点, 安装分区, 或者采取任何其他的合适的动作.

我们所见的最后一个主要的 kobject 函数是这些事件的产生. 实际的事件在当一个 kobject 传递到 kobject_add 或 kobject_del 时发生. 在这个事件被传递到用户空间之前, 和这个 kobject 关联的代码( 或者, 更特别的, 它所属的 kset )有机会来添加信息给用户空间或者来完全关闭事件的产生.

14.3.1. 热插拔操作

热插拔事件的实际控制是通过一套存储于 kset_hotplug_ops 结构的方法完成.


struct kset_hotplug_ops {
 int (*filter)(struct kset *kset, struct kobject *kobj);
 char *(*name)(struct kset *kset, struct kobject *kobj);
 int (*hotplug)(struct kset *kset, struct kobject *kobj,
 char **envp, int num_envp, char *buffer,
 int buffer_size);
};

一个指向这个结构的指针在 kset 结构的 hotplug_ops 成员中. 如果一个给定的 kobject 不包含在一个 kset 中, 内核搜索整个层次( 通过 parent 指针) 直到它发现一个 kobject 确实有一个 kset; 接着使用这个 kset 的热插拔操作.

filter 热插拔操作被调用无论何时内核在考虑为给定 kobject 产生一个事件. 如果 filter 返回 0, 事件没有创建. 这个方法, 因此, 给 kset 代码一个机会来决定哪个事件应当被传递给用户空间以及哪个不.

作为一个例子关于这个方法怎样被使用, 考虑块设备子系统. 至少有 3 类 kobject 用在那里, 表示磁盘, 分区, 和请求队列. 用户空间可能想对磁盘或分区的增加作出反应, 但是它正常地不关心请求队列. 因此 filter 方法允许事件产生只给代表磁盘和分区的 kobjects. 它看来如此:


static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
{

 struct kobj_type *ktype = get_ktype(kobj);
    return ((ktype == &ktype_block) || (ktype == &ktype_part));
}

这里, 一个快速的在 kobject 类型上的测试是足以决定是否这个事件应当产生或者不.

当用户空间热插拔程序被调用, 它被传递给相关子系统的 name 作为它唯一的一个参数. name 热插拔方法负责提供这个名子. 它应当返回一个简单的适合传递给用户空间的字串.

热插拔脚本的可能想知道的其他所有东东都在环境中传递. 最终的热插拔方法( hotplug )给了一个机会来在调用这个脚本之前添加有用的环境变量. 再次, 这个方法的原型是:


int (*hotplug)(struct kset *kset, struct kobject *kobj,
 char **envp, int num_envp, char *buffer,
 int buffer_size); 

如常, kset 和 kobject 描述事件产生给的对象. envp 数组是一个地方来存储额外的环境变量定义(以通常的 NAME=值 的格式); 它有 num_envp 个入口变量. 这些变量自身应当被编码入缓冲, 缓冲是 buffer_size 字节长. 如果你添加任何变量到 envp, 确信添加一个 NULL 入口在你最后的添加项后面, 这样内核知道结尾在哪里. 返回值正常应当是 0; 任何非零返回都终止热插拔事件的产生.

热插拔事件的产生(象在设备模型中大部分工作)常常是由在总线驱动级的逻辑处理.

14.2. 低级 sysfs 操作
14.4. 总线, 设备, 和驱动
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }