Chinaunix首页 | 论坛 | 博客
  • 博客访问: 350958
  • 博文数量: 63
  • 博客积分: 1412
  • 博客等级: 中尉
  • 技术积分: 648
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-10 23:07
文章分类

全部博文(63)

文章存档

2012年(42)

2011年(21)

我的朋友

分类: C/C++

2011-03-11 20:23:52

1.通知链表简介(从网上的一篇文章中找到的关于通知链的介绍,我直接拿来引用下)
    大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制。通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知。
    通知链表是一个函数链表,链表上的每一个节点都注册了一个函数。当某个事情发生时,链表上所有节点对应的函数就会被执行。所以对于通知链表来说有一个通知方与一个接收方。在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通知方注册了某个函数,在发生某个事件时这些函数就得到执行。其实和系统调用signal的思想差不多。

 

2.通知链实现的核心思想就是回调函数的思想。

 

3.具体实现:以下以网卡的netdev_chain通知链为例,来讲解通知链的实现。具体代码见linux-2.6.18/net/ipv4/Fib_frontend.c的ip_fib_init()函数

 

 

      //该网卡通知链的回调函数
  1. static struct notifier_block fib_netdev_notifier = {
  2.     .notifier_call =fib_netdev_event,
  3. };
  4. //调用 创建通知链的函数
  5. register_netdevice_notifier(&fib_netdev_notifier);
  6. //创建通知链的函数
  7. int register_netdevice_notifier(struct notifier_block *nb)
  8. {
  9.     struct net_device *dev;
  10.     int err;

  11.     rtnl_lock();
  12.     err = raw_notifier_chain_register(&netdev_chain, nb);
  13.     if (!err) {
  14.         for (dev = dev_base; dev; dev = dev->next) {
  15.             nb->notifier_call(nb, NETDEV_REGISTER, dev);

  16.             if (dev->flags & IFF_UP)
  17.                 nb->notifier_call(nb, NETDEV_UP, dev);
  18.         }
  19.     }
  20.     rtnl_unlock();
  21.     return err;
  22. }
  23. --------------------------------------------------------------------------------------------------------
  24. //以下为调用通知链的过程
  25. //调用通知链函数
  26.   int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
  27.         unsigned long val, void *v)
  28. {
  29.     int ret;

  30.     down_read(&nh->rwsem);
  31.     ret = notifier_call_chain(&nh->head, val, v);
  32.     up_read(&nh->rwsem);
  33.     return ret;
  34. }

  35. static int __kprobes notifier_call_chain(struct notifier_block **nl,
  36.         unsigned long val, void *v)
  37. {
  38.     int ret = NOTIFY_DONE;
  39.     struct notifier_block *nb, *next_nb;

  40.     nb = rcu_dereference(*nl);
  41.     while (nb) {
  42.         next_nb = rcu_dereference(nb->next);
  43.         //这个函数就是创建通知链时的回调函数,即fib_netdev_event()函数
  44.           ret = nb->notifier_call(nb, val, v);
  45.         if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
  46.             break;
  47.         nb = next_nb;
  48.     }
  49.     return ret;
  50. }

 

 

阅读(1544) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~