学习笔记:内核启动流程

来源:互联网 发布:linux运行jar文件 编辑:程序博客网 时间:2024/06/06 14:07

⒈内核的配置:
Ⅰ、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.ldsexport 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 }

这里写图片描述

1 0
原创粉丝点击