背景:
针对上一篇文章已经讲解了如何通过命令写入debug_mask值来开放binder驱动中的相关debug日志,在本节将剖析为啥通过echo写入值到debug_mask就可以实现开放相关日志。
源码分析:
入手点可以先从我们直接打印日志的binder_debug方法开始:
正常如要打印日志只需要调用
static void binder_vma_open(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
//这里会调用binder_debug来进行打印
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
}
这里看看binder_debug方法:
kernel/nubia/msm8998/drivers/android/binder.c
#define binder_debug(mask, x...) \
do { \
if (binder_debug_mask & mask) \
pr_info(x); \
} while (0)
这里可以看到binder_debug第一个参数就是mask,第二个是x其实就是正常日志打印参数,这个mask其实就是前面一节说道的开放哪些binder日志打印的枚举,这里上面看到我们传递值是BINDER_DEBUG_OPEN_CLOSE。
binder_debug_mask 是全局的一个变量,其实可以简单认为系统会把binder_debug_mask变量和我们/sys/module/binder/parameters/debug_mask值一样。
那么上面(binder_debug_mask & mask)就是检测debug_mask文件中的值是否包含了mask这个项,如果包含则会调用下面的pr_info(x)方法来进行打印
看看pr_info方法
kernel/nubia/msm8998/include/linux/printk.h
#define pr_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
其实就是调用printk打印。
那么上面就已经讲解清楚了,binder_debug在各个binder的相关操作方法中都有进行调用,但是binder_debug具体是否可以调用到printk进行输入,其实最后还是要看binder_debug_mask这个值,那么这个值具体又是怎么来的呢?
kernel/nubia/msm8998/drivers/android/binder.c
static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
module_param_named(debug_mask, binder_debug_mask, uint, 0644);
这里看到binder_debug_mask赋值一共两个地方,有一个初始值,有一个传递到module_param_named方法中的,其实binder_debug_mask的改变就是靠这个module_param_named方法,下面我们来重点讨论一下module_param_named方法。
module_param_named解析
module_param_named 是 Linux 内核中用于模块参数的一个宏定义,它允许模块开发者定义模块参数,这些参数可以在模块加载时通过命令行或配置文件等方式设置。module_param_named 宏定义在 <linux/moduleparam.h> 头文件中,通常用在模块的源代码中。
上面解释可能比较抽象,无法时刻理解,下面以debug_mask为案例先进行直观剖析
module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
module_param_named的第一个参数为debug_mask,首先会生成/sys/module/binder/parameters/目录下生成debug_mask文件节点,而且如果读取debug_mask文件就是binder_debug_mask变量的值。
当通过echo xxx > debug_mask命令,会触发动态修改module_param_named的第二个参数binder_debug_mask值进行改变,一旦binder_debug_mask改变就会。
上面总结就是:第一个参数debug_mask会有一个文件在/sys/module/binder/parameters/,读取和写入这个文件的值都会同步到binder_debug_mask这个变量上。
那么具体是怎么实现的debug_mask就可以同步到binder_debug_mask变量呢?这块就需要内核驱动相关的一些知识,比较复杂,这块就不给大家分析具体源码了,这里给大家一个参考blog:
https://blog.youkuaiyun.com/tugouxp/article/details/122759735
更多framework实战干货,请关注“千里马学框架”