1.通知链表简介(从网上的一篇文章中找到的关于通知链的介绍,我直接拿来引用下)
大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制。通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知。
通知链表是一个函数链表,链表上的每一个节点都注册了一个函数。当某个事情发生时,链表上所有节点对应的函数就会被执行。所以对于通知链表来说有一个通知方与一个接收方。在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通知方注册了某个函数,在发生某个事件时这些函数就得到执行。其实和系统调用signal的思想差不多。
2.通知链实现的核心思想就是回调函数的思想。
3.具体实现:以下以网卡的netdev_chain通知链为例,来讲解通知链的实现。具体代码见linux-2.6.18/net/ipv4/Fib_frontend.c的ip_fib_init()函数
//该网卡通知链的回调函数
- static struct notifier_block fib_netdev_notifier = {
- .notifier_call =fib_netdev_event,
- };
- //调用 创建通知链的函数
- register_netdevice_notifier(&fib_netdev_notifier);
- //创建通知链的函数
- int register_netdevice_notifier(struct notifier_block *nb)
- {
- struct net_device *dev;
- int err;
- rtnl_lock();
- err = raw_notifier_chain_register(&netdev_chain, nb);
- if (!err) {
- for (dev = dev_base; dev; dev = dev->next) {
- nb->notifier_call(nb, NETDEV_REGISTER, dev);
- if (dev->flags & IFF_UP)
- nb->notifier_call(nb, NETDEV_UP, dev);
- }
- }
- rtnl_unlock();
- return err;
- }
- --------------------------------------------------------------------------------------------------------
- //以下为调用通知链的过程
- //调用通知链函数
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
- unsigned long val, void *v)
- {
- int ret;
- down_read(&nh->rwsem);
- ret = notifier_call_chain(&nh->head, val, v);
- up_read(&nh->rwsem);
- return ret;
- }
- static int __kprobes notifier_call_chain(struct notifier_block **nl,
- unsigned long val, void *v)
- {
- int ret = NOTIFY_DONE;
- struct notifier_block *nb, *next_nb;
- nb = rcu_dereference(*nl);
- while (nb) {
- next_nb = rcu_dereference(nb->next);
- //这个函数就是创建通知链时的回调函数,即fib_netdev_event()函数
ret = nb->notifier_call(nb, val, v);
- if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
- break;
- nb = next_nb;
- }
- return ret;
- }
阅读(1544) | 评论(0) | 转发(0) |