Linux开发五_构建根文件系统

时间:2022-04-29 08:49:12

Linux开发五

构建根文件系统

象棋小子    1048272975

文件系统是对一个存储设备上的数据和元数据进行组织的机制,根文件系统是linux内核启动时所挂载的第一个文件系统。对于一个可启动的linux系统,根文件系统是其不可或缺的一部分。笔者此处就根文件系统的构建作一个简单的介绍。

1. 根文件系统概述

linux系统为了精简以及便于维护,分成了内核空间以及用户空间。linux内核由内存管理、进程管理、设备驱动程序、网络管理等组成,它是操作系统的核心,具有很多最基本的功能,决定了系统的性能和稳定性。用户空间的文件系统用来提供管理系统的各种配置,提供相应的应用程序、服务、数据交换等。文件系统作为一种载体,它是用来实现用户与操作系统内核的交互。

linux内核启动完成之后,会尝试执行用户空间的第一个程序,init进程,用户空间根据这个进程,派生出其它的用户子进程。由于内核空间与用户空间的分离,linux内核必须要有一定的方法去加载执行用户空间的init进程,通常linux内核会在根文件系统相应的目录去尝试执行这个用户进程,如果未能加载执行,则内核panic。因此,一个可启动的linux系统必须包含linux内核以及一个根文件系统。

2. 构建最简单的根文件系统

根文件系统可以有不同的文件系统类型,如yaffs、网络文件系统NFS、initramfs等,也可以在不同的存储设备上,如nandflash、sd/mmc、u盘等。此处以initramfs为例说明根文件系统的构建。initramfs是一个ram文件系统,在initrd技术问题背景下,所提出一种更简单、更高效的新的处理方式。基于内存的文件系统,往往只是做为一种过渡手段,用来挂载系统真正的根文件系统,但对于很多嵌入式系统来说,initramfs往往也是最终的文件系统。

如前面所述,linux内核启动到最后会尝试加载执行根文件系统里的init用户程序,因此根文件系统里只要给内核提供init可执行文件,转到用户空间,linux系统则算启动成功。此处编写一个简单的init应用程序Hello world。

#include"stdio.h"

#include"stdlib.h"

 

int main(void)

{

       int i;

i = 0;

       while (1) {

              printf("Hello world %d\n", i);

              sleep(1);

              i++;

       }

}

此处可用宿主机gcc进行编译执行以验证代码效果,然后用arm-linux-gcc静态编译,使之生成arm CPU可执行的指令,并且可脱离任何库独立运行,arm-linux-gcc -static -o init init.c,生成init可执行文件,用readelf命令查看确保生成的init可执行文件为armv5指令集,软浮点(s3c2416)。

创建一个example文件夹用作为根文件系统目录,把init可执行文件放在example目录下,由于用printf打印,需要使用控制台,因为还需要控制台设备文件。创建dev目录,在该目录下创建console设备节点,mknod /dev/console c 5 1即可。因此,在example目录下,一个最简单的打印Helloworld根文件系统只需init可执行文件、/dev目录及该目录下的console设备节点。

编译linux内核使之支持initramfs,此处为了测试,内核关闭看门狗,以免不能喂狗造成系统复位。在General setup下打开支持initramfs以及相应的根文件系统目录路径。

Linux开发五_构建根文件系统

图2-1 initramfs编译进linux内核

编译内核,最后在内核源码树/usr目录下有一个initramfs_data.cpio档案即为initramfs,initramfs可以直接编译进内核,当独立于内核时,由bootloader进行加载进ram。这里initramfs编译进内核,bootloader只需加载linux内核并启动即可。此处把编译生成的linux内核zImage复制到sd卡的/image目录下并命名为kernel.bin,由bootloader从sd卡加载内核启动。

Linux开发五_构建根文件系统

图2-2 bootloader从sd卡启动linux内核

3. Busybox构建根文件系统

3.1. Busybox概述

对于linux系统来说,用户空间往往需要很多常用的linux命令、工具等来跟linux内核进行交互。这些命令集可以自行实现、也可以下载相应的命令源码进行移植,除此之外,还有一些开源的工具已经打包实现了linux常用的命令集,如busybox、embutils等。其中busybox是常用的一个工具,它能够以一个极小的应用程序来提供整个命令集的功能,而且需要哪些命令都是可以配置的,这非常适合于嵌入式系统的应用。

