一. 简介
上一篇文章学习了 Linux内核如何确定是否支持此设备,如果支持,设备就会启动 Linux 内核。
文章地址如下:
设备树根节点下的compatile属性的作用-CSDN博客
本文继上面文章的学习。这里简单看一下, Linux 内核是如何根据设备树根节点的 compatible 属性来匹配出对 应的 machine_desc。
二. Linux 内核如何根据设备树根节点的 compatible 属性来匹配machine_desc
Linux
内核调用
start_kernel
函数来启动内核,
start_kernel
函数会调用 setup_arch
函数来匹配
machine_desc
,
setup_arch
函数定义在文件
arch/arm/kernel/setup.c
中,函
数内容如下
(
有缩减
)
:
void __init setup_arch(char **cmdline_p)
{
const struct machine_desc *mdesc;
setup_processor();
mdesc = setup_machine_fdt(__atags_pointer);
if (!mdesc)
mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
machine_desc = mdesc;
machine_name = mdesc->name;
...............
}
第
6
行,调用
setup_machine_fdt()
函数来获取匹配的
machine_desc
,参数就是
atags
的首
地址,也就是
uboot
传递给
Linux
内核的 .
dtb 设备树
文件的首地址,
setup_machine_fdt()
函数的返回值就是
找到的最匹配的
machine_desc
。
函数 setup_machine_fdt 定义在文件 arch/arm/kernel/devtree.c 中,内容如下(有缩减):
const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
{
const struct machine_desc *mdesc, *mdesc_best = NULL;
......
if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))
return NULL;
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
......
__machine_arch_type = mdesc->nr;
return mdesc;
}
第
8
行,调用函数
of_flat_dt_match_machine()函数
来获取匹配的
machine_desc
,参数
mdesc_best
是 默 认 的
machine_desc
。
参数
arch_get_next_mach
是 个 函 数 , 此 函 数 定 义 在 定 义 在
arch/arm/kernel/devtree.c
文件中。
找到匹配的
machine_desc
的过程,就是用设备树根节点的
compatible
属性值和
Linux
内核中
machine_desc
下
.dt_compat
的值比较,看看那个相等,如果相
等,就表示找到匹配的
machine_desc
,
arch_get_next_mach
函数的工作就是获取
Linux
内核中
下一个
machine_desc
结构体。
最后再来看一下 of_flat_dt_match_machine 函数,此函数定义在文件 drivers/of/fdt.c 中,内容如下(有缩减):
const void * __init of_flat_dt_match_machine(const void *default_match,
const void * (*get_next_compat)(const char * const**))
{
const void *data = NULL;
const void *best_data = default_match;
const char *const *compat;
unsigned long dt_root;
unsigned int best_score = ~1, score = 0;
dt_root = of_get_flat_dt_root();
while ((data = get_next_compat(&compat))) {
score = of_flat_dt_match(dt_root, compat);
if (score > 0 && score < best_score) {
best_data = data;
best_score = score;
}
}
........................
pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
return best_data;
}
第 10 行,通过 of_get_flat_dt_root() 函数获取设备树根节点。
第
11~16
行,此循环就是查找匹配的
machine_desc
过程。
第
12
行的
of_flat_dt_match
函
数,会将根节点
compatible
属性的值和每个
machine_desc
结构体中
. dt_compat
的值进行比较,直
至找到匹配的那个
machine_desc
。
三. 总结
总结一下,
Linux
内核通过根节点
compatible
属性找到对应的设备的函数调用过程。过程
如下图所示: