本章主要是这两步:
boot_cpu_init();
在CPU位图中注册当前运行CPU
page_address_init();
初始化HIGHMEM管理
boot_cpu_init
kernel/cpu.c
static DECLARE_BITMAP(cpu_possible_bits,
CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_possible_mask =
to_cpumask(cpu_possible_bits);
EXPORT_SYMBOL(cpu_possible_mask);
static DECLARE_BITMAP(cpu_online_bits,
CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_online_mask =
to_cpumask(cpu_online_bits);
EXPORT_SYMBOL(cpu_online_mask);
static DECLARE_BITMAP(cpu_present_bits,
CONFIG_NR_CPUS) __read_mostly;
const struct cpumask *const cpu_present_mask =
to_cpumask(cpu_present_bits);
EXPORT_SYMBOL(cpu_present_mask);
这里先申请了3个位图,用来维护系统内CPU的状态信息。每一位代表了一个CPU的某种状态。
比如cpu_possible_bit, 是系统中可执行当前热插拔(hot
plug)的CPU的位图。
cpu_online_bits,是将online(使用中)的所有CPU的位设置为1的位图。
cpu_present_bits,是显示系统内CPU的位图,并非所有CPU处于online状态。
每个位图一般都是一个long型的数组(一般只有一个成员,毕竟每个long至少有32位,一般不会有超过32个CPU)
static void __init boot_cpu_init(void)
{
int cpu = smp_processor_id();
获取执行当前任务的CPU号
set_cpu_online(cpu, true);
set_cpu_present(cpu, true);
set_cpu_possible(cpu, true);
}
这个函数将三种位图(cpu_possible_bit,cpu_online_bits,cpu_present_bits)中的对应当前CPU
ID的位设为1。
像set_cpu_online只是一些移位的算数操作,不再研究
page_address_init
管理高端内存。网上找了个文章贴在附件。
高端内存是RAM中896M以上的内存空间,该区域用于用户空间程序或页缓存。高端内存不能直接映射,所以比低端内存(内核可以直接映射的内存)访问速度更慢。
内核使用 kmap()
映射高端内存(ZONE_HIGHMEM),用散列表page_address_htable另行管理HIGHMEM中分配的内存。
static struct page_address_map page_address_maps[LAST_PKMAP];
LAST_PKMAP =
512
void __init page_address_init(void)
{
int i;
INIT_LIST_HEAD(&page_address_pool);
创建了一个页地址的池子,起始是个链表头,下面会把512个page_address_maps数组的成员链接到这个头上。
for (i = 0; i < ARRAY_SIZE(page_address_maps);
i++)
list_add(&page_address_maps[i].list,
&page_address_pool);
for (i = 0; i < ARRAY_SIZE(page_address_htable);
i++) {
INIT_LIST_HEAD(&page_address_htable[i].lh);
初始化数组page_address_htable所有成员的内部变量
spin_lock_init(&page_address_htable[i].lock);
}
spin_lock_init(&pool_lock);
}