Linux内核模块原子通知链使用示例
给一个atomic_notifier_chain_register的用法示例
下面是一个 Linux 内核模块中使用 atomic_notifier_chain_register
的完整示例。该函数用于向原子通知链注册回调函数,适用于原子上下文(如中断处理程序):
1 |
|
关键点解释:
定义原子通知链:
1
static ATOMIC_NOTIFIER_HEAD(test_notifier_chain);
使用内核宏声明并初始化一个原子通知链。
创建通知块:
1
2
3
4static struct notifier_block test_nb = {
.notifier_call = test_event_handler,
.priority = 0,
};notifier_call
: 事件处理函数指针priority
: 回调优先级(数值越大越先执行)
事件处理函数:
1
static int test_event_handler(...)
接收三个参数:
event
: 事件标识(自定义数值)data
: 传递的数据指针(可强转为任意类型)
触发通知:
1
atomic_notifier_call_chain(&test_notifier_chain, event_id, data_ptr);
调用后所有注册的处理函数都会被执行。
注册/注销:
- 注册:
atomic_notifier_chain_register()
- 注销:
atomic_notifier_chain_unregister()
- 注册:
使用场景:
- 中断处理:在原子上下文(如中断上半部)发送通知
- 硬件事件:处理器热事件、电源状态变化等
- 跨模块通信:解耦模块间的通知机制
实际输出示例(dmesg):
1 | [ ] 注册原子通知链 |
注意:
- 原子通知链的回调函数不能睡眠(禁止阻塞操作)
- 优先级相同的回调按注册顺序执行
- 适用于需要高性能和原子安全性的场景
给一个atomic_notifier_chain_register的用法示例,回调函数支持带多个参数
带多参数的 atomic_notifier_chain_register 示例
下面是一个完整的内核模块示例,展示了如何在 atomic_notifier_chain_register
的回调函数中传递多个参数:
1 |
|
关键点说明
1. 多参数传递机制
- 创建参数结构体
event_params
封装所有需要传递的参数 - 在触发事件时动态分配结构体并填充数据
- 将结构体指针作为
void *data
传递给回调函数 - 在回调函数中将
void *
转换回结构体指针
2. 内存管理
- 使用
kzalloc(sizeof(struct event_params), GFP_ATOMIC)
动态分配内存GFP_ATOMIC
确保在原子上下文中安全分配
- 在通知处理完成后使用
kfree(params)
释放内存
3. 参数结构体设计
1 | struct event_params { |
- 支持多种类型参数组合
- 可根据实际需求扩展
4. 安全注意事项
- 检查
data
是否为NULL
避免空指针解引用 - 字符串使用常量或确保生命周期足够长
- 在原子上下文中避免复杂操作
编译和测试方法
创建 Makefile:
1
2
3
4
5
6
7obj-m += atomic_notifier_example.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean编译模块:
1
make
加载模块:
1
sudo insmod atomic_notifier_example.ko
查看输出:
1
dmesg | tail -n 20
预期输出
1 | [ ] CPU 通知模块初始化 |
当卸载模块时:
1 | [ ] CPU 通知模块退出 |
这个示例展示了如何在原子通知链中传递复杂的多参数数据,同时确保了原子上下文下的内存安全和操作安全。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!