linux notify 通知在TP中的应用

通过对tp中代码的分析来解读一下notifier如何应用。
Mtk_tpd.c中代码:

static struct notifier_block tpd_fb_notifier;//定义一个notifier_block
static int tpd_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{}//定义填充回调函数
tpd_fb_notifier.notifier_call = tpd_fb_notifier_callback;//将定义的notifier_block中的结构体成员指向回调函数
if (fb_register_client(&tpd_fb_notifier))//注册自定义的notifier_block

这也就是使用 notify 系统所需要的四个步骤
定义一个 notifier_block:tpd_fb_notifier,这是一个结构体,结构体成员为:

struct notifier_block {    
    int (*notifier_call)(struct notifier_block *, unsigned long, void *);  
    struct notifier_block __rcu *next;  
    int priority;  
};  

第一个成员变量是一个回调函数;
上述步骤中可以看到在第二步中定义了一个函数,并在第三步中赋给了
tpd_fb_notifier. notifier_call 这一结构体成员;
第二个成员是指向下一个 notifier_block,第三个是这个 notifier_block 的优先级,数值越大,优先级越高
然后将 notifier_block:tpd_fb_notifier 注册起来,注册到哪里?我们分析代码:
fb_notify.c 中:

int fb_register_client(struct notifier_block *nb)
{
    return blocking_notifier_chain_register(&fb_notifier_list, nb);
}

将参数中的 notify_block 注册到 fb_notifier_list 链表中
fb_notifier_list 又是什么?

static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);

是一个通知链的头部节点(这个通知链的类型是 blocking_notifier_chain,还有其他的三种通知链类型,可以百度),通过这个头部节点可以遍历到注册在这个通知链中的其他所有 notify_block

那么定义注册完这些个东西有什么用呢?
在 fb_notify.c 中还定义了一个函数:

int fb_notifier_call_chain(unsigned long val, void *v)
{
    return blocking_notifier_call_chain(&fb_notifier_list, val, v);
}

当调用这个函数的时候,通知 fb_notifier_list 链表中所注册的所有 notify_block 执行相应的结构体成员notifier_call,即执行链表上的所有 notify_block 的 callback 函数;这样就达到一个目的:调用这个函数之后就可以执行到我们自定义的函数,执行我们想要的功能;
我们再看这个函数的实现:
Notifier.c

int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
        unsigned long val, void *v)
{
    return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
}

static int notifier_call_chain(struct notifier_block **nl,
                   unsigned long val, void *v,
                   int nr_to_call, int *nr_calls)
{
……
ret = nb->notifier_call(nb, val, v);
//这句话就是执行这个notify_block的 call 函数,这个函数有三个参数,第一个是 notify_block 自身,val和 v 是要传送的数据,val 是一个无符号 long 型,v 是一个空指针,可以指向任何数据类型(指针真是个好东西)
……
}

上述 notifier_call(nb, val, v) ;对应一个实际的函数例子是

tpd_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
val = event;v = data

可是这里有一个问题,网上相关博客说:当有事件触发时,通知者调用 notifier_call_chain 函数通知事件的到达,这个函数会遍历 nl 指向的通知链中所有的元素,然后依次调用每一个的回调函数,完成通知动作。
我觉得不是太可能吧,这样的话岂不是执行了多余的函数?!一定是哪里还有判断我没有找到,这个问题后面一定要搞清楚。

流程图:
这里写图片描述

推荐文章:内核通知链 学习笔记
notifier chain — 内核通知链

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linuxnotify是一个通知机制,用于在内核的不同组件之间进行通信和协作。通知机制通过注册、注销和通知接口来实现。 在Linux内核,可以使用notifier_chain_register函数来注册一个通知块,使用notifier_chain_unregister函数来注销一个通知块。这些函数可以用于将通知块添加到通知或从通知移除。 通知链是一个由多个通知块组成的链表结构。当需要发送通知时,可以使用notifier_call_chain函数来触发通知的所有注册了的函数。这些函数将按照注册的顺序被调用。 此外,对于阻塞和非阻塞的通知,还有相应的接口封装。例如,blocking_notifier_chain_register函数用于注册一个阻塞通知块,blocking_notifier_chain_unregister函数用于注销一个阻塞通知块,blocking_notifier_call_chain函数用于触发阻塞通知的所有函数。 总结起来,Linuxnotify机制通过注册、注销和通知接口,以及通知链的方式实现内核组件之间的通信和协作。 #### 引用[.reference_title] - *1* [linuxnotify机制(仅用于内核模块之间的通信)](https://blog.csdn.net/weixin_30568715/article/details/96373966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [基于帧缓冲设备学习Linuxnotify机制](https://blog.csdn.net/pangyinglong/article/details/98763271)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值