kernel移植
kernel概述
内核相当于操作系统,它为上层应用提供进程控制、内存管理、设备驱动、文件系统、网络控制等基础功能。
kernel编译
使用补丁文件编译
- 解压kernel源码
- 打补丁,patch -p1 < 补丁文件
- 配置,有如下三种方法
- make menuconfig 自己配置,不建议
- 使用kernel源码的默认配置文件
- 找到arch/arm/configs/下相似的配置文件,xxx_defconfig
- 在顶层目录make xxx_defconfig,xxx_deconfig文件,将写入顶层目录下的.config文件中,之后make menuconfig会读取.config,显示配置结果
- 使用厂家提供的配置文件
即顶层目录的config.ok,将其cp config.ok .config即可。
- make uImage
uImage:64K头部+实际内核数据,在uboot移植时可知(uboot环境变量中的bootcmd),拷贝内核时,将读取头部,再拷贝实际内核数据至ram中
配置过程
make xxx_deconfig,将生成顶层目录下的.config
.config文件内有:
例如,CONFIG_DM9000=y
grep -rn CONFIG_DM9000 ./*,查看该字符出现在哪些文件中:
1、C源码,arch/arm/plat-s3c24xx/common-smdk.c,
#if defined(CONFIG_DM9000)
由4可知,C源码的CONFIG_DM9000,在autoconf.h中定义
2、makefile文件:/drivers/net/Makefile中
obj-$(CONFIG_DM9000) += dm9dev9000c.o
根据3,将dm9dev9000c.c编译进内核
3、include/config/auto.conf,
CONFIG_DM9000=y
这里的CONFIG_DM9000,是从.config中读取的,这里的y,表示将其编译进内核
该auto.conf被顶层makefile包含,供子目录makefile使用
4、include/linux/autoconf.h
#define CONFIG_DM9000 1
这里的CONFIG_DM9000,是从.config中读取的,并在autoconf.h写成#define CONFIG_DM9000 1
编译过程分析
make uImage
1、顶层makefile:
找uImage目标,未找到,但有如下:
include $(srctree)/arch/$(ARCH)/Makefile
2、分析arch/arm/Makefile
zImage Image xipImage bootpImage uImage: vmlinux
==>依赖于vmlinux
3、vmlinux在顶层makefile中制定规则:
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
$(call if_changed_rule,vmlinux__)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
$(Q)rm -f .old_version
展开vmlinux的依赖,如下:
vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds ==》arch/arm/kernel/vmlinux.lds
vmlinux-init := $(head-y) $(init-y)
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
init-y := init/
init-y := $(patsubst %/, %/built-in.o, $(init-y))
patsubst替换通配符,将$(init-y)目录下的%/(即所有文件),替换为built-in.o,即将init下所有文件编译成built-in.o
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y := $(patsubst %/, %/built-in.o, $(core-y))
==》链接为usr/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
libs-y := $(libs-y1) $(libs-y2)
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := lib/
libs-y := arch/arm/lib/ $(libs-y) //arch/arm/Makefile
==》lib/lib.a lib/built-in.o
drivers-y := drivers/ sound/
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
==》drivers/built-in.o sound/built-in.o
net-y := net/
net-y := $(patsubst %/, %/built-in.o, $(net-y))
==》net/built-in.o
以上,有些宏定义例如core-y,在arch/arm/Makefile中也有定义,这里没有一一列举出来
4、make过程
链接脚本为arch/arm/kernel/vmlinux.lds,里面定义了uImage的内存分布
第一个执行的文件为:arch/arm/kernel/head.S
内核启动流程
内核最终目的:挂接根文件系统,启动应用程序
uboot:do_bootm_linux:
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);//启动内核
1、处理uboot传递的参数
bd->bi_arch_number:机器码,uboot源码中定义
比较机器码,看本kernel是否支持该板子
kernel源码中定义了对应板子的机器码,编译至内存某一区段
bd->bi_boot_params:uboot启动参数
2、启动内核
流程概述如下:
start_kernel:
rest_init:
kernel_init:
prepare_namespace:
mount_root //挂载根文件系统
init_post:
//执行应用程序