在可插拔的总线如USB(和CardbusPCI)中,终端用户在主机运行时将设备插入到总线上。在大部分情况下,用户期望设备立即可用。这意味着系统必须作许多事情,包括:
-
找到一个可以处理设备的驱动。它可能包括装载一个内核模块,较新的驱动可以用模块初始化工具将设备的支持发布到用户应用工具集中。
-
将一个驱动绑定到该设备中。总线框架使用设备驱动的probe()函数来为该设备绑定一个驱动。
-
告诉其他的子系统配置新的设备。打印队列可能被使能,网络被开启,磁盘分区被挂载等等。在一些情况下,还会有一些驱动相关的动作。
PolicyAgent:是指当发生热插拔事件时,被内核触发的用户空间程序(如/sbin/hotplug)。通常这些程序是一些shell脚本,通过该脚本去调用更多的管理工具。
这种机制主要是通过kobject对象模型来实现的。
热插拔相关接口函数:
/**
* kobject_uevent - notify userspace by ending an uevent
*
* @action: action that is happening
* @kobj: struct kobject that the action is happening to
*
* Returns 0 if kobject_uevent() is completed with success or the
* corresponding error when it fails.
*/
int kobject_uevent(struct kobject *kobj, enum kobject_action action);
相当于kobject_uevent_env(kobj, action, NULL);
/**
* kobject_uevent_env - send an uevent with environmental data
*
* @action: action that is happening
* @kobj: struct kobject that the action is happening to
* @envp_ext: pointer to environmental data
*
* Returns 0 if kobject_uevent() is completed with success or the
* corresponding error when it fails.
*/
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp[]);
/**
* add_uevent_var - add key value string to the environment buffer
* @env: environment buffer structure
* @format: printf format for the key=value pair
*
* Returns 0 if environment variable was added successfully or -ENOMEM
* if no space was available.
*/
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
__attribute__((format (printf, 2, 3)));
/**
* kobject_action_type - translate action string to numeric type
*
* @buf: buffer containing the action string, newline is ignored
* @len: length of buffer
* @type: pointer to the location to store the action type
*
* Returns 0 if the action string was recognized.
*/
int kobject_action_type(const char *buf, size_t count,
enum kobject_action *type);
相关数据结构:
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOVE,
KOBJ_ONLINE,
KOBJ_OFFLINE,
KOBJ_MAX
};
/* the strings here must match the enum in include/linux/kobject.h */
static const char *kobject_actions[] = {
[KOBJ_ADD] = "add",
[KOBJ_REMOVE] = "remove",
[KOBJ_CHANGE] = "change",
[KOBJ_MOVE] = "move",
[KOBJ_ONLINE] = "online",
[KOBJ_OFFLINE] = "offline",
};
struct kobj_uevent_env {
char *envp[UEVENT_NUM_ENVP];
int envp_idx;
char buf[UEVENT_BUFFER_SIZE];
int buflen;
};
//热插拔事件相关操作
struct kset_uevent_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);//事件过滤函数
const char *(*name)(struct kset *kset, struct kobject *kobj);//获取总线名称,如USB
int (*uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env);//提交热插拔事件
};
相关函数:
struct kset *kset_create_and_add(const char *name,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj);
其中structkset_uevent_ops中指定具体的uevent函数。