通过对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 指向的通知链中所有的元素,然后依次调用每一个的回调函数,完成通知动作。
我觉得不是太可能吧,这样的话岂不是执行了多余的函数?!一定是哪里还有判断我没有找到,这个问题后面一定要搞清楚。
流程图: