通知链netdev_chain和inetaddr_chain区别以及使用

参考文献:《深入理解linux网络技术内幕》

《精通linux内核网络》

代码内核版本:3.1.68

...............................................................................................

1. 初始化

ip_fib_init()

这个函数看似复杂,其实就主要作两件事:

  1) 把参数struct notifier_block *nb 注册到netdev_chain通知链上去

  2) 系统中所有已经被注册过或激活的网络设备的事件都要被新增的这个通知的回调函数重新调用一遍,这样让设备更新到一个完整的状态

  在 路由子系统初始化时,系统会调用ip_fib_init() 函数,ip_fib_init() 中会注册一个回调函数到netdev_chain通知链,这样当别的子系统通知netdev_chain上有特定的事件类型发生时,路由子系统的相应回调 函数就可以作一些反应。

1181 void __init ip_fib_init(void)
1182 {
1183     fib_trie_init();
1184
1185     register_pernet_subsys(&fib_net_ops);
1186
1187     register_netdevice_notifier(&fib_netdev_notifier);
1188     register_inetaddr_notifier(&fib_inetaddr_notifier);
1189
1190     rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL);
1191     rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL);
1192     rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL);
1193 }  

(1) int register_netdevice_notifier(struct notifier_block *nb)
功能: 在内核通知链netdev_chain上注册消息块,用来接收有关网络设备的注册状态等信息
nb:消息块,在里面自己添加消息处理函数
返回值:成功返回0
头文件:#include <linux/netdevice.h>

(2) int unregister_netdevice_notifier(struct notifier_block *nb)
功能:与上面register_netdevice_notifier为一对,用于在通知链netdev_chain上删除消息块

(3) int register_inetaddr_notifier(struct notifier_block *nb)
功能: 在内核通知链inetaddr_chain上注册消息块,用于接收ip地址的改变等事件
nb:消息块,在里面自己添加消息处理函数
返回值:成功返回0
头文件: #include <linux/inetdevice.h>

(4) int unregister_inetaddr_notifier(struct notifier_block *nb)
功能:与上面register_inetaddr_notifier为一对,用于在通知链inetaddr_chain上删除消息块

fib_netdev_notifier的定义:

  static struct notifier_block fib_netdev_notifier = {

         .notifier_call =fib_netdev_event,

  };

  fib_netdev_notifier就是一个struct notifier_block,其中.priority默认初始化为0,.next由注册时设定

事件说明
  #define NETDEV_UP    0x0001//激活一个网络设备
  #define NETDEV_DOWN    0x0002//停止一个网络设备,所有对该设备的引用都应释放
  #define NETDEV_REBOOT    0x0003 //检查到网络设备接口硬件崩溃,硬件重启
  #define NETDEV_CHANGE    0x0004 //网络设备的数据包队列状态发生改变
  #define NETDEV_REGISTER 0x0005//一个网络设备事例注册到系统中,但尚未激活
  #define NETDEV_UNREGISTER    0x0006//网络设备驱动已卸载
  #define NETDEV_CHANGEMTU    0x0007//MTU发生了改变
  #define NETDEV_CHANGEADDR    0x0008//硬件地址发生了改变
  #define NETDEV_GOING_DOWN    0x0009//网络设备即将注销,有dev->close报告,通知相关子系统处理
  #define NETDEV_CHANGENAME    0x000A//网络设备名改变
  #define NETDEV_FEAT_CHANGE    0x000B//网络硬件功能改变

  再来大致看一下函数fib_netdev_event() :

1046 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1047 {
1048     struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1049     struct netdev_notifier_info_ext *info_ext = ptr;
1050     struct in_device *in_dev;
1051     struct net *net = dev_net(dev);
1052
1053     if (event == NETDEV_UNREGISTER) {
1054         fib_disable_ip(dev, 2);
1055         rt_flush_dev(dev);
1056         return NOTIFY_DONE;
1057     }
1058
1059     in_dev = __in_dev_get_rtnl(dev);
1060     if (!in_dev)
1061         return NOTIFY_DONE;
1062
1063     switch (event) {
1064     case NETDEV_UP://激活一个网络设备
1065         for_ifa(in_dev) {
1066             fib_add_ifaddr(ifa);
1067         } endfor_ifa(in_dev);
1068 #ifdef CONFIG_IP_ROUTE_MULTIPATH
1069         fib_sync_up(dev);
1070 #endif
1071         atomic_inc(&net->ipv4.dev_addr_genid);
1072         rt_cache_flush(net);
1073         break;
1074     case NETDEV_DOWN://停止一个网络设备,所有对该设备的引用都应释放
1075         fib_disable_ip(dev, 0);
1076         break;
1077     case NETDEV_CHANGEMTU:
1078         fib_sync_mtu(dev, info_ext->ext.mtu);
1079         rt_cache_flush(net);
1080         break;
1081     case NETDEV_CHANGE:
1082         rt_cache_flush(net);
1083         break;
1084     }
1085     return NOTIFY_DONE;
1086 }

使用举例

 1 #include <linux/module.h>
 2 #include <linux/init.h>
 3 #include <linux/kernel.h>
 4 #include <linux/types.h>
 5 #include <linux/netdevice.h>
 6 #include <linux/inetdevice.h>
 7
 8 //处理网络设备的启动与禁用等事件
 9 int test_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
