深入理解Linux网络技术内幕——Notification内核通知表链
为什么要有内核通知表链:
- If (subsystem_X_enabled) {
- do_something_1
- }
- if (subsystem_Y_enabled) {
- do_something_2
- }
- If (subsystem_Z_enabled) {
- do_something_3
- }
- ... ... ...
Chain则大大的改善了这些不足。

- //通知块
- 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;
- }
深入理解Linux网络技术内幕——Notification内核通知表链的更多相关文章
- 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口
Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...
- 深入理解linux网络技术内幕读书笔记(四)--通知链
Table of Contents 1 概述 2 定义链 3 链注册 4 链上的通知事件 5 网络子系统的通知链 5.1 包裹函数 5.2 范例 6 测试实例 概述 [注意] 通知链只在内核子系统之间 ...
- 深入理解Linux网络技术内幕——设备的注册与初始化(二)
设备注册于设备除名 设备注册与设备除名一般有 register_netdev和unregister_netdev完成.这两个是包裹函数,负责上锁,真正起作用的是其调用的register_net ...
- 深入理解Linux网络技术内幕——用户空间与内核空间交互
概述: 内核空间与用户空间经常需要进行交互.举个例子:当用户空间使用一些配置命令如ifconfig或route时,内核处理程序就要响应这些处理请求. 用户空间与内核有多种交互方式,最常 ...
- 深入理解linux网络技术内幕读书笔记(七)--组件初始化的内核基础架构
Table of Contents 1 引导期间的内核选项 2 注册关键字 3 模块初始化代码 引导期间的内核选项 linux运行用户把内核配置选项传给引导记录,然后引导记录再把选项传给内核. 在引导 ...
- 深入理解Linux网络技术内幕——内核基础架构和组件初始化
引导期间的内核选项 Linux允许用户把内核配置选项传给引导记录,再有引导记录传给内核,以便对内核进行调整. start_kernel中调用两次parse_args,用于引导期间配置用 ...
- 《深入理解Linux网络技术内幕》阅读笔记 --- 路由基本概念
一.路由的基本概念 1.一条路由就是一组参数,这些参数存储了往一个给定目的地转发流量所需的信息,而一条路由所需的最少的参数集合为:(1)目的网络,(2)出口设备,(3)下一跳网关 2.路由中的相关术语 ...
- 深入理解linux网络技术内幕读书笔记(十)--帧的接收
Table of Contents 1 概述 1.1 帧接收的中断处理 2 设备的开启与关闭 3 队列 4 通知内核帧已接收:NAPI和netif_rx 4.1 NAPI简介 4.1.1 NAPI优点 ...
- 深入理解linux网络技术内幕读书笔记(九)--中断与网络驱动程序
Table of Contents 1 接收到帧时通知驱动程序 1.1 轮询 1.2 中断 2 中断处理程序 3 抢占功能 4 下半部函数 4.1 内核2.4版本以后的下半部函数: 引入软IRQ 5 ...
随机推荐
- java中new一个对象和对象=null有什么区别
原创:转载请注明出处 今天在写代码时,遇到一个问题,特此进行记录. for (ProfileDto profileDto : profile) { // Profile resP ...
- 04_Windows平台Spark开发环境构建
Spark的开发环境,可以基于IDEA+Scala插件,最终将打包得到的jar文件放入Linux服务器上的Spark上运行 如果是Python的小伙伴,可以在Windows上部署spark+hadoo ...
- 51nod 1307 绳子与重物(并查集水了一发)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 思路: 可以直接二分答案,然后dfs. 因为标签是并查集, ...
- FAILED Selenium2Library
FAILED Selenium2Library Importing test library 'Selenium2Library' failed: ImportError: cannot import ...
- fusion--RNAseq
融合基因(Fusion gene)是指两个基因的全部或一部分的序列相互融合为一个新的基因的过程.其有可能是染色体易位.中间缺失或染色体倒置所致的结果. 异常的融合基因可以引起恶性血液疾病以及肿瘤.例如 ...
- Java中Arrays 与 Collections 的简单操作
import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.C ...
- python写入csv文件的几种方法总结
生成test.csv文件 #coding=utf- import pandas as pd #任意的多组列表 a = [,,] b = [,,] #字典中的key值即为csv中列名 dataframe ...
- Jmeter ResponseAssertion 【Ignore Status】
在Jmeter源码中AssertionGui.java中,定义了Ignore Status的作用域 /** * Checkbox to indicate whether the response sh ...
- xss脚本注入后端的防护
1.脚本注入最主要的是不要相信用户输入的任何数据,对数据进行转义 可以使用:org.springframework.web.util.HtmlUtils包中的 HtmlUtils.htmlEscape ...
- listener TNS-01189 问题
-- 启动监听,提示已经启动. [oracle@sh ~]$ lsnrctl start LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 0 ...