Arm32-Linux子系统的互相Notify

前言:

Linux下面不同的子系统一个个的组成了整个系统的运行环节,为了让这些子系统能够互相通讯,有一种叫做:notify chain(通知链)的东西。本篇看下。

概括

所谓通知链,有通知,就有执行的地方。比如A子系统通知B子系统,麻烦你帮我执行一件事情。这时候,A子系统就会通知B子系统,把需要执行的事情信息同时传递给B子系统,让其帮助执行。.

这个过程,首先是需要有执行的事情,所以就需要注册。当注册好了之后,A子系统通知B子系统,B子系统就会找到注册的那个事情进行执行。

这里以原子通知链(Atomic notifier chains)为例,它是指令级的通知链,个人比较喜欢这种。它分别由注册通知链,卸载通知链,以及调用通知链三种函数:

1. int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *n);  2. int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *n);  3. int atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v);

还以上面的为例,假如A子系统需要通知B子系统你帮我完成一个事情。那么B子系统首先需要注册一个这个事情,通过函数:atomic_notifier_chain_register来完成。当A子系统不需要B子系统为它做事的时候,可以卸载掉这件事情:atomic_notifier_chain_unregister。

为什么会有卸载这个函数,因为所有的做事情的回调函数都在一个链表里面,当A子系统通知B子系统做事的时候,有可能会查找整个链表。当成百上千的子系统相互注册的时候,链表非常庞大,卸载这些事情(函数回调),可以很好的提高性能。

上面函数的参数如下:
参数nl是通知链的头部,val表示事件类型,v用来指向通知链上的函数执行时需要用到的参数,nr_to_call表示准备最多通知几个,-1表示整条链都通知,nr_calls非空的话,返回通知了多少个。

elf入口

当Arm32调用用户态的C Main的时候,堆栈里面的ret_from_fork就是通过原子调用链来执行的。

thread #1, stop reason = breakpoint 84.1frame #0: 0x8010011c vmlinux`ret_from_fork at entry-common.S:142frame #1: 0x801468b8 vmlinux`atomic_notifier_call_chain [inlined] __rcu_read_unlock at rcupdate.h:74:2frame #2: 0x801468b4 vmlinux`atomic_notifier_call_chain [inlined] rcu_read_unlock at rcupdate.h:719:2frame #3: 0x801468b4 vmlinux`atomic_notifier_call_chain(nh=<unavailable>, val=<unavailable>, v=<unavailable>) at notifier.c:199:2

另外一个需要注意的是Arm32的elf入口是通过读取内存异常的中断处理程序来调用用户态Glibc的_start函数入口。

而X64则是通过缺页异常来调用用户态Glibc的_start入口。