linux内核驱动笔记 - NotifierChain的使用记录

背景

在做内核开发的过程中,多模块的开发是十分常见的,模块与模块之间的信息交互也是不可避免的,其中NotifierChain的机制比较好的进行了解耦,而不是直接模块间提供函数进行调用;

涉及到的结构体与宏

包含头文件

确保包含了正确的头文件,一般需要包含 linux/notifier.h

#include <linux/notifier.h>
//宏
RAW_NOTIFIER_HEAD(...)
//结构体
struct notifier_block;
//函数 -- 这里暂时只介绍无锁的注册与注销
raw_notifier_chain_register(...)
raw_notifier_chain_unregister(...)

用法模块划分

消息中转者

struct RAW_NOTIFIER_HEAD(middle_chain);
//需要暴露如下接口提供给消息消费者使用
int demo_listener_register_notifier(struct notifier_block *nb) 
{
	return raw_notifier_chain_register(&middle_chain, nb);
}
EXPORT_SYMBOL(demo_listener_register_notifier);
int demo_listener_unregister_notifier(struct notifier_block *nb) 
{
	return raw_notifier_chain_unregister(&middle_chain, nb);
}
EXPORT_SYMBOL(demo_listener_unregister_notifier);
//暴露如下接口提供给消息生产者使用
int demo_producer_notifier_call_chain(long val, void *v)
{
	return raw_notifier_call_chain(&middle_chain, val, v);
}

通知消息生产者

#define DEMO_TYPE 1
static void ANY_func(...) {
	struct demo_st d = {...};
	//完成通知DEMO_TYPE消息的创建与发布
	demo_producer_notifier_call_chain(DEMO_TYPE, &d); 
}

通知消息消费者

static struct notifier_block listener = {
	.notifier_call = demo_callback,
	.priority = NOTIFY_PRIO_PBR,
};
static int demo_callback(struct notifier_block *nb, long type, void *arg)
{
	//TODO
	return NOTIFY_OK;
};
static int listener_module_init(...) {
	demo_listener_register_notifier(&listener);
}

注意事项

  1. 线程安全
    raw_notifier_chain_registerraw_notifier_chain_unregister 不是线程安全的,所以在多线程环境下使用时需要注意同步。

  2. 返回值检查
    确保检查 raw_notifier_chain_register 的返回值,以确定注册操作是否成功。

  3. 生命周期管理
    确保在模块卸载或其他适当的时机调用 raw_notifier_chain_unregister 解除注册,以避免内存泄漏或野指针问题。

    ret = raw_notifier_chain_unregister(&my_notifier_chain, &my_notifier);
    if (ret) {
        printk(KERN_ERR "Failed to unregister notifier\n");
    }
    

类似接口

除了 raw_notifier_chain_register 之外,还有其他类型的 notifier chain,可以根据不同的需求选择合适的接口:

  1. atomic_notifier_chain_register
    用于需要原子操作的通知链。

    int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *n);
    int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *n);
    
  2. blocking_notifier_chain_register
    用于阻塞通知链,适用于可能需要睡眠的情况。

    int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *n);
    int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *n);
    
  3. srcu_notifier_chain_register
    使用 SRCU(Sleepable Read-Copy Update)机制的通知链,适用于复杂同步要求的情况。

    int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *n);
    int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, struct notifier_block *n);
    

关键字

通知 消息机制 监听者

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值