10 {
11    struct net_device *dev = (struct net_device *)ptr;
12     switch(event)
13     {
14         case NETDEV_UP:
15              if(dev && dev->name)
16                  printk("test dev[%s] is up\n",dev->name);
17              break;
18         case NETDEV_DOWN:
19              if(dev && dev->name)
20                  printk("test  dev[%s] is down\n",dev->name);
21                 break;
22         default:
23              break;
24     }
25
26     return NOTIFY_DONE;
27 }
28
29 //处理ip地址的改变事件
30 int test_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
31 {
32
33     struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
34     struct net_device *dev = NULL;
35
36     if(ifa && ifa->ifa_dev)
37         dev = ifa->ifa_dev->dev;
38
39     switch(event)
40     {
41         case NETDEV_UP:
42             if(dev && dev->name)
43                  printk("inet[%p] is up\n",dev->name);
44             break;
45         case NETDEV_DOWN:
46              if(dev && dev->name)
47                  printk("inet[%p] is down\n",dev->name);
48         default:
49             break;
50
51     }
52
53     return NOTIFY_OK;
54 }
55
56 struct notifier_block inethandle={
57     .notifier_call = test_inetaddr_event
58 };
59
60 struct notifier_block devhandle={
61     .notifier_call = test_netdev_event
62 };
63
64 static int __init  net_event_init(void)
65 {
66     /*
67        在netdev_chain通知链上注册消息块
68        netdev_chain通知链是内核中用于传递有关网络设备注册状态的通知信息
69     */
70     register_netdevice_notifier(&devhandle);
71
72     /*
73       在inetaddr_chain通知链上注册消息块
74       inetaddr_chain通知链是内核中用于传递有关本地接口上的ipv4地址的插入,删除以及变更的通知信息
75     */
76     register_inetaddr_notifier(&inethandle);
77     return 0;
78 }
79
80 static void __exit net_event_exit(void)
81 {
82     unregister_netdevice_notifier(&devhandle);
83     unregister_inetaddr_notifier(&inethandle);
84     return;
85 }
86
87
88 module_init(net_event_init);
89 module_exit(net_event_exit);
90 MODULE_LICENSE("GPL");

原文地址:https://www.cnblogs.com/mysky007/p/12251382.html

时间: 2024-09-28 03:25:11

通知链netdev_chain和inetaddr_chain区别以及使用的相关文章

Linux内核基础--事件通知链(notifier chain)

转载: http://blog.csdn.net/wuhzossibility/article/details/8079025 http://blog.chinaunix.net/uid-27717694-id-4286337.html 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制(notificationchain). 通知

Linux内核基础--事件通知链(notifier chain)【转】

转自:http://blog.csdn.net/wuhzossibility/article/details/8079025 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制(notificationchain). 通知链只能用在各个子系统之间,而不能在内核和用户空间进行事件的通知.组成内核的核心系统代码均位于kernel目录下,

Linux内核通知链模块

通知链描述 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制.通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知. 通知链表是一个函数链表,链表上的每一个节点都注册了一个函数.当某个事情发生时,链表上所有节点对应的函数就会被执行.所以对于通知链表来说有一个通知方与一个接收方.在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通

Linux 内核通知链机制的原理及实现

一.概念: 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子 系统,Linux内核提供了通知链的机制.通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知. 通知链表是一个函数链表,链表上的每一个节点都注册了一个函数.当某个事情发生时,链表上所有节点对应的函数就会被执行.所以对于通知链表来说有一个通知 方与一个接收方.在通知这个事件时所运行的函数由被通知方决定,实际上也即是

linux内核notifier机制 linux通知链

在linux内核系统中,各个模块.子系统之间是相互独立的.Linux内核可以通过通知链机制来获取由其它模块或子系统产生的它感兴趣的某些事件.使用notifier由通知者可以传递给被通知者长整型参数与指针.在linux中有许多地方用到,比如reboot通知,cpu调频通知,网卡事件,电池低电警报等等.熟悉使用notifier有助于linux内核驱动开发. notifier_block结构: struct notifier_block { int (*notifier_call)(struct no

内核通知链原理及机制

转载:http://blog.chinaunix.net/uid-25871104-id-3086446.html 一.概念: 大 多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系 统,Linux内核提供了通知链的机制.通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知.通知链表是一个函数链表, 链表上的每一个节点都注册了一个函数.当某个事情发生时,链表上所有节点对应的函

Linux内核调试方法总结之内核通知链

Linux内核通知链notifier 1.内核通知链表简介(引用网络资料)    大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制.通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知.    通知链表是一个函数链表,链表上的每一个节点都注册了一个函数.当某个事情发生时,链表上所有节点对应的函数就会被执行.所以对于通知链表来说有一个通知

arm-none-linux-gnueabi交叉工具链安装 ,介绍,区别总结

1.arm-none-linux-gnueabi-gcc下载 http://www.veryarm.com/arm-none-linux-gnueabi-gcc arm-none-linux-gnueabi-gcc是 Codesourcery 公司(目前已经被Mentor收购)基于GCC推出的的ARM交叉编译工具.可用于交叉编译ARM系统中所有环节的代码,包括裸机程序.u-boot.Linux kernel.filesystem和App应用程序.使用时,按照主机平台,可以下载以下任一版本中的一个

linux kernel notifier chain(事件通知链)

Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制(notification chain). struct notifier_block { int (*notifier_call)(struct notifier_block *, unsigned long, void *); struct notifier_block *next; int priorit