linux中INIT_MM_CONTEXT宏对pgd的重复赋值
在GNU C中,支持通过标号元素对指定结构体成员名进行初始化,这允许初始化值以任意顺序出现。
在linux内核中对init_mm初始化时有如下代码。
#define INIT_MM_CONTEXT(name) \.pgd = init_pg_dir,struct mm_struct init_mm = {.mm_rb = RB_ROOT,.pgd = swapper_pg_dir,.mm_users = ATOMIC_INIT(2),.mm_count = ATOMIC_INIT(1),.write_protect_seq = SEQCNT_ZERO(init_mm.write_protect_seq),MMAP_LOCK_INITIALIZER(init_mm).page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),.arg_lock = __SPIN_LOCK_UNLOCKED(init_mm.arg_lock),.mmlist = LIST_HEAD_INIT(init_mm.mmlist),.user_ns = &init_user_ns,.cpu_bitmap = CPU_BITS_NONE,INIT_MM_CONTEXT(init_mm)
};
其中对.pgd进行了两次赋值,第一次是.pgd = swapper_pg_dir, 而最后,又使用INIT_MM_CONTEXT宏对其进行了赋值,那结果如何呢?
请看如下测试代码:
#include <stdio.h>#define __pr(x) printf("%-40s: %d\n", #x, x)struct test {int a;int b;int c;
};int main(void)
{struct test val = {.a = 1,.c = 2,.a = 3, // final val};__pr(val.a);__pr(val.b);__pr(val.c);return 0;
}
测试结果:
val.a : 3
val.b : 0
val.c : 2
从测试结果来看,最终结果以最后一次赋值为准。
除了结构体可以覆盖之前的值外,数组的赋值也有类似特性,如kernel/time/hrtimer.c中
static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {/* Make sure we catch unsupported clockids */[0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES,[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,[CLOCK_TAI] = HRTIMER_BASE_TAI,
};