- struct
notifier_block { -
int (*notifier_call)(struct notifier_block *, unsigned long, void *); -
struct notifier_block *next; -
int priority; - };
- int
register_inetaddr_notifier(struct notifier_block *nb){ -
return blocking_notifier_chain_register(&inetaddr_chain, nb); - }
- int
blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *n){ -
int ret; -
// 如果是在开机的时候还不具备down_write的条件 -
if (unlikely(system_state < SYSTEM_RUNNING)) -
return notifier_chain_register(&nh->head, n); -
down_write(&nh->rwsem); -
ret = notifier_chain_register(&nh->head, n); -
up_write(&nh->rwsem); -
return ret; - }
- static
int notifier_chain_register(struct notifier_block **nl,struct notifier_block *n){ -
// 找到链表的尾部 -
while ((*nl) != NULL) { -
if (n->priority > (*nl)->priority) -
break; -
nl = &((*nl)->next); -
} -
n->next = *nl; -
// rcu机制 -
rcu_assign_pointer(*nl, n); -
return 0; - }
- #define
rcu_assign_pointer(p, v) \ -
({ \ -
if (!__builtin_constant_p(v) || \ -
((v) != NULL)) \ -
smp_wmb(); \ -
(p) = (v); \ -
})
- #define
barrier() __asm__ __volatile__("": : :"memory")
内存屏障的宏定义 | 功能说明 |
mb() | 多(单)处理器的内存屏障 |
rmb() | 多(单)处理器的读内存屏障 |
wmb() | 多(单)处理器的写内存屏障 |
smp_mb() | 多处理器的内存屏障 |
smp_rmb() | 多处理器的读内存屏障 |
smp_wmb() | 多处理器的写内存屏障 |
对网络层代码表征特别重要事件的通知链有如下两个:
inetaddr_chain | 本地接口上的IPv4地址的插入、删除、变更的通知信息 |
netdev_chain | 有关网络设备注册状态的通知信息 |
- static
struct notifier_block fib_inetaddr_notifier = { -
.notifier_call =fib_inetaddr_event, - };
- static
struct notifier_block fib_netdev_notifier = { -
.notifier_call =fib_netdev_event, - };
- void
__init ip_fib_init(void){ -
// ... -
register_netdevice_notifier(&fib_netdev_notifier); -
register_inetaddr_notifier(&fib_inetaddr_notifier); -
// ... - }
int register_netdevice_notifier(struct notifier_block *nb)
这个函数主要完成两件事情:
1)把参数struct notifier_block *nb注册到netdev_chain通知链上;
2)系统中所有已经被注册过的或者激活的网络设备的事件都要被新增的这个通知的回调函数重新调用一遍,使设备更新到一个完整的状态。
inetaddr_chain 网络设备的IP地址结构
1) 在TCPIP协议环境下,
网络设备结构(net_device)具有一个ip_ptr指针指向IP协议的设备参数块(in_device),
它包含设备IP地址结构(in_ifaddr)的链表指针(ifa_list).
IP地址结构链可以为一个网络设备配置多个IP地址,
使得局域网中的单台主机能模拟多台主机的作用.
(2) 设备IP地址的配置由应用程序通过ioctl()系统调用使用ifreq参数结构来完成.
同一设备的不同IP地址用不同的设备别名来标识,
例如"eth0:1"和"eth0:2"分别代表设备eht0的两个地址. 当增加一个别名设备时,
如果它的地址与已有地址属于同一子网, 则它的地址被标记为"从属"(IFA_F_SECONDARY).
当设备最后一个别名被删除时, 设备的IP参数块将被释放.设备地址参数发生改变时,
将通过地址消息链(inetaddr_chain)向有关子系统发送通知消息,
例如路由子系统用来刷新转发表和路由缓冲表.