//链接脚本
SECTIONS{
. = 0x33f80000; /*代码段起始地址*/
.text : {
start.o (.text)
*(.text)
} /*代码段*/
. = ALIGN(4); /*下一段的起始地址向4取整*/
.rodata : {*(.rodata*)} /*只读数据段*/
. = ALIGN(4);
.data : {*(.data)} /*数据段*/
. = ALIGN(4);
__bss_start = .; /*bss段起始地址设为当前地址*/
.bss : {*(.bss) *(COMMON) } /*bss段 以及通用符号段*/
__bss_end = .;
}
//清除BSS段
void clean_bss(void)
{
extern int __bss_start, __bss_end;
int *p = &__bss_start;
for (; p < &__bss_end; p++)
*p = 0;
}
上面的代码时以前自己写u-boot中用到了c函数清除bss段,引用段名的方法是int *p = &__bss_start;一直以为引用段名是固定写法。直到今天看到了linux-4.19-rc3中使用段名的方法才发现端倪。
static const void * __init arch_get_next_mach(const char *const **match)
{
static const struct machine_desc *mdesc = __arch_info_begin;
const struct machine_desc *m = mdesc;
if (m >= __arch_info_end)
return NULL;
mdesc++;
*match = m->dt_compat;
return m;
}
4.19内核中有这么一个函数,功能是取得.arch.info.init段中每个结构体的dt_compat成员,功能上没什么问题,就是对引用段名的方式出现了疑问,这个地方的引用的方法和以前的认知有点不同。
我在内核中搜索了__arch_info_begin,得到了以下的结果
extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
__arch_info_begin被声明成了一个结构体数组,所以在arch_get_next_mach()函数中才能使用指针进行引用。
static const struct machine_desc *mdesc = __arch_info_begin;
这样就得到了一个结论:段名的引用其实和声明有关,而不是简单的固定写法。