⒈内核的配置:
Ⅰ、cp config_ok .config
Ⅱ、make uImage时:
.config生成include/linux/autoconf.h
.config生成include/config/auto.conf,被顶层Makefile包含,子目录下的Makefile用它。
⒉分析Makefile:
找到第一个文件:提纲挈领,顺藤摸瓜
链接脚本:内核放在那里,里面的东西是怎么排布的
Ⅰ、uImage: vmlinux
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
Ⅱ、vmlinux: vmlinux-lds vmlinux-init vmlinux-main kallsyms.o
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
⑴、vmlinux-init
vmlinux-init := $(head-y) $(init-y)
①、head-y
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
②、init-y
init-y := init/
init-y := $(patsubst %/, %/built-in.o, $(init-y))
⑵、vmlinux-main
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
①、core-y
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y := $(patsubst %/, %/built-in.o, $(core-y))
②、libs-y
libs-y := lib/
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
③、drivers-y
drivers-y := drivers/ sound/
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
④、net-y
net-y := net/
net-y := $(patsubst %/, %/built-in.o, $(net-y))
Ⅲ、
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
Ⅳ、在编译uImage时原材料按以下方式组成内核
arm-linux-ld -EL -p --no-undefined -X -o vmlinux
-T arch/arm/kernel/vmlinux.lds
arch/arm/kernel/head.o
arch/arm/kernel/init_task.o
init/built-in.o
--start-group
usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o
--end-group
.tmp_kallsyms2.o
由此,我们找到了第一个文件:
arch/arm/kernel/head.S
链接脚本:
arch/arm/kernel/vmlinux.lds
3.分析head.S文件
Ⅰ、u-boot的传入参数有
⑴、机器ID
⑵、启动参数
Ⅱ、head.S主要功能:
⑴、判断是否支持这个CPU
bl __lookup_processor_type
⑵、判断是否支持这个单板,机器ID在这步进行匹配
bl __lookup_machine_type
⑶、建立页表
bl __create_page_tables
⑷、使能MMU
adr lr, __enable_mmu
⑸、跳到linux-2.6.22.6\init\main.c:start_kernel函数,启动参数会在linux-2.6.22.6\init\main.c:start_kernel函数中处理
启动参数处理函数:
setup_arch(&command_line);
setup_command_line(command_line);
4、挂载根文件系统:(☞☞:调用)
linux-2.6.22.6\init\main.c:asmlinkage void __init start_kernel(void)
☞☞
linux-2.6.22.6\init\main.c:static void noinline __init_refok rest_init(void)
{
...
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
...
}
☞☞
linux-2.6.22.6\init\main.c:static int __init kernel_init(void * unused)
☞☞
linux-2.6.22.6\init\do_mounts.c:void __init prepare_namespace(void)
☞☞
linux-2.6.22.6\init\do_mounts.c:void __init mount_root(void)
5、通过以上步骤挂载好根文件系统后调用linux-2.6.22.6\init\main.c:init_post函数执行第一个应用程序
static int noinline init_post(void)
{
...
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
...
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults...\n", execute_command);
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
}
...
}
其中execute_command指针地址上得内容如下可得,是命令行参数init的值,宏__setup("init=", init_setup)
会调用linux-2.6.22.6\init\main.c:init_setup函数将命令行参数传到execute_command保存的地址上去:
static char *execute_command;
static int __init init_setup(char *str)
{
unsigned int i;
execute_command = str;
/*
* In case LILO is going to boot us with default command line,
* it prepends "auto" before the whole cmdline which makes
* the shell think it should execute a script with such name.
* So we ignore all arguments entered _before_ init=... [MJ]
*/
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("init=", init_setup);
宏__setup("init=", init_setup)
在如下定义
linux-2.6.22.6\linux-2.6.22.6\include\linux\init.h:
#define __setup(str, fn) \ __setup_param(str, fn, fn, 0)
#define __setup_param(str, unique_id, fn, early) \
static char __setup_str_##unique_id[] __initdata = str; \
static struct obs_kernel_param __setup_##unique_id \
__attribute_used__ \
__attribute__((__section__(".init.setup"))) \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }