您的位置:首页 > 运维架构 > Linux

解读linux内核代码之boot(1)

2011-06-10 21:27 253 查看
最近开始研究linux内核,之前本来是在看《Understanding The Linux Kernel》,看了几章之后,发现虽然这本书讲的很通俗易懂,但是我看的是第二版,书中对应的内核版本是2.4的,而现在最新的内核版本确实2.6.39的,大体上算法是差不多的,但是很多代码实现完全不同了,所以就放弃了这本书,开始从源代码入手开始看。

由于内核代码很多,刚开始也不知道从哪里开始看起,纠结了很久才决定从内核boot的代码开始看起。

boot的代码在/arch/x86/boot/这个目录下,下面很明显的有个main.c文件,自然地打开一看,里面有个main函数,如下

void main(void)

{

/* First, copy the boot header into the "zeropage" */

copy_boot_params();

/* Initialize the early-boot console */

console_init();

if (cmdline_find_option_bool("debug"))

puts("early console in setup code/n");

/* End of heap check */

init_heap();

/* Make sure we have all the proper CPU support */

if (validate_cpu()) {

puts("Unable to boot - please use a kernel appropriate "

"for your CPU./n");

die();

}

/* Tell the BIOS what CPU mode we intend to run in. */

set_bios_mode();

/* Detect memory layout */

detect_memory();

/* Set keyboard repeat rate (why?) */

keyboard_set_repeat();

/* Query MCA information */

query_mca();

/* Query Intel SpeedStep (IST) information */

query_ist();

/* Query APM information */

#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)

query_apm_bios();

#endif

/* Query EDD information */

#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)

query_edd();

#endif

/* Set the video mode */

set_video();

/* Do the last things and invoke protected mode */

go_to_protected_mode();

}

函数的第一句调用函数copy_boot_params(), 这个函数依然在本文件中,作用是拷贝boot参数到第一个内存page,提醒一句,这个时候cpu还是运行在实模式下。copy_boot_params()的实现如下

static void copy_boot_params(void)

{

struct old_cmdline {

u16 cl_magic;

u16 cl_offset;

};

const struct old_cmdline * const oldcmd =

(const struct old_cmdline *)OLD_CL_ADDRESS;

BUILD_BUG_ON(sizeof boot_params != 4096);

memcpy(&boot_params.hdr, &hdr, sizeof hdr);

if (!boot_params.hdr.cmd_line_ptr &&

oldcmd->cl_magic == OLD_CL_MAGIC) {

/* Old-style command line protocol. */

u16 cmdline_seg;

/* Figure out if the command line falls in the region

of memory that an old kernel would have copied up

to 0x90000... */

if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)

cmdline_seg = ds();

else

cmdline_seg = 0x9000;

boot_params.hdr.cmd_line_ptr =

(cmdline_seg << 4) + oldcmd->cl_offset;

}

}

这个函数逻辑是简单的,我并不想说这个,注意这一句memcpy(&boot_params.hdr, &hdr, sizeof hdr);中hdr这个变量,这个结构体变量在main.c里面并没有定义,然后我惊讶地发现这个hdr居然在linux内核代码中所有的h文件和c文件中都没有定义,出了在boot.h中声明了一下extern struct setup_header hdr;

最后把目光发在head.s这个汇编文件上,打开一看,果然hdr这个变量是在这个汇编文件中定义的。

在header.s中,实现了内核启动执行main函数(如上文说的)之前做的动作,包括定义hdr变量并赋值,分配stack,然后调用main函数,以及内核不能正确启动的打印信息等等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: