Android内核是基于Linux 2.6内核的(MSD6A608使用2.6.35.11版本的内核),并且是Linux 2.6内核的一个增强版本,除了修改部分Bug外,它提供了用于支持Android平台的设备驱动。
内核代码的产生(Zip&unZip Kernel)
Kernel代码编译连接后产生kernel镜像,kernel镜像分为压缩与非压缩两种。压缩内核镜像是把非压缩内核镜像作为数据进行压缩打包,并加上了解压缩代码。也就是说,它是一个自解压的可执行镜像。两种内核镜像的产生过程如下图:
内核入口(Entry of kernel)
Linux 内核编译连接后生成的ELF 映像文件是vmlinux,从内核源代码顶层目录下的 Makefile(即顶层Makefile)中可以找到vmlinux 的生成规则:
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
其中$(vmlinux-lds)是编译连接脚本,对于ARM 平台,就是arch/arm/kernel/vmlinux-lds 文件。
vmlinux-init 也在顶层Makefile 中定义: vmlinux-init := $(head-y) $(init-y)
head-y 在arch/arm/Makefile 中定义:
head-y:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o ?
ifeq ($(CONFIG_MMU),) MMUEXT := -nommu endif
对于有 MMU 的处理器,MMUEXT 为空白字符串,所以arch/arm/kernel/head.O 是第一个连
接的文件,而这个文件是由arch/arm/kernel/head.S 编译产生成的。 ARM Linux 启动过程分析
综合以上分析,可以得出结论,非压缩 ARM Linux 内核的入口点在arch/arm/kernel/head.S中。
head.S最后包含了head-common.S,在head-common.S中定义调转到C语言入口函数start_kernel()。
start_kernel()函数
start_kernel()函数是内核初始化C语言部分的主体。。这个函数完成系统底层基本机制,包括处理器、存储管理系统、进程管理系统、中断机制、定时机制等的初始化工作。start_kernel()函数的实现在init/main.c。start_kernel()函数完成基本的初始化工作后,最后调用了rest_init()函数。下面来看看rest_init()函数的实现,同样在init/main.c定义:
static noinline void __init_refok rest_init(void) __releases(kernel_lock) { int pid; rcu_scheduler_starting(); /* * We need to spawn init first so that it obtains pid 1, however * the init task will end up wanting to create kthreads, which, if * we schedule it before we create kthreadd, will OOPS. */ kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);//创建第一个内核线程,入口点是kernel_init()函数
numa_default_policy(); pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);//创建第二个内核线程,入口点是kthreadd()函数
rcu_read_lock(); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); rcu_read_unlock(); complete(&kthreadd_done); unlock_kernel();
}
/*
* The boot idle thread must execute schedule() * at least once to get things moving: */
init_idle_bootup_task(current); preempt_enable_no_resched(); schedule();
preempt_disable();
/* Call into cpu_idle with preempt disabled */ cpu_idle(); //进入空闲状态
该函数创建了一个入口点init()函数的内核线程,新创建的内核线程pid=1,放入了调度队列中,系统转而执行kernel_init()函数,kernel_init()函数同样在/init/main.c中实现,该函数完成系统更高层次,比如驱动程序,根文件系统等等的初始化工作,其中的关键点为:
do_basic_setup()函数比较重要,这个函数先调用driver_init()函数完成驱动程序的初始化,又通过do_initcalls()函数依次调用了系统中所有的初始化函数。
接着看kernel_init()函数,该函数接着加载了外部程序/init从而有了自己的用户态空间,进而变成了一个进程,然后该进程再执行用户态的初始化程序,如创建终端,等待用户登录等等,系统启动完成。
Android应用系统
Android源代码由两部分组成,Android内核代码和Android系统应用部分的代码。MStar android TV的系统应用代码放在android/ics目录下,顶层目录如下:
Android/abi (abi相关代码。ABI:applicationbinary interface,应用程序二进制接口) Android/bionic(bionic C库)
Android/bootable(启动引导相关代码)
Android/build(存放系统编译规则及generic等基础开发配置包) Android/cts(Android兼容性测试套件标准) Android/dalvik(dalvik JAVA虚拟机)
Android/development(应用程序开发相关) Android/device (设备相关代码) Android/docs (介绍开源的相关文档)
Android/external(android使用的一些开源的模组)
Android/frameworks(核心框架——java及C++语言,是Android应用程序的框架。) Android/hardware(主要是硬件适配层HAL代码) Android/libcore(核心库相关)
Android/ndk (ndk相关代码。AndroidNDK(Android NativeDevelopment Kit)是一系列的开发工具,允许程序开发人员在Android应用程序中嵌入C/C++语言编写的非托管代码。)
Android/out(编译完成后的代码输出与此目录) Android/packages(应用程序包)
Android/prebuilt(x86和arm架构下预编译的一些资源) Android/sdk(sdk及模拟器)
Android/system(文件系统、应用及组件——C语言) Android/Makefile
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库Mstar理论及实践篇(5)在线全文阅读。
相关推荐: