这最基本的三个接口分别实现了对通知链上通知块的注册、卸载和遍历操作,可以想象,原子通知链、可阻塞通知链和原始通知链一定会对基本通知链的操作函数再进行一次包装的,事实也确实如此:
// 注册函数extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *nb);extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb);extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb);extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *nb);extern int blocking_notifier_chain_cond_register( struct blocking_notifier_head *nh, struct notifier_block *nb);// 卸载函数extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *nb);extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb);extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb);extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, struct notifier_block *nb);// 遍历操作extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v);extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls);extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v);extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls);extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v);extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls);extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v);extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls);上述这四类通知链的基本API又构成了内核中其他子系统定义、操作自己通知链的基础 。例如,Netlink定义了一个原子通知链,所以,它对原子通知链的基本API又封装了一层,以形成自己的特色:
static ATOMIC_NOTIFIER_HEAD(netlink_chain);int netlink_register_notifier(struct notifier_block *nb){ return atomic_notifier_chain_register(&netlink_chain, nb);}EXPORT_SYMBOL(netlink_register_notifier);int netlink_unregister_notifier(struct notifier_block *nb){ return atomic_notifier_chain_unregister(&netlink_chain, nb);}EXPORT_SYMBOL(netlink_unregister_notifier);网络事件也有一个原子通知链(net/core/netevent.c):
/* * Network event notifiers * * Authors: * Tom Tucker <tom@opengridcomputing.com> * Steve Wise <swise@opengridcomputing.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Fixes: */#include <linux/rtnetlink.h>#include <linux/notifier.h>#include <linux/export.h>#include <net/netevent.h>static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);/** * register_netevent_notifier - register a netevent notifier block * @nb: notifier * * Register a notifier to be called when a netevent occurs. * The notifier passed is linked into the kernel structures and must * not be reused until it has been unregistered. A negative errno code * is returned on a failure. */int register_netevent_notifier(struct notifier_block *nb){ int err; err = atomic_notifier_chain_register(&netevent_notif_chain, nb); return err;}EXPORT_SYMBOL_GPL(register_netevent_notifier);/** * netevent_unregister_notifier - unregister a netevent notifier block * @nb: notifier * * Unregister a notifier previously registered by * register_neigh_notifier(). The notifier is unlinked into the * kernel structures and may then be reused. A negative errno code * is returned on a failure. */int unregister_netevent_notifier(struct notifier_block *nb){ return atomic_notifier_chain_unregister(&netevent_notif_chain, nb);}EXPORT_SYMBOL_GPL(unregister_netevent_notifier);/** * call_netevent_notifiers - call all netevent notifier blocks * @val: value passed unmodified to notifier function * @v: pointer passed unmodified to notifier function * * Call all neighbour notifier blocks. Parameters and return value * are as for notifier_call_chain(). */int call_netevent_notifiers(unsigned long val, void *v){ return atomic_notifier_call_chain(&netevent_notif_chain, val, v);}EXPORT_SYMBOL_GPL(call_netevent_notifiers);运作机制
通知链的运作机制包括两个角色:
- 被通知者:对某一事件感兴趣一方 。定义了当事件发生时,相应的处理函数,即回调函数,被通知者将其注册到通知链中(被通知者注册的动作就是在通知链中增加一项) 。
推荐阅读
- 录取通知书没写市能寄到吗 录取通知书能寄到农村里吗
- 查找 Linux 发行版名称、版本和内核详细信息
- 无比强大的Linux ls命令家族,你会几个
- linux下.tar.gz和.gz文件解压详解
- Linux安装Nginx
- 全面解析 Linux Load
- 网络工程师史上最全cmd命令大全,含Windows和Linux系统
- Linux文件安全与权限
- 面试完之后,HR让你回去等通知?3招教你判断面试结果
- Linux 下各文件夹的结构说明及用途介绍
