在linux系统软件架构可以分为4个层次(从低到高分别为):
1.引导加载程序
引导加载程序(Bootloader)是固化在硬件Flash中的一段引导代码,用于完成硬件的一些基本配置,引导内核启动。
同时,Bootloader会在自身与内核分区之间存放一些可设置的参数(Boot parameters),比如IP地址,串口波特率,要传递给内核的命令行参数。
2.系统内核
系统内核(Kernel)是整个操作系统的最底层,它负责整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制、是否支持LVM或Quota等文件系统等等,如果内核不认识某个最新的硬件,那么硬件也就无法被驱动,你也就无法使用该硬件。计算机真正工作的东西其实是硬件,例如数值运算要使用到CPU、数据储存要使用到硬盘、图形显示会用到显示适配器、音乐发声要有音效芯片、连接Internet 可能需要网络卡等等。内核就是控制这些芯片如何工作。
3.文件系统
Linux文件系统(File System)中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。
4.用户程序
用户应用程序(Application)为了完成某项或某几项特定任务而被开发运行于操作系统之上的计算机程序。
正常启动过程中,Bootloader首先运行,然后将内核复制到内存中(或者在固态存储设备上直接运行,但是效率较低),并在内存某个固定的地址(包括地址与参数的结构)设置好要传递给内核的参数,最后运行内核。内核启动后,挂载(mount)根文件系统(Root filesystem),启动文件系统中的应用程序。
上电 ——> Bootloader —[传递参数]—> 加载内核 ——> 内核挂载根文件系统 ——>执行应用程序
操作系统内核本身就是一个裸机程序,和我们学的uboot和其他裸机程序没有本质的区别;事实上,不少U-Boot源码就是根据相应的Linux内核源程序进行简化而形成的,尤其是一些设备的驱动程序。如果我们去琢磨U-Boot源码的注释,便会轻易的发现这一情况。
区别就是操作系统运行起来后可以分为应用层(用户态)和内核层(内核态),分层后,两层的权限不同(实现的原理是基于CPU的模式切换),内存访问和设备操作的管理上更加精细(内核可以随便方位各种硬件,而应用程序只能被限制的访问硬件和内存地址)。
以ARM处理器为例,除用户模式外,其余6种工作模式都属于特权模式:
用户模式(USR):正常程序执行模式,不能直接切换到其他模式
系统模式(SYS):运行操作系统的特权任务,与用户模式类似,但具有可以直接切换到其他模式等特权
快中断模式(FIQ):支持高速数据传输及通道处理,FIQ异常响应时进入此模式
中断模式(IRQ):用于通用中断处理,IRQ异常响应时进入此模式
管理模式(SVC):操作系统保护模式,系统复位和软件中断响应时进入此模式(由系统调用执行软中断SWI命令触发)
中止模式(ABT):用于支持虚拟内存和/或存储器保护,在ARM7TDMI没有大用处
未定义模式(UND):支持硬件协处理器的软件仿真,未定义指令异常响应时进入此模式
Linux内核态是从ARM的SVC即管理模式下启动的,但在某些情况下、如:硬件中断、程序异常(被动)等情况下进入ARM的其他特权模式,这时仍然可以进入内核态(因为就是可以操作内核了);同样,Linux用户态是从ARM用户模式启动的,但当进入ARM系统模式时、仍然可以操作Linux用户态程序(进入用户态,如init进程的启动过程)。
即:Linux内核从ARM的SVC模式下启动,但内核态不仅仅指ARM的SVC模式(还包括可以访问内核空间的所有ARM模式);Linux用户程序从ARM的用户模式启动,但用户态不仅仅指ARM的用户模式。
直观来看:uboot的镜像是u-boot.bin,Linux系统的镜像是zImage,这两个东西其实都是裸机程序镜像。从系统启动的角度来讲,内核和uboot都是裸机程序。
Linux文件系统中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。这种机制有利于用户和操作系统的交互。
尽管内核是 Linux 的核心,但文件却是用户与操作系统交互所采用的主要工具。这对 Linux 来说尤其如此,这是因为在 UNIX 传统中,它使用文件 I/O 机制管理硬件设备和数据文件
Linux支持多种文件系统类型,因为它将底层与应用层分隔开;而提供统一的接口支持应用层对于不同实现的文件系统的访问,这个统一的接口称为虚拟文件系统VFS。
kernel中以VFS去支持各种文件系统,如yaffs,ext3,cramfs等等。yaffs/yaffs2是专为嵌入式系统使用NAND型闪存而设计的一种日志型文件系统。在内核中以VFS来屏蔽各种文件系统的接口不同,以VFS向kernel提供一个统一的接口。
文件系统指文件存在的物理空间,linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。以“/”为顶级目录的文件系统称为根文件系统。
Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。系统正常挂载根文件系统之后可以自动或手动挂载其他的文件系统(根文件系统是其他文件的最终挂载点)。因此,一个系统中可以同时存在不同的文件系统。
也就是说:
根文件系统可以是任何kernel支持的文件系统类型(ext4,yaffs等)。
但它必须包含linux内核启动时所必需的文件(根文件系统必需存在的目录 /dev /bin /sbin 等等),不然系统启动会失败。
根文件系统是之所以有个根(/)字,是因为它是linux系统启动时挂载(mount,所谓挂载:就是在内存中创建一个虚拟的文件对应具体的存储空间分区的过程,挂载时不会保存信息,下次启动时得重新挂载)的第一个文件系统,启动完成后可以自动(配置etc/fstab)或者手动的方式将其它文件系统(分区)挂载到根文件系统中。
不同的文件系统类型有不同的特点,因而根据存储设备的硬件特性、系统需求等有不同的应用场合。在嵌入式Linux应用中,主要的存储设备为 RAM(DRAM, SDRAM)和ROM(常采用FLASH存储器),常用的基于存储设备的文件系统类型包括:jffs2, yaffs, cramfs, romfs, ramdisk,initramfs, ramfs/tmpfs,ubifs等。
早期的uboot没有分区的概念,uboot只知道应该将什么数据烧写到存储介质的什么区间中。
(也就是说,对于uboot来看,只有起始地址结束地址等,A~B地址放内核,C~D地址放文件系统,即:规定哪个地址区间放内核或者文件系统等)
虽然此后,uboot中渐渐也有了MTD等管理分区部分的功能。尽管如此,不影响我们的学习理解。
cpu首先执行位于0地址的uboot,uboot启动以后初始化一些资源,告诉内核有关的参数并引导内核,内核通过事先添加对于某种文件系统类型的支持驱动(相当于一小段程序),读取uboot等boot loader在指定的区域烧写制作好的文件系统镜像,内核解析并挂载成根文件系统,并在此基础上,通过VFS再挂载不同的文件系统类型,完成启动以后,再去管理有关的资源(包括应用程序)