1,linux内核的基础知识
1.1 linux内核版本
从内核源码顶层目录Makefile中可以看到:
- VERSION和PATCHLEVEL组成主版本号,比如2.4、2.5、2.6等,稳定版本的德主版本号用偶数表示(比如2.6的内核),开发中的版本号用奇数表示(比如2.5),它是下一个稳定版本内核的前身。
- SUBLEVEL称为次版本号,它不分奇偶,顺序递增,每隔1~2个月发布一个稳定版本。
- EXTRAVERSION称为扩展版本号,它不分奇偶,顺序递增,每周发布几次扩展本版号。
1.2 什么是标准内核
按照资料上的习惯说法,标准内核(或称基础内核)就是指主要在http://www.kernel.org/维护和获取的内核,实际上它也有平台属性的。这些linux内核并不总是适用于所有linux支持的体系结构。实际上,这些内核版本很多时候并不是为一些流行的嵌入式linux系统开发的,也很少运行于这些嵌入式linux系统上,这个站点上的内核首先确保的是在Intel X86体系结构上可以正常运行,它是基于X86处理器的内核,如对 linux-2.4.18.tar.bz2的配置make menuconfig时就可以看到,Processor type and features--->中只有386、486、586/K5/5x86/6x86/6x86MX、Pentium-Classic、Pentium-MMX、Pentium-Pro/Celeron/Pentium-II、Pentium-III/Celeron(Coppermine)、Pentium-4、K6/K6-II/K6-III 、Athlon/Duron/K7 、Elan 、Crusoe、Winchip-C6 、Winchip-2 、Winchip-2A/Winchip-3 、CyrixIII/C3 选项,而没有类似Samsun 2410等其他芯片的选择。如果需要用在其他特定的处理器平台上就需要对内核进行打补丁,形成不同的嵌入式内核。实际上,不同处理器系统的内核下载站点中提供的也往往是补丁patch而已,故原x86平台上的内核变成了基础内核,也被称为标准内核了。
ARM用的RISC精简指令集,每条指令长度固定32bit;常用的100条汇编指令
X86的CISC复杂指令集,每条指令长度不固定。指令比上面多太多,但是常用的也差不多。
比如要移动内存里的一个数据,CISC可以一条实现,但是,精简指令至少两条或更多。
因此x86的内核就要比ARM内核的结构复杂很多,因此贵很多。
1.3 Linux操作系统的分类
第一种分类:以主要功能差异和发行组织区分(即基础linux系统/内核是不同的)
- 标准linux
- μClinux(无MMU支持的linux系统,运行在无MMU的CPU上)
- Linux-RT(是最早在linux上实现硬实时支持的linux发行版本)
- Embedix(由Lineo公司开发,基于PowerPC和x86平台开发的)
- 其他
第二层分类中的linux系统/内核相对于第一层分类的标准内核来说,也可以称为嵌入式linxu系统/内核。如应用在ARM平台上的嵌入式Linux系统通常有arm-linux(常运行在arm9平台上),μClinux(常用在arm7平台上),在标准linux基础上扩展对其他的平台的支持往往通过安装patch实现,如armlinux就是对linux安装rmk补丁(如patch-2.4.18-rmk7.bz2)形成的,只有安装了这些补丁,内核才能顺利地移植到ARM Linux上。也有些是已经安装好补丁的内核源码包,如linux-2.4.18-rmk7.tar.bz2。
不同处理器系统的内核/内核补丁下载站点:
处理器系统 适合的内核站点 下载方式
x86 http://www.kernel.org/ ftp, http, rsync
ARM http://www.arm.linux.org.uk/developer/ ftp, rsync
PowerPC http://penguinppc.org/ ftp, http, rsync, BitKeeper
MIPS http://www.linux-mips.org/ ftp, cvs
SuperH http://linuxsh.sourceforge.net/ cvs, BitKeeper
M68K http://linux-m68k.org/ ftp, http
non-MMU CPUs http://www.uclinux.org/ ftp, http
这些站点不仅仅是linux内核站点,它们可能直接提供了针对你的目标硬件系统的linux内核版本。
1.4 linux内核的选择
ARM Linux的移植,建议使用2.4.x或2.6.x版本。当然大部分你使用的硬件平台会提供linux内核的说明。
2,linux内核启动过程
一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux 内核,文件系统,应用程序。其中 Bootloader是系统启动或复位以后执行的第一段代码,它主要用来初始化处理器及外设,然后调用 Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个文件系统做为根文件系统(Root Filesystem)。根文件系统是 Linux 系统的核心组成部分,它可以做为Linux 系统中文件和数据的存储区域,通常它还包括系统配置文件和运行应用软件所需要的库。应用程序可以说是嵌入式系统的“灵魂”,它所实现的功能通常就是设计该嵌入式系统所要达到的目标。如果没有应用程序的支持,任何硬件上设计精良的嵌入式系统都没有实用意义。
2.1Bootloader启动过程
1)Bootloader概念和作用
Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于 PC 机上的 BIOS。
在完成对系统的初始化任务之后,它会将非易失性存储器(通常是Flash或DOC等)中的Linux 内核拷贝到 RAM 中去,然后跳转到内核的第一条指令处继续执行,从而启动 Linux 内核。
2)Bootloader的执行过程
实际应用中的 Bootloader根据所需功能的不同可以设计得很复杂,除完成基本的初始化系统和调用 Linux 内核等基本任务外,还可以执行很多用户输入的命令,比如设置 Linux 启动参数,给 Flash 分区等;也可以设计得很简单,只完成最基本的功能。但为了能达到启动Linux 内核的目的,所有的 Bootloader都必须具备以下功能:
2.2linux启动过程
Linux 内核有两种映像:一种是非压缩内核,叫 Image,另一种是它的压缩版本,叫 zImage。根据内核映像的不同,Linux 内核的启动在开始阶段也有所不同。zImage 是 Image经过压缩形成的,所以它的大小比 Image 小。但为了能使用 zImage,必须在它的开头加上解压缩的代码,将 zImage 解压缩之后才能执行,因此它的执行速度比 Image 要慢。但考虑到嵌入式系统的存储空容量一般比较小,采用 zImage 可以占用较少的存储空间,因此牺牲一点性能上的代价也是值得的。所以一般的嵌入式系统均采用压缩内核的方式。
__lookup_processor_type调用结束返回原程序时,会将返回结果保存到寄存器中。其中r8 保存了页表的标志位,r9 保存了处理器的 ID 号,r10 保存了与处理器相关的 stru proc_info_list 结构地址。
- 调用 setup_arch()函数进行与体系结构相关的第一个初始化工作;对不同的体系结构来说该函数有不同的定义。对于 ARM 平台而言,该函数定义在arch /arm/ kernel/Setup.c。它首先通过检测出来的处理器类型进行处理器内核的初始化,然后通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用paging_init()开启 MMU,创建内核页表,映射所有的物理内存和 IO空间。
- 创建异常向量表和初始化中断处理函数;
- 初始化系统核心进程调度器和时钟中断处理机制;
- 初始化串口控制台(serial-console);ARM-Linux 在初始化过程中一般都会初始化一个串口做为内核的控制台,这样内核在启动过程中就可以通过串口输出信息以便开发者或用户了解系统的启动进程。
- 创建和初始化系统 cache,为各种内存调用机制提供缓存,包括;动态内存分配,虚拟文件系统(VirtualFile System)及页缓存。初始化内存管理,检测内存大小及被内核占用的内存情况;
- 初始化系统的进程间通信机制(IPC);
execve("/sbin/init",argv_init,envp_init)
execve("/etc/init",argv_init,envp_init)
execve("/bin/init",argv_init,envp_init)
execve("/bin/sh",argv_init,envp_init)
当所有的初始化工作结束后,cpu_idle()函数会被调用来使系统处于闲置(idle)状态并等待用户程序的执行。至此,整个 Linux 内核启动完毕。
通过对Linux 的启动过程的分析,我们可以看出哪些是和硬件相关的,哪些是Linux 内核内部已实现的功能,这样在移植Linux 的过程中便有所针对。而Linux内核的分层设计将使Linux 的移植变得更加容易。
大部分转载自:https://blog.csdn.net/kelsey11/article/details/74075143