当前位置: 首页 > ai >正文

Linux内核notify通知笔录

前沿

        本篇文章围绕三个问题来讲述,并解释案例代码演示,从而更进一步的了解该机制。

1.Notify机制是什么?

        notify是一种内核子模块相互之间通信一种机制。如设备状态变化,电源事件等场景。另外它是一种通过事件驱动的通信机制,允许某个组建在特定事件发生时主动通知其他组件。内核中依据不同的上下文存在多种类型的形式,每种形式都有其特定的功能应用场景。

2.Notify实现原理?

        该机制模式就好比发布订阅机制一样,发布者发布消息,订阅者订阅相关的数信息。当有事件发生时,通过通知链调用订阅者提前注册的数据机制,然后订阅者收到对应的消息处理。有中断触发方式,上下文触发方式。

3.Notify内核中如何使用?

        发布消息:

#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>// 定义全局通知链头
BLOCKING_NOTIFIER_HEAD(my_notifier_chain);
EXPORT_SYMBOL(my_notifier_chain);  // 确保正确导出// 发送通知函数
int send_notification(unsigned long val, void *v)
{printk(KERN_INFO "MODULE A: Notifier chain head: %px\n", my_notifier_chain.head);if (my_notifier_chain.head == NULL) {printk(KERN_ERR "MODULE A: Notifier chain is empty!\n");}printk(KERN_INFO "MODULE A: Sending notification (val=%lu)\n", val);int ret = blocking_notifier_call_chain(&my_notifier_chain, val, v);printk(KERN_INFO "MODULE A: Notification result: %d\n", ret);return ret;
}
EXPORT_SYMBOL(send_notification);// 添加设备文件操作以手动触发通知
static ssize_t trigger_write(struct file *filp, const char __user *buf, size_t count, loff_t *off)
{char msg[100];if (copy_from_user(msg, buf, count))return -EFAULT;msg[count] = '\0';send_notification(100, msg);return count;
}static struct file_operations fops = {.write = trigger_write,
};static int major;static int __init module_a_init(void)
{major = register_chrdev(0, "notify_trigger", &fops);printk(KERN_INFO "MODULE A: Loaded (major=%d)\n", major);printk(KERN_INFO "MODULE A: Use 'echo \"message\" > /dev/notify_trigger' to test\n");return 0;
}static void __exit module_a_exit(void)
{unregister_chrdev(major, "notify_trigger");printk(KERN_INFO "MODULE A: Unloaded\n");
}module_init(module_a_init);
module_exit(module_a_exit);
MODULE_LICENSE("GPL");

        订阅消息:

#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/kernel.h>// 声明外部符号
extern struct blocking_notifier_head my_notifier_chain;// 回调函数
static int my_notifier_call(struct notifier_block *nb, unsigned long val, void *v)
{printk(KERN_INFO "MODULE B: ===== NOTIFICATION RECEIVED =====\n");printk(KERN_INFO "MODULE B: Event value: %lu\n", val);printk(KERN_INFO "MODULE B: Message: %s\n", (char *)v);printk(KERN_INFO "MODULE B: ===== END NOTIFICATION =====\n");return NOTIFY_OK;
}// 定义通知块
static struct notifier_block my_notifier = {.notifier_call = my_notifier_call,.priority = 0,
};static int __init module_b_init(void)
{int ret;// 注册通知回调ret = blocking_notifier_chain_register(&my_notifier_chain, &my_notifier);if (ret) {printk(KERN_ERR "MODULE B: Registration failed: %d\n", ret);return ret;}printk(KERN_INFO "MODULE B: Successfully registered notifier\n");printk(KERN_INFO "MODULE B: Current notifier chain: %px\n", &my_notifier_chain);return 0;
}static void __exit module_b_exit(void)
{blocking_notifier_chain_unregister(&my_notifier_chain, &my_notifier);printk(KERN_INFO "MODULE B: Unregistered notifier\n");
}module_init(module_b_init);
module_exit(module_b_exit);
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: module_a");

Makefile:

obj-m := module_a.o module_b.oKDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)all:$(MAKE) -C $(KDIR) M=$(PWD) modulesclean:$(MAKE) -C $(KDIR) M=$(PWD) clean

按照先写入module_a之后在写入module_b,然后在系统/dev目录下创建设备,之后通过该对应的设备填充信息触发a模块调用通知链从而b模块收到对应的消息。如下输入日志:


[36699.868674] module_a: loading out-of-tree module taints kernel.
[36699.869060] module_a: module verification failed: signature and/or required key missing - tainting kernel
[36699.871047] MODULE A: Loaded (major=242)
[36699.871048] MODULE A: Use 'echo "message" > /dev/notify_trigger' to test
[36705.974380] MODULE B: Successfully registered notifier
[36705.974381] MODULE B: Current notifier chain: ffffffffc09300e0
[36763.437614] MODULE A: Notifier chain head: ffffffffc094d000
[36763.437616] MODULE A: Sending notification (val=100)
[36763.437617] MODULE B: ===== NOTIFICATION RECEIVED =====
[36763.437617] MODULE B: Event value: 100
[36763.437618] MODULE B: Message: Hello World[36763.437618] MODULE B: ===== END NOTIFICATION =====
[36763.437619] MODULE A: Notification result: 1

以上就是notify学习笔记,后续还会更新内核源代码详细实现过程! 

http://www.xdnf.cn/news/3323.html

相关文章:

  • 软件测评中心如何保障软件质量与性能?评测范围和标准有哪些?
  • Java 多线程进阶:线程安全、synchronized、死锁、wait/notify 全解析(含代码示例)
  • Go 语言中一个功能强大且广泛使用的数据验证库github.com/go-playground/validator/v10
  • 2025五一杯数学建模A题:支路车流量推测问题,思路分析+模型代码
  • 拉宾公钥密码算法实现
  • 面经-计算机网络——OSI七层模型与TCP/IP四层模型的对比详解
  • IDEA在项目中添加模块出现Error adding module to project: null(向项目添加模块时出错: null)的解决方法
  • 位运算切换大小写
  • 数字智慧方案6158丨智慧医疗解决方案精华版(58页PPT)(文末有下载方式)
  • Spark,集群搭建之Yarn模式
  • go实现双向链表
  • Unity SpriteRenderer(精灵渲染器)
  • Linux常用命令27——userdel删除用户
  • 如何阅读GitHub上的深度学习项目
  • 论文报错3
  • js文件加密。安装 Terser
  • C++负载均衡远程调用学习之TCP连接封装与TCPCLIENT封装
  • 审计专员简历模板
  • 【Hot 100】23. 合并 K 个升序链表
  • 【深度学习新浪潮】小米MiMo-7B报告内容浅析
  • MATLAB中removedelay函数用法
  • 区间贪心 (区间端点处理)
  • llamafactory-cli webui启动报错TypeError: argument of type ‘bool‘ is not iterable
  • 《AI大模型应知应会100篇》第41篇:多轮对话设计:构建高效的交互式应用
  • CentOS 7 下安装 supervisor-3.4.0-1.el7.noarch.rpm 详细步骤
  • QMK固件开发指南:构建您的第一个固件
  • 22.2Linux的I2C驱动实验(编程)_csdn
  • 2024年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • Qt指南针
  • 9. 深入Spring AI:刨析 ChatMemory