linux-4.20.11内核消息通知链
最近发生一些事情,心情有所波动,没有更新,今天更新一下消息通知链。爷爷去世前的那个晚上正在看linux内核的消息通知链,今天,爷爷整整去世一个月了,前几天一直梦到爷爷,也奇怪,梦中我知道爷爷已经走了,但是还是显得那么自然。
通知链简单结构为:
linux内核中的消息通知链分为:
- 原始通知链
- 原子通知链(不受线程机制影响)
- 加锁通知链
他们的结构分别为:
struct notifier_block;typedef int (*notifier_fn_t)(struct notifier_block *nb,unsigned long action, void *data);struct notifier_block {notifier_fn_t notifier_call;struct notifier_block __rcu *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;
};
当然提供了一些宏
#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \spin_lock_init(&(name)->lock); \(name)->head = NULL; \} while (0)
#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \init_rwsem(&(name)->rwsem); \(name)->head = NULL; \} while (0)
#define RAW_INIT_NOTIFIER_HEAD(name) do { \(name)->head = NULL; \} while (0)
下面给出原始文件
notifier.h include\linux 8409 2/20/2019 9
/* SPDX-License-Identifier: GPL-2.0 */
/** Routines to manage notifier chains for passing status changes to any* interested routines. We need this instead of hard coded call lists so* that modules can poke their nose into the innards. The network devices* needed them so here they are for the rest of you.** Alan Cox <Alan.Cox@linux.org>*/#ifndef _LINUX_NOTIFIER_H
#define _LINUX_NOTIFIER_H
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/srcu.h>/** Notifier chains are of four types:** Atomic notifier chains: Chain callbacks run in interrupt/atomic* context. Callouts are not allowed to block.* Blocking notifier chains: Chain callbacks run in process context.* Callouts are allowed to block.* Raw notifier chains: There are no restrictions on callbacks,* registration, or unregistration. All locking and protection* must be provided by the caller.* SRCU notifier chains: A variant of blocking notifier chains, with* the same restrictions.** atomic_notifier_chain_register() may be called from an atomic context,* but blocking_notifier_chain_register() and srcu_notifier_chain_register()* must be called from a process context. Ditto for the corresponding* _unregister() routines.** atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),* and srcu_notifier_chain_unregister() _must not_ be called from within* the call chain.** SRCU notifier chains are an alternative form of blocking notifier chains.* They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for* protection of the chain links. This means there is _very_ low overhead* in srcu_notifier_call_chain(): no cache bounces and no memory barriers.* As compensation, srcu_notifier_chain_unregister() is rather expensive.* SRCU notifier chains should be used when the chain will be called very* often but notifier_blocks will seldom be removed.*/struct notifier_block;typedef int (*notifier_fn_t)(struct notifier_block *nb,unsigned long action, void *data);struct notifier_block {notifier_fn_t notifier_call;struct notifier_block __rcu *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;
};#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \spin_lock_init(&(name)->lock); \(name)->head = NULL; \} while (0)
#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \init_rwsem(&(name)->rwsem); \(name)->head = NULL; \} while (0)
#define RAW_INIT_NOTIFIER_HEAD(name) do { \(name)->head = NULL; \} while (0)/* srcu_notifier_heads must be cleaned up dynamically */
extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
#define srcu_cleanup_notifier_head(name) \cleanup_srcu_struct(&(name)->srcu);#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 }#define SRCU_NOTIFIER_INIT(name, pcpu) \{ \.mutex = __MUTEX_INITIALIZER(name.mutex), \.head = NULL, \.srcu = __SRCU_STRUCT_INIT(name.srcu, pcpu), \}#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)#ifdef CONFIG_TREE_SRCU
#define _SRCU_NOTIFIER_HEAD(name, mod) \static DEFINE_PER_CPU(struct srcu_data, name##_head_srcu_data); \mod struct srcu_notifier_head name = \SRCU_NOTIFIER_INIT(name, name##_head_srcu_data)#else
#define _SRCU_NOTIFIER_HEAD(name, mod) \mod struct srcu_notifier_head name = \SRCU_NOTIFIER_INIT(name, name)#endif#define SRCU_NOTIFIER_HEAD(name) \_SRCU_NOTIFIER_HEAD(name, /* not static */)#define SRCU_NOTIFIER_HEAD_STATIC(name) \_SRCU_NOTIFIER_HEAD(name, static)#ifdef __KERNEL__extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,struct notifier_block *nb);
extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,struct notifier_block *nb);
extern int raw_notifier_chain_register(struct raw_notifier_head *nh,struct notifier_block *nb);
extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,struct notifier_block *nb);extern int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,struct notifier_block *nb);extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,struct notifier_block *nb);
extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,struct notifier_block *nb);
extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,struct notifier_block *nb);
extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,struct notifier_block *nb);extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,unsigned long val, void *v);
extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,unsigned long val, void *v, int nr_to_call, int *nr_calls);
extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,unsigned long val, void *v);
extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,unsigned long val, void *v, int nr_to_call, int *nr_calls);
extern int raw_notifier_call_chain(struct raw_notifier_head *nh,unsigned long val, void *v);
extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,unsigned long val, void *v, int nr_to_call, int *nr_calls);
extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,unsigned long val, void *v);
extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,unsigned long val, void *v, int nr_to_call, int *nr_calls);#define NOTIFY_DONE 0x0000 /* Don't care */
#define NOTIFY_OK 0x0001 /* Suits me */
#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)/* Bad/Veto action */
/** Clean way to return from the notifier and stop further calls.*/
#define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
static inline int notifier_from_errno(int err)
{if (err)return NOTIFY_STOP_MASK | (NOTIFY_OK - err);return NOTIFY_OK;
}/* Restore (negative) errno value from notify return value. */
static inline int notifier_to_errno(int ret)
{ret &= ~NOTIFY_STOP_MASK;return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
}/** Declared notifiers so far. I can imagine quite a few more chains* over time (eg laptop power reset chains, reboot chain (to clean * device units up), device [un]mount chain, module load/unload chain,* low memory chain, screenblank chain (for plug in modular screenblankers) * VC switch chains (for loadable kernel svgalib VC switch helpers) etc...*//* CPU notfiers are defined in include/linux/cpu.h. *//* netdevice notifiers are defined in include/linux/netdevice.h *//* reboot notifiers are defined in include/linux/reboot.h. *//* Hibernation and suspend events are defined in include/linux/suspend.h. *//* Virtual Terminal events are defined in include/linux/vt.h. */#define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released *//* Console keyboard events.* Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and* KBD_KEYSYM. */
#define KBD_KEYCODE 0x0001 /* Keyboard keycode, called before any other */
#define KBD_UNBOUND_KEYCODE 0x0002 /* Keyboard keycode which is not bound to any other */
#define KBD_UNICODE 0x0003 /* Keyboard unicode */
#define KBD_KEYSYM 0x0004 /* Keyboard keysym */
#define KBD_POST_KEYSYM 0x0005 /* Called after keyboard keysym interpretation */extern struct blocking_notifier_head reboot_notifier_list;#endif /* __KERNEL__ */
#endif /* _LINUX_NOTIFIER_H */
对应的去查看.c文件就行了,需要注意的一点是,如果想要讲代码复制出来自己使用,可能只能弄出原始通知链(亲测可用有效),其他的则调用了大量的内核中的接口,不容易被“抠”出来。
linux-4.20.11内核消息通知链相关推荐
- Linux内核通知链机制的原理及实现【转】
转自:http://www.cnblogs.com/armlinux/archive/2011/11/11/2396781.html 一.概念: 大多数内核子系统都是相互独立的,因此某个子系统可能对其 ...
- Linux 内核通知链和例程代码
概念 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制.通知链表只 ...
- linux 通知链,Linux内核通知链notifier
当有事件发生时,通知者调用 notifier_call_chain 函数通知事件的到达,这个函数会遍历n1指向的通知链中所有的元素,然后依次调用每一个的回调函数,完成通知动作. static int ...
- Linux内核基础--事件通知链(notifier chain)【转】
转自:http://blog.csdn.net/wuhzossibility/article/details/8079025 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个 ...
- Linux内核notifier机制通知链
内核使用通知链的机制在内核各子系统之间进行事件通知(注:无法用于内核态和用户态之间的事件通知). 一.通知链介绍 在文件include/linux/notifier.h中,可以查看Linux内核定义的 ...
- 内核通知链(网络子系统为例)
概念 1.Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制( ...
- linux 网络函数调用链,Linux通知链机制及实例
Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,要使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.内核实现了事件通知链机制(notification cha ...
- HALCON: HALCON 20.11.0.0 Progress主要新特性
HALCON: HALCON 20.11.0.0 Progress主要新特性 改进了基于形状的匹配 在HALCON 20.11中,对基于形状匹配的核心技术进行了改进,尤其是针对低对比度和高噪声的场景. ...
- Linux内核概念:per-CPU,cpumask,inicall机制,通知链
Linux内核概念 per-CPU,cpumask,inicall机制,通知链 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Per-cpu 变 ...
最新文章
- ​全球首个视频实验期刊JOVE征稿:植物微生物组学方法专刊(牛犇、韦中、高峥、王蒙岑)...
- 高效人士的七个习惯(读书笔记)
- 消息中间件—RocketMQ的RPC通信(二
- java面试题七 char转int
- 转:c#委托事件实现窗体传值通信
- 数组的合并和升序排列_leetcode 33 搜索旋转排序数组
- Windows Eclipse Maven 安装
- java 象限分析_用四种象限分析你(未来的人生走向)
- 数据分析实战100例(基于SQLPandas)_探索Chipotle快餐数据
- MATLAB对光路进行模拟,MATLAB辅助OptiSystem实现光学反馈环路的模拟
- [ubuntu] 安装五笔输入法
- iterm2新技能-用不同的颜色创建新标签
- l130 华大低功耗mcu_HC32L130国产超低功耗华大MCU芯片介绍
- 每日方法分享:手机怎么录屏?
- android 设置壁纸页面,Android实现手机壁纸改变的方法
- 微信小程序实现文本两端对齐
- Java实现十字形开关问题(“飞行员兄弟“)
- The Bucket List 题解
- GSWiFi路由器苹果安卓手机辅助连接通用方法-网线版(图文教程)
- C#简单游戏外挂制作(二)
热门文章
- but was actually of type [com.sun.proxy.$Proxy13]
- Java并发编程-BlockingQueue阻塞队列
- Scoped CSS规范草案
- NSTimer、CADisplayLink、GCD 三种定时器的用法 —— 昉
- 网上看到的,关于测试用例编写粒度准则
- 给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换)...
- 封装好的实用的读写XML类---增删改查XML
- 如何以 JAVA call 一個現有的 dll 檔?
- VB 字符串续行符最多25行…………
- php 上传100m文件,PHP向MySQL中insert100M以上的文件