通知链(Notifier Chains):
通知链用于向请求通知的代码区发送状态变化消息。
有几个内核中预定义的通知器:
l Die Notification: 当一个内核函数触发了一个由“opps”引起的陷阱或错误时。
l Net device notification:当一个网卡禁用或启用时,
l CPU frequency notification:当处理器频率发生变化时
l Internet address notification:当一个网卡IP地址发生变化时
自定义通知链:
使用BLOCKING_NOTIFIER_HEAD()初始化,通过blocking_notifier_chain_register()来注册通知链。在中断上下文中,使用ATOMIC_NOTIFIER_HEAD()初始化,通过atomic_notifier_chain_register()来注册通知链。
代码示例:
#include <linux/notifier.h>
#include <linux/kdebug.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
extern int register_die_notifier(struct notifier_block *nb);
extern int unregister_die_notifier(struct notifier_block *nb);
/* Die notification event handler */
int my_die_event_handler(struct notifier_block *self, unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
if (val == 1) { /* '1' corresponds to an "oops" */
printk("my_die_event: OOPs! at EIP=%lx\n", args->regs->eip);
} /* else ignore */
return 0;
}
/* Die Notifier Definition */
static struct notifier_block my_die_notifier = {
.notifier_call = my_die_event_handler,
};
/* Net Device notification event handler */
int my_dev_event_handler(struct notifier_block *self,
unsigned long val, void *data)
{
printk("my_dev_event: Val=%ld, Interface=%s\n", val,
((struct net_device *) data)->name);
return 0;
}
/* Net Device notifier definition */
static struct notifier_block my_dev_notifier = {
.notifier_call = my_dev_event_handler,
};
/* User-defined notification event handler */
int my_event_handler(struct notifier_block *self,
unsigned long val, void *data)
{
printk("my_event: Val=%ld\n", val);
return 0;
}
/* User-defined notifier chain implementation */
static BLOCKING_NOTIFIER_HEAD(my_noti_chain);
static struct notifier_block my_notifier = {
.notifier_call = my_event_handler,
};
/* Driver Initialization */
static int __init
my_init(void)
{
/* ... */
/* Register Die Notifier */
register_die_notifier(&my_die_notifier);
/* Register Net Device Notifier */
register_netdevice_notifier(&my_dev_notifier);
/* Register a user-defined Notifier */
blocking_notifier_chain_register(&my_noti_chain, &my_notifier);
/* ... */
return 0;
}
//驱动模块初始化函数
static int __init hello3_init(void)
{
my_init();
blocking_notifier_call_chain(&my_noti_chain, 100, NULL);
return 0;
}
module_init(hello3_init);
//驱动模块注册函数
static void __exit hello3_exit(void)
{
unregister_die_notifier(&my_die_notifier);
unregister_netdevice_notifier(&my_dev_notifier);
blocking_notifier_chain_unregister(&my_noti_chain, &my_notifier);
}
module_exit(hello3_exit);