3.2. Busybox配置编译

busybox可以根据功能需求进行裁剪,此处避免讨论使用动态库,使用静态编译,使用交叉编译工具,对于s3c2416,要求交叉编译工具编译armv5指令集,软浮点等,不是默认需指定CFLAGS。

Linux开发五_构建根文件系统

图3-1 busybox配置

编译busybox后,在源码目录_install有linuxrc链接文件以及命令集文件夹,/bin和/sbin,其中linuxrc链接到/bin/busybox,/bin和/sbin所有命令均是链接到/bin/busybox。

3.3. Busybox根文件系统

创建busybox目录作为根文件系统目录,把_install上的/bin、/sbin、以及linuxrc复制到busybox目录下,由于initramfs执行第一个用户程序为init,此处把linuxrc重命名为init即可。

busybox的一些命令需要一些目录、配置文件、设备等的支持。因此,基于busybox的根文件系统还需创建一些目录及文件。

此处以busybox源码目录examples/bootfloppy/etc为例说明/etc目录及其文件内容。busybox启动后,首先会解析/etc/inittab的内容,根据这个配置文件,进行相应的运行动作。

::sysinit:/etc/init.d/rcS

::respawn:-/bin/sh

::askfirst:-/bin/sh

::ctrlaltdel:/bin/umount -a -r

::restart:/sbin/init

sysinit表明系统启动后最先执行/etc/init.d/rcS启动脚本,最后启动/bin/sh子进程。/etc/init.d/rcS内容如下

#! /bin/sh

/bin/mount –a

脚本尝试挂载/etc/fstab列出的所有文件系统,因此需要/etc/fstab文件,其内容如下

proc           /proc    proc     defaults    0   0

可知尝试挂载proc文件系统到/proc目录,因此对于这个busybox自带的/etc配置例程,根文件系统目录下需/proc目录,用mkdir /proc即可创建该目录。

在例程/etc目录下,还有一个profile文件,该文件用于配置每个用户登录系统后的环境变量。其内容如下

echo -n "Processing /etc/profile... "

PATH=/sbin:/bin

runlevel=S

prevlevel=N

umask 022

export PATH runlevel prevlevel

echo

busybox需要使用控制台等设备文件,因此还需要/dev目录以及该目录下简单的设备节点,在/dev目录下创建console、null这两个设备节点即可

mknod /dev/console c 5 1

mknod /dev/null c 1 3

至此基于busybox例程的配置修改完成,这是根据例程所实现较简单的目录及其配置,一般根据需要使用则需存在,不需使用则无需存在的原则,可以根据根文件系统的功能,进行更复杂的配置。

3.4. Busybox测试

在内核中修改initramfs的目录路径为/root/rootfs/busybox,进行编译内核,把生成的内核拷贝到sd卡/image目录并重命名为kernel.bin,由bootloader从sd卡加载启动linux内核。

Linux开发五_构建根文件系统

图3-2 基于busybox的linux内核启动

测试之前的Hello world程序,./helloworld,用ctrl+c终止进程

Linux开发五_构建根文件系统

图3-3 测试Hello world子进程

用vi编辑生成文本文件,mkdir创建文件夹等,成功后,当前的文件系统有相应的操作改变,但系统重启后,基于ram文件系统的initramfs又回到之前的内容。

4. 附录

对于嵌入式系统来说,基于linux进行构建整个系统,往往是因为linux下驱动完善,有各种优秀的开源项目,网络等各种功能支持完备,从一定程序上减少了相当的开发工作。此时的linux系统往往尽量精简,只需达到相应的项目需求即可,采用initramfs来精简文件系统无疑是一种不错的方法,可以实现linux系统的秒启动。

附录为arm交叉编译工具链下基于newlib的s3c2416 linux启动 bootloader工程,本章所述的根文件系统,bootloader从sd卡加载内核启动,工程直接make即可。

http://pan.baidu.com/s/1c2Fz7tI

mdk下s3c2416 linux启动bootloader工程。

http://pan.baidu.com/s/1hs1Kl16

本章所述的根文件系统

http://pan.baidu.com/s/1eSMhdOA