手动构建rootfs及文件功能分析

来源:互联网 发布:mac照片图库怎么导出 编辑:程序博客网 时间:2024/05/22 14:35

转载地址:http://blog.csdn.net/qq_28992301/article/details/52127009

这份笔记记录了从0开始构建一个最小根文件系统的流程,从而达到分析其目录结构及文件的目的,基于的kernel版本为2.6.35

1.结构总览

如图

  • /linuxrc:由busybox安装,就是kernel执行的init程序,本质是指向busybox的符号链接
  • /bin:由busybox安装,里面是通用命令,如ls
  • /sbin:由busybox安装,里面是root权限命令,如shutdown
  • /usr:由busybox安装,里面是共享、开放的内容(意思是任意用户都可以使用)
  • bin:由busybox安装,里面是共享、开放的命令,如whoami
  • sbin:由busybox安装,里面是不重要的系统命令,如deluser
  • /etc:里面是各个程序的配置文件,众多程序在运行时需要根据配置文件来指导它们的行为

    • inittab:busybox的配置文件,busybox运行时将根据/etc/inittab来指导自己的行为,可以用它实现应用程序的开机自启动,此外它还调用了rcS
    • fstab:配置文件,被busybox的mount -a 指令读取,指定了系统初始化时应该挂载的文件系统
    • profile:一个脚本程序,被busybox调用,作用是在控制台中显示用户的名字
    • passwd:配置文件,里面记录了用户和密码的设置
    • shadow:配置文件,里面是所有用户的密码(加密过的)
    • init.d:此目录包含了很多系统服务启动时需要运行的脚本
      • rcS:控制台初始化程序,在进入控制台前被busybox调用执行,可以利用它实现应用程序的开机自启动
  • sysconfig:

    • HOSTNAME:配置文件,里面存放用户的名字,会被rcs读取
  • /proc:系统的虚拟文件系统的挂载点,要自己创建,里面是虚拟的文件,表示了系统的一部分状态

  • /sys:系统的虚拟文件系统的挂载点,要自己创建,里面是虚拟的文件,非常全面的表示了系统状态
  • /tmp:系统的虚拟文件系统的挂载点,要自己创建,用于存放临时生成的文件,一般是空的
  • /var:系统的虚拟文件系统的挂载点,要自己创建,用于存放一些数据
  • /dev:系统的虚拟文件系统的挂载点,要自己创建,用于存放设备文件
  • /lib:里面存放了很多库文件,应用程序会进去加载需要的动态链接库

2.安装busybox

可以从官网https://busybox.net/downloads/ 下载到源码,我们使用2015年的1.24.1版本。busybox这个项目借鉴了很多kernel的地方,比如配置部分和Makefile等,我们只要按照kernel的方法操作它就行了

  • 进入源码目录,打开Makefile检查架构和交叉编译工具链,利用/在vim中搜索CROSS_COMPILE和ARCH,将其改为
ARCH = armCROSS_COMPILE = /usr/local/arm/arm-2009q3/bin//arm-none-linux-gnueabi-
  • 1
  • 2
  • 然后直接make menuconfig,开始配置busybox。首先进入Busybox Settings->Build Options 配置使用静态链接库,因为我们要移植到开发板所以不要使用动态链接库
    这里写图片描述
    再进入Busybox Settings->Busybox Library Tuning,设置为vi风格
    这里写图片描述
    进入Linux Module Utilities,设置模块化,注意要取消 Simplified modutils,然后选择下面的子选项
    这里写图片描述
    进入Linux System Utilities,确认mdev下面的子选项都被选中了
    这里写图片描述
    进入 Busybox Settings->Installation Options (“make install” behavior),修改busybox的安装路径
    这里写图片描述
  • 配置完了直接编译,make -j4,发现报错了:
    这里写图片描述
    看来是sync.c报错了,google一下,发现这个sync功能并不是什么特别有用的,我们直接在menu config中将其屏蔽即可。然后再编译,发现没有报错
  • 然后输入 make install 来安装busybox,这一步主要的目的是把编译生成的一大坨可执行文件、和依赖的库文件,妥当的安装到我们指定的目录下(即根文件系统目录)

3.添加/etc/inittab

