最近发生一些事情,心情有所波动,没有更新,今天更新一下消息通知链。爷爷去世前的那个晚上正在看linux内核的消息通知链,今天,爷爷整整去世一个月了,前几天一直梦到爷爷,也奇怪,梦中我知道爷爷已经走了,但是还是显得那么自然。

通知链简单结构为:

linux内核中的消息通知链分为:

  1. 原始通知链
  2. 原子通知链(不受线程机制影响)
  3. 加锁通知链

他们的结构分别为:


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内核消息通知链相关推荐

  1. Linux内核通知链机制的原理及实现【转】

    转自:http://www.cnblogs.com/armlinux/archive/2011/11/11/2396781.html 一.概念: 大多数内核子系统都是相互独立的,因此某个子系统可能对其 ...

  2. Linux 内核通知链和例程代码

    概念 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系统,Linux内核提供了通知链的机制.通知链表只 ...

  3. linux 通知链,Linux内核通知链notifier

    当有事件发生时,通知者调用 notifier_call_chain 函数通知事件的到达,这个函数会遍历n1指向的通知链中所有的元素,然后依次调用每一个的回调函数,完成通知动作. static int ...

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

    转自:http://blog.csdn.net/wuhzossibility/article/details/8079025 内核通知链 1.1. 概述 Linux内核中各个子系统相互依赖,当其中某个 ...

  5. Linux内核notifier机制通知链

    内核使用通知链的机制在内核各子系统之间进行事件通知(注:无法用于内核态和用户态之间的事件通知). 一.通知链介绍 在文件include/linux/notifier.h中,可以查看Linux内核定义的 ...

  6. 内核通知链(网络子系统为例)

    概念 1.Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,就必须使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.为满足这样的需求,内核实现了事件通知链机制( ...

  7. linux 网络函数调用链,Linux通知链机制及实例

    Linux内核中各个子系统相互依赖,当其中某个子系统状态发生改变时,要使用一定的机制告知使用其服务的其他子系统,以便其他子系统采取相应的措施.内核实现了事件通知链机制(notification cha ...

  8. HALCON: HALCON 20.11.0.0 Progress主要新特性

    HALCON: HALCON 20.11.0.0 Progress主要新特性 改进了基于形状的匹配 在HALCON 20.11中,对基于形状匹配的核心技术进行了改进,尤其是针对低对比度和高噪声的场景. ...

  9. Linux内核概念:per-CPU,cpumask,inicall机制,通知链

    Linux内核概念 per-CPU,cpumask,inicall机制,通知链 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Per-cpu 变 ...

最新文章

  1. ​全球首个视频实验期刊JOVE征稿:植物微生物组学方法专刊(牛犇、韦中、高峥、王蒙岑)...
  2. 高效人士的七个习惯(读书笔记)
  3. 消息中间件—RocketMQ的RPC通信(二
  4. java面试题七 char转int
  5. 转:c#委托事件实现窗体传值通信
  6. 数组的合并和升序排列_leetcode 33 搜索旋转排序数组
  7. Windows Eclipse Maven 安装
  8. java 象限分析_用四种象限分析你(未来的人生走向)
  9. 数据分析实战100例(基于SQLPandas)_探索Chipotle快餐数据
  10. MATLAB对光路进行模拟,MATLAB辅助OptiSystem实现光学反馈环路的模拟
  11. [ubuntu] 安装五笔输入法
  12. iterm2新技能-用不同的颜色创建新标签
  13. l130 华大低功耗mcu_HC32L130国产超低功耗华大MCU芯片介绍
  14. 每日方法分享:手机怎么录屏?
  15. android 设置壁纸页面,Android实现手机壁纸改变的方法
  16. 微信小程序实现文本两端对齐
  17. Java实现十字形开关问题(“飞行员兄弟“)
  18. The Bucket List 题解
  19. GSWiFi路由器苹果安卓手机辅助连接通用方法-网线版(图文教程)
  20. C#简单游戏外挂制作(二)

热门文章

  1. but was actually of type [com.sun.proxy.$Proxy13]
  2. Java并发编程-BlockingQueue阻塞队列
  3. Scoped CSS规范草案
  4. NSTimer、CADisplayLink、GCD 三种定时器的用法 —— 昉
  5. 网上看到的,关于测试用例编写粒度准则
  6. 给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换)...
  7. 封装好的实用的读写XML类---增删改查XML
  8. 如何以 JAVA call 一個現有的 dll 檔?
  9. VB 字符串续行符最多25行…………
  10. php 上传100m文件,PHP向MySQL中insert100M以上的文件