深入理解Linux网络技术内幕——Notification内核通知表链
If (subsystem_X_enabled) { do_something_1 } if (subsystem_Y_enabled) { do_something_2 } If (subsystem_Z_enabled) { do_something_3 } ... ... ...
//通知块 struct notifier_block { int (*notifier_call)(struct notifier_block *self, unsigned long, void *);//回调函数 struct notifier_block *next; // int priority; //注册的优先级,用户自行指定,优先级越高回调函数就越早执行 };
//原子通知表链 struct atomic_notifier_head { spinlock_t lock; struct notifier_block __rcu *head; }; //可阻塞通知表链 struct blocking_notifier_head { struct rw_semaphore rwsem; struct notifier_block __rcu *head; }; //原始通知表链 struct raw_notifier_head { struct notifier_block __rcu *head; }; //可阻塞通知表链的变体 struct srcu_notifier_head { struct mutex mutex; struct srcu_struct srcu; struct notifier_block __rcu *head; };
static RAW_NOTIFIER_HEAD(netdev_chain);
#define ATOMIC_NOTIFIER_HEAD(name) struct atomic_notifier_head name = ATOMIC_NOTIFIER_INIT(name) #define BLOCKING_NOTIFIER_HEAD(name) struct blocking_notifier_head name = BLOCKING_NOTIFIER_INIT(name) #define RAW_NOTIFIER_HEAD(name) struct raw_notifier_head name = RAW_NOTIFIER_INIT(name)
#define ATOMIC_NOTIFIER_INIT(name) { .lock = __SPIN_LOCK_UNLOCKED(name.lock), .head = NULL } #define BLOCKING_NOTIFIER_INIT(name) { .rwsem = __RWSEM_INITIALIZER((name).rwsem), .head = NULL } #define RAW_NOTIFIER_INIT(name) { .head = NULL } /* srcu_notifier_heads cannot be initialized statically */
int notifier_chain_register(struct notifier_block **list, struct notifier_block *n) int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
int register_netdevice_notifier(struct notifier_block *nb) { raw_notifier_chain_register(&netdev_chain, nb); } int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *n) { return notifier_chain_register(&nh->head, n); }
static int __kprobes notifier_call_chain(struct notifier_block **nl, unsigned long val, void *v, int nr_to_call, int *nr_calls) { int ret = NOTIFY_DONE; struct notifier_block *nb, *next_nb; nb = rcu_dereference_raw(*nl); while (nb && nr_to_call) { next_nb = rcu_dereference_raw(nb->next); #ifdef CONFIG_DEBUG_NOTIFIERS if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) { WARN(1, "Invalid notifier called!"); nb = next_nb; continue; } #endif ret = nb->notifier_call(nb, val, v); if (nr_calls) (*nr_calls)++; if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) break; nb = next_nb; nr_to_call--; } return ret; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。