/etc目录里面是各个程序的配置文件,众多程序在运行时需要根据配置文件来指导它们的行为
此处的/etc/inittab就是busybox的配置文件之一,busybox运行时将根据/etc/inittab来指导自己的行为。如果我们要添加自己的自启应用程序,并不推荐inittab,推荐rc*.d,详见第5节。

  • 首先手动创建/etc目录,然后在里面创建/etc/inittab文件,并向其内部添加:
#sjh:这是一个典型的inittab内容#first:run the system script file::sysinit:/etc/init.d/rcS::sysinit:/bin/login::askfirst:-/bin/sh::ctrlaltdel:-/sbin/reboot#umount all filesystem::shutdown:/bin/umount -a -r#restart init process::restart:/sbin/init
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • inittab文件内容是严格按照一定的格式的,非#开头的就是正式语句了,每一行都是一个配置项
  • 配置项的标准格式为,id:runlevels:action:process 其中,冒号代表分隔符,分隔开各个部分;id和runlevels不是很重要,一般能省略,这就是为什么上面这段代码行首有两个冒号的原因;action代表一个条件/状态;process代表操作
  • ::sysinit:/etc/init.d/rcS的意思是:当条件状态为“访问控制台前的初始化”时,执行“/etc/init.d/rcS”
  • ::sysinit:/bin/login的意思是:当条件状态为“访问控制台前的初始化”时,执行“/bin/login”即启动用户登录程序
  • ::askfirst:-/bin/sh的意思是:当条件状态为“启动程序前(不太理解?)”是,执行“-/bin/sh”
  • ::ctrlaltdel:-/sbin/reboot的意思是:当条件状态为“重启”时,执行“-/sbin/reboot”
  • ::shutdown:/bin/umount -a -r的意思是:当条件状态为“关机”时,执行“/bin/umount -a -r”(意思是取消挂载的目录)
  • ::restart:/sbin/init的意思是:当条件状态为“重启init(busybox)”时,执行“/sbin/init”(init其实就是busybox)
  • 总之,busybox在运行时会不断的循环判断,一旦当前符合条件状态了inittab中的某一个配置项,它就会执行相应的操作。可见,inittab文件对于busybox相当重要

4.添加/etc/init.d/rcS

/etc/init.d/rcS是被busybox调用的控制台初始化程序,这个文件是一个shell脚本,在开机访问控制台前它将被busybox执行,可以认为rcS是一个开机就执行的初始化程序
如果我们要添加自己的自启应用程序,并不推荐rcS,推荐rc*.d,详见第5节

  • 首先手动创建/etc/init.d/,然后在里面创建rcS,并向其内部添加
#!/bin/shPATH=/sbin:/bin:/usr/sbin:/usr/binrunlevel=Sprevlevel=Numask 022export PATH runlevel prevlevelmount -aecho /sbin/mdev > /proc/sys/kernel/hotplugmdev -s/bin/hostname -F /etc/sysconfig/HOSTNAMEifconfig eth0 192.168.1.3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 首先一上来定义了三个变量PATH、runlevel、prevlevel,并将其导出为环境变量
  • PATH这个环境变量代表应用程序的默认路径,当我们执行应用程序(如 ls)时可以不输入路径,busybox会去这个路径内搜索。PATH=/sbin:/bin:/usr/sbin:/usr/bin表示将应用程序默认路径设置为/sbin、/bin、/usr/sbin、/usr/bin,冒号为分隔符
  • runlevel这个环境变量表示Linux系统的运行级别(模式)设置,比如0代表关机,1代表单用户root模式,2代表多用户模式,我们这里设置的S代表的也是单用户root模式
  • prevlevel这个环境变量不是很重要
  • umask 022表示设置umask值为022,umask决定了用户创建新文件时,新文件的权限,一般来说默认的022够用了
  • mount -a表示挂载指定的文件系统,具体由/etc/fstab(见后文)指定
  • echo /sbin/mdev > /proc/sys/kernel/hotplug表示创建符号链接mdev,指向hotplug,这一步的根本目的是实现热插拔设备功能,其实就是当驱动模块被加载时,自动生成/dev下的设备文件
  • mdev -s,表示开启扫描驱动设备模块,如果扫描到了就自动生成/dev下的设备文件。这一步和上一步其实就是开启mdev的“自动创建设备文件功能
  • /bin/hostname -F /etc/sysconfig/HOSTNAME表示执行了hostname程序,把当前主机的名字设置为HOSTNAME(见后文)文件中的主机名,-F是参数,表示去文件中获取主机名
  • ifconfig eth0 192.168.1.3表示设置ip地址

5.添加/etc/rc*.d目录(可选)

这是一种当前非常流行的开机启动设置方式,/etc/rc*.d中的脚本将被开机启动。rc*.d中的*代表了了启动优先级

  • 如果文件系统中有这类目录,那么我们应该按照这个方法设置开机启动程序。如果本来就没有,那么也没必要强行添加,也能在/etc/inittab/etc/init.d/rcS设置开机启动
  • 关于添加开机启动的注意点:
    • 能后台运行尽量后台运行,前台运行会占用控制台,如果需要后台运行,则只需在指令后面加&即可,如/test/hello_static &
    • 开机启动的程序中,应该使用全路径,因为只有登录后,当前目录才会进入~/,而开机启动的程序有可能在登录前运行(也有可能根本不登录),所以使用全路径比较保险

6.添加/etc/fstab

该文件指定了系统初始化时应该挂载的文件系统,
首先手动创建/etc/fstab,并向其内部添加:

#   <file system>   <mount point>   <type>  <options>   <dump>  <pass>    proc            /proc           proc    defaults    0       0    sysfs           /sys            sysfs   defaults    0       0    tmpfs           /var            tmpfs   defaults    0       0    tmpfs           /tmp            tmpfs   defaults    0       0    tmpfs           /dev            tmpfs   defaults    0       0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 上面几栏分别代表要挂载的设备、挂载的地点(目录)、按什么类型挂载、选项
  • 其实这些都是虚拟文件系统,具体和驱动有关

7.添加/etc/sysconfig/HOSTNAME和/etc/profile

  • /etc/sysconfig/HOSTNAME是系统初始化程序rcS读取的一个配置文件,里面是用户的名字
  • /etc/profile是一个脚本程序,被busybox调用,它可以在控制台中显示用户的名字,如图:
    这里写图片描述
  • 手动创建这两个文件,往HOSTNAME中写用户名,往profile中填充:
   # Ash profile   # vim: syntax=sh   # No core files by default   ulimit -S -c 0 > /dev/null 2>&1   USER="`id -un`"   LOGNAME=$USER   PS1='[\u@\h \W]\# '   PATH=$PATH   HOSTNAME=`/bin/hostname`   export USER LOGNAME PS1 PATH
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

8.添加/proc、/sys、/tmp、/var、/dev

这些目录都将作为系统的虚拟文件系统的挂载点,自己手动创建即可,busybox的mount -a 指令会根据/etc/fstab文件自动挂载虚拟文件系统到这些目录

  • /proc的作用是展示内核运行时的一些数据结构,它们将以文件的方式呈现在/proc中,开发者可以通过观察其中的文件来了解内核的运行信息。虚拟文件的内容都是动态创建的,它们并非完全是只读的,前面介绍的写/proc/sys/kernel/printk 可以改变 printk的打印级别
  • /sys的作用和/proc完全相同,它是/proc的升级版本,里面的虚拟文件基本都可以读写

9.(可选)添加/etc/passwd、/etc/shadow

这两个文件内部配置了用户和密码相关的设置,一般的嵌入式系统用不到这个功能。如果需要使用可以在网上搜索这两个文件的格式

10.添加/lib

在主机中交叉编译出来的应用程序若使用了静态链接库,则可以直接在开发板上跑。而使用了动态链接的则不行,因为执行时在需要开发板上加载库文件。所以在rootfs中添加动态链接库文件是必不可少的

  • 首先·要获取库文件,一般来说在交叉编译工具链中是有提供的。我们用的arm-2009q3工具链的动态链接库在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib目录下。其他的一些交叉编译工具链中动态链接库的目录不一定在这里,要去找一下。找的方法就是find
  • 复制动态链接库到roots/lib目录下。复制时要注意参数用-rdf,主要目的就是符号链接复制过来还是符号链接
  • (可选)当使用norflash,空间不足时,我们可以裁剪动态链接库中的调试符号信息。裁剪的方法是使用交叉编译工具链中的arm-none-linux-gnueabi-strip工具,我们在lib目录下输入arm-none-linux-gnueabi-strip *so*,把所有名字中的含有so的库文件都裁剪掉他们的调试符号信息。裁完发现lib文件夹大小由3.8mb缩为了3.0mb,而zImage一共也才3.5mb,可见裁掉的这些空间非常可观
原创粉丝点击