根文件系统构建和实验过程


一、一、根文件系统构建路线linux

一、先逐步构建文件夹形式的根文件系统而后在制做烧录镜像shell



二、一、busybox移植实战windows

一、busybox中是一些shell命令集bash

二、busybox×××服务器

(1)busybox是一个开源代码,能够在网上下载架构

(2)busybox的版本新旧无所谓,随便下载一个,busybox安装在咱们建立的那个根文件系统文件夹形式的目录下,先将文件解压到一个本身建立的文件夹下ide

(3)busybox的玩法和Linux内核的玩法很像,都是须要配置的函数


三、makefile的修改工具

(1)ARCH = armoop

(2)CROSS_COMPINE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-


四、make menuconfig进行配置

(1)配置参考老师提供的文档


五、而后make,而后make install

(1)make 编译,若是有错误,第一种方法就是去看哪一个地方出错了,进行源代码的修改。可是通常状况下,出错的地方的那个应该实现的功能多是咱们不想要的,通常出错是因为咱们的arm-gcc交叉编译工具链和咱们的这个busybox中的makefile不兼容致使的,因此咱们第二种方法就是让他不编译那个出错的文件,用find -name “xxx”来查找这个文件在地方。发现这个文件所在的目录后,看这个目录下有没有makefile,若是有在makefile中将这个文件不添加编译就行,若是没有,就看有没有kbuid这个文件,也能够在这个文件中将那个文件不进行编译,怎么作呢,就是在对应的makefile或者kbuid中找到这个文件所对应的那个CONFIG宏,完了以后再make menuconfig中将这个宏对应的东西配置成没有就行了,若是没有这个宏,那么就直接用出错的那个文件的名字找就好了,找到后给它去掉,未来make的时候就不会编译这个文件了,在次进行make 编译后,编译出来了busybox这个东西,就在证实编译经过了

(2)make install 执行的时候就是执行busybox顶层目录的一个目标install,就是在执行这个目标

(3)make install 在全部的Linux下的软件中,这个目标的一个做用就是安装软件,源代码安装,安装的做用就是将编译生成的可执行程序及其依赖的库文件和配置文件头文件等这些有用的东西安装到咱们当前系统中咱们指定的目录下,通常都是能够本身指定安装到哪一个目录下,若是不指定通常都有个默认目录下,默认的目录不一样软件是不样的,因此咱们通常是本身去指定,在make menuconfig的Busybox Settings--->中有一个install的默认安装地方,能够看出来默认是安装在哪里的,也能够在这里进行修改,咱们要安装到咱们的那个根文件系统文件夹下


二、二、inittab详解

一、一个配置文件,在根文件系统的文件夹下,建立一个etc文件夹,将inittab放到这里,在次启动内核用nfs挂载这个根文件系统就成功了,最小的根文件系统


二、inittab格式详解

(1)这个inittab的工做原理被/linuxrc(也就是busybox)执行时调用起做用

(2)inittab在/etc目录下,因此是一个运行时的配置文件,是文本格式的(内容是由不少字符构成的,按照必定格式组织的),实际工做的时候busybox会按照必定的格式去解析这个inittab文件,这个格式是由busybox决定的,在busybox的代码中能够体现,而后根据解析的内容来决定怎么工做

(3)busybox究竟如何完成解析,而且解析的结果如何去工做(busybox中,实现/etc/inittab的原理并非咱们的目标,这些是写busybox的人须要知道的),咱们的重点是要知道inittab的格式是怎么样的,咱们看到一个inittab后怎么去分析inittab对启动的影响,明白inittab这样写是什么意思

(4)inittab的格式在busybox中定义的。网上能够找到。

(5)#是行注释

(6):冒号在里面是分隔符,分隔开各个部分

(7)inittab是以行为单位的,行和行之间没有关联,每行是一个配置项,每个配置项表示已个独立的含义

(8)每一行的配置项都是由三个冒号分隔开的四个配置值共同肯定的,这四个配置值是id:runlevels:action:process

可是有些配置值能够空缺,可是空缺了冒号是不能丢的。因此有时会看到连续的冒号

(9)每一行的配置项中,四个配置值,最重要的就是action和process,action是一种状态,process是一个可被执行的程序pathname,合起来的意思就是,当知足action的条件时,就会执行process的程序,这个在busybox的源代码中能够分析出来,由于busybox最后是进入到了一个死循环中,在这个死循环中,busybox不断的去检查action知足的条件,知足一个就去执行一个对应的process进程。因此咱们的这个busybox进程1(也就是linuxrc,也就是init)最后始终在死循环中,不断的检查者个inittab文件中的action是否条件成立,若是成立执行一个对应的pricess,因此在整个操做系统运行起来的过程当中,这个inittab是一直在被用的

(10)明白各个action是什么意思

::sysinit:/etc/init.d/rcS  这个action是sysinit,意思是当控制台启动以前执行后面的process,其余的action是什么含义在网上搜busybox inittab就能够知道了


二、三、busybox源码的分析1

一、进行解压

二、整理目录

三、创建SI工程

四、整个程序的入口确认

(1)在uboot中和内核中,由于操做系统尚未运做起来,咱们程序的入口要看连接脚本中指定的入口是哪里

(2)可是咱们busybox程序是一个Linux内核启动起来后运行的,这个busybox未来是安装到根文件系统中的,因此这个busybox是一个应用程序,因此对于应用程序而言,对于操做系统运行起来的状况下,咱们的程序入口就应该是main函数。

咱们程序入口是在Appletlib.c中的main函数中,当咱们在命令行下输入一个命令的时候,这个命令就做为这个函数的argv[0]了,经过这个argv来找到对应的那个xxx_main函数去运行执行这个命令,在返回到这个mian函数中,在次去看argv,因此busybox就是靠这种方法,来实现一个程序能够当作不少命令的程序的



二、四、busybox源码的分析2

一、inittab解析与执行

(1)inittab解析是在busybox中的init.c中的init_main中,启动的时候执行的真正的函数

二、pwd命令执行路径分析

三、busybox体积优点管理



二、五、rcS文件介绍

一、/etc/init.d/rcS这个文件是一个配置文件,是咱们Linux运行中最重要的一个配置文件,这个文件是在busybox调用/etc/inittab这个配置文件时,被运行的。在后面的其余的配置文件,都是由这个文件引出来的,这个文件能够复杂也能够简单的,里面有不少配置项

二、PATH=XXX

(1)PATH这个环境变量是Linux系统内部定义的一个环境变量,含义是操做系统在执行一个程序时会默认的奥PATH指定的各个目录下去寻找,若是找不到就认定这个程序不存在,若是找到了就去执行他,将一个可执行程序的目录导出到PATH,可让咱们不带路径的去执行这个程序。

(2)因此我在作根文件系统的时候,咱们的/etc/init.d/rcS这个配置文件中的PATH做用就是,让咱们在执行那些命令集的时候也就是执行那些应用程序的时候,能够不用指定路径,达到咱们Ubuntu中的那个效果。

(3)但是咱们当前的状况是,咱们并无将这个文件添加到咱们/etc/init.d目录下,咱们没有这个文件,可是内核挂载了这个根文件系统后,再命令行下,咱们直接ls也是好使的,而不用加上路径去执行这个程序?也就是说为何咱们的rcS文件尚未添加,咱们系统就有了PATH中的值?由于在busybox的源码中,busybox用硬编码的方式导出了一些环境变量,其中就有PATH,而且有个默认值

三、runlevel=S

(1)runlevel和运行阶段有关,就是从系统启动到启动完毕的几个阶段,=S表示将系统设置为单用户模式

四、prevlevel=N

五、umask 022

(1)umask是Linux的一个命令,做用是设置Linux系统的umask值

(2)umask的值决定当前用户在建立文件时的文件的默认的权限

六、mount -a

(1)mount命令是用来挂载文件系统的,mount -a的意思是挂载全部的应该挂载的文件系统,在busybox中mount -a时会去查找一个文件/etc/fstab、并执行这个文件,这个文件中按照必定的格式列出了应该被挂载的文件系统(包括了虚拟文件系统),因此想要mount -a工做,就必需要有fstab这个文件来配合


七、目前为止的根文件系统制做实战


(1)在以前的咱们的根文件系统文件夹下的,按照咱们的inittab中的第一步要执行的东西,咱们知道要在etc目录下中建立一个init.d文件夹,将rcS这个配置文件放到里面,由于rcS中用到mount -a要挂载fstab中列出的全部文件系统包括虚拟文件系统,因此须要用到fstab这个配置文件。因此咱们将fstab这个配置文件在放到/etc目录下,以后去启动内核nfs挂载这个根文件系统文件夹,发现仍是说这个rcS不存在,是由于rcS这个脚本文件中的内容是在windows中编写的,回车有差别,改下便可。能够说明若是在shell脚本中,若是内容格式不对,运行时会被认为文件不存在


(2)有时一个应用程序在执行的时候也会提示文件不存在,多是由于这个应用程序所调用的一个动态连接库找不到


(3)PATH和runlevel的测试


由于在busybox源码中,PATH默认的值就给出来了,是/sbin:/bin:/usr/sbin:/usr/bin,因此咱们在rcS中不加这个PATH的时候,在命令行下,也是能看到PATH被赋值了的,因此咱们能够不用设置这个值。

runlevel这个是运行级别,就是咱们inittab配置文件中的每个配置项对应的那个id:runlevel:action:process中的那个runlevel级别,可是在busybox中是不支持的,之后若是想更加详细的去理解,能够去网上搜索学习


(4)umask

umask是设置咱们当前用户下建立文件时该文件的文件权限的,通过测试,知道

当咱们将umask的值设置成022时,咱们建立文件后,文件拥有的权限是644,

当咱们将umask的值设置成044时,建立一个文件的时候,文件的权限是622

当咱们将umask的值设置成444时,建立一个文件的时候,文件的权限是222


因此能够看出来umask的值含义就是0对应文件权限6就是可读可写,2对应的文件权限是4也就是可读,4对应的文件权限是2,也就是可写,加起来是666.


(5)mount测试

当前挂载的时候所有出错

缘由是咱们当前的根文件系统中找不到挂载点,挂载点就是咱们要将目标文件系统(固然这里是虚拟文件系统)挂载到当前文件系统的某一个目录中,这个目录就是挂载点

解决方案就是,本身在制做的根文件系统的根目录下,建立挂载点目录就行

验证是否挂载是否成功,能够看咱们挂载时的一个输出信息,没有报错就挂载成功了,还能够在启动后,去看咱们的proc和sys文件夹,若是在Ubuntu中看里面没有东西,在咱们开发板中的这些文件能看到东西,就说明挂载成功了


八、mdev -s

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

(1)medv是udev的嵌入式简化版本,udev/mdev是用来配合Linux驱动工做的一个应用层的软件,mdev/udev的做用就是配合Linux驱动生成相应的设备文件,/dev目录下

(2)在rcS文件中,没有启动mdev的时候,咱们的/dev目录下启动后是没有东西的,在rcS文件中添加上mdev相关的两行内容后,在次启动系统,发现咱们的/dev目录下有内容了,全是设备驱动文件。

(3)/dev目录下的设备驱动文件,就是mdev生成的,这就是mdev的意义


九、hostname

(1)hostname是Linux中的一个命令,这个命令执行后(hostname xxx)能够用来设置当前系统的主机名,直接hostname能够显示当前系统的主机名

(2)/bin/hostname -F /etc/sysconfig/HOSTNAME 

/bin/hostname 执行了这个程序,-F指定了一个主机名的配置文件(这个文件的通常文件名叫hostname或者大写的HOSTNAME)。

(3)使用方法就是在根文件系统中,将关于hostname的这一行内容添加到rcS中,在根文件系统的/etc目录下建立一个sysconfig文件夹,在这个文件夹下建立一个HOSTNAME文件,在这个文件中写入咱们想要的主机名字就好了。


十、ifconfig

(1)有时咱们但愿看机后,进入命令行时,咱们的IP地址就有一个指定的IP地址,这时咱们就能够在rcS文件中ifconfig eth0 一个IP地址



十一、profile文件和用户登陆理论

(1)以前咱们在HOSTNAME中输入了咱们的主机名字,但是咱们的命令下仍是没有变,因此把这个profile配置文件添加到etc目录下就能够解决这个问题了。

(2)添加这个profile文件后,发如今命令行下咱们的主机名字能显示出来了,可是咱们用户名尚未,因此只有咱们添加用户登陆功能之后,这个用户名才能显示出来,就达到了咱们Ubuntu中的效果了,好比root用户,就是root@Ubuntu

(3)profile的工做原理:也是被init进程调用执行的,因此是认名字的,profile这几个字不能写错。本身去网上搜吧


十二、如何看到用户登陆界面

(1)由于以前的inittab中有一个配置项::askfirst:-/bin/sh,做用是当咱们系统启动后,就去执行/bin/sh,执行这个后当咱们按下回车后就会进入命令行,所以咱们这样安排的话。就不会出现用户登陆界面,会直接进入命令行

(2)咱们要出现登陆界面,就不能执行这个/bin/sh程序,而应该执行一个负责负责出现登陆界面而且能管理用户名和密码的一个程序,busybox中集成了一个这样的程序,这个程序就是/bin/login或者/sbin/getty,这两个都行。


1三、用户名和密码的设置

(1)用户名和密码的设置确定是和咱们的登陆程序有关的,是在登陆程序中写死的,可是全部的Linux的用户名和密码的管理几乎都是同样的

(2)密码通常都是加密的文字,意思就是系统中的密码确定是在系统的一个专门用来存放密码的文件中存储的,不是明文,否则你得系统被攻破了之后,别人就能够直接知道你的密码。


1四、用户登陆的实战

(1)将inttab配置文件中的askfirst这个action注释掉,添加一个sysinit action对应process是/bin/login、

(2)重启系统后,能够进入到登陆界面,咱们当前用的是单用户模式,因此只能是root用户登陆,可是咱们的密码怎么输都不对

(3)由于咱们根本就没有给root用户设置密码,因此固然不对了

(4)添加psswd和shadow文件,Linux系统中用来描述用户名和密码的文件是psswd和shadow文件,这两个文件都要在etc目录下,shadow文件中存储的是密文的密码,psswd中存储的是用户密码的设置

(5)咱们直接复制Ubuntu中的/etc/psswd 和 /etc/shadow这两个文件到咱们的根文件系统的etc目录下就行,在进行相应的修改就行,好比在psswd文件中留下咱们用的用户root,将root用户登陆后对应的目录建立或者本身修改,将登陆root用户后执行的脚本改为/bin/sh,由于busybox中不支持bash只支持sh默认。

(6)咱们能够先将root用户对应的shadow那段密码的位置,弄成没有,完了以后启动系统,咱们直接输入root就能够进入root用户了,默认是无密码的,我能够经过psswd root给这个root用户设置密码、

(7)有时若是咱们忘记了操做系统的密码,咱们怎么办呢,解决方法就是咱们在启动这个操做系统的时候进入到uboot界面bootloader界面,告诉内核咱们的根文件系统是nfs的,以后拿一根网线和咱们另外一台电脑上,用这台电脑登陆一个相似于Ubuntu的系统,在这个系统上搭建nfs服务器,建立对应根文件系统的文件夹,咱们把启动忘记密码的那操做系统后,就会挂载到咱们的这个Ubuntu根文件系统文件夹下,咱们在这个文件夹下找到那个加密的文件,将用户对应的密码设置成空,在重启系统就行了。

(8)id号的提示,提示串口的id号,能够在inittab中,将对应的id号添加上就行了。咱们用的是串口,在/dev目录下找到那个串口2的名字写到inittab中,咱们添加的那个action是sysinit,proess是/bin/login上的id中


1五、getty的作法和login的作法是同样的,二者应该在busybox中没有区别


一、1六、动态连接库的拷贝

一、静态连接hellowrod程序并执行

(1)咱们在Ubuntu中写一个C语言程序,写完后若是咱们是用gcc编译的话,就不能再咱们的arm平台上运行,由于个人Ubuntu是80386架构的,因此咱们要用arm-linux-gcc去交叉编译成能够在arm平台上运行的可执行程序


(2)咱们先静态编译连接这个helloword程序,也就是用 arm-linux-gcc hello.c -o hello_static -static 这样去静态编译连接

(3)实验结果是,咱们静态编译生成的hello_static能够成功的运行在咱们的系统上,


二、动态连接并执行

(1)动态连接:

arm-linux-gcc hello.c -o hello_dynamic


(2)若是不加动态连接库的话,是不能运行在咱们开发板系统上的。


(3)动态连接的hello中,当在咱们的开发板的系统上运行时,执行那个printf函数时找不到当前运行时环境对应的动态连接库,也就是说,在根文件系统中找不到lib中对应的动态连接库文件,由于动态连接的程序,是在程序运行的时候,将调用的函数在动态连接库中找到那个代码段,进行加载运行的。因此咱们的rootfs中没有动态连接,在执行动态连接的程序的时候就会找到不相应的代码段,就会出错


(4)因此咱们应该将arm-linux-gcc的动态连接库文件复制到根文件系统目录下的/lib目录下,添加动态连接库就行了


(5)arm-linux-gcc这个交叉编译工具对应的动态连接库,就在咱们安装这个交叉编译工具链时所在的某个目录下,个人是在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib中,因此复制这个目录中的东西到咱们的根文件系统的/lib中,其余一些的交叉编译工具对应的动态连接库可能不在这个目录下,咱们能够用find -name “*libm.so*”去找。


(6)复制的时候,参数要加上 -rdf 目的是为了让符号连接复制过来后仍是符号连接。

复制方法是用 cp xxx/*so* xxx/ -rdf  用*so* 来把不是动态连接库的东西过滤出去


(7)复制过来后,由于这些动态连接库文件中包含了一些调试用的符号信息,占空间,因此能够用arm-linux-strip *so* 用这个strip工具,将调试符号信息去掉,就省了一些空间了


二、六、开机自启动与主流的rcS格式是什么样的

一、开机自动启动这里的意思是说,在开发板上的操做系统起来之后可让一些应用程序自动执行。

(1)实现方法就是在rcS脚本中,加上想要开机直接执行的应用程序就行。由于根文件系统挂载后,会执行init进程1,这个进程就是/linuxrc,就是busybox,他先执行inittab,inittab中先执行了rcS,因此这个rcS中的内容会先被执行,能够在这里进行添加


二、前台运行和后台运行


(1)前台运行:程序运行占用了当前的控制台,因此这个程序叫作前台运行的程序。程序不结束会不到控制台。好比咱们写一个hello.c让这个程序一直在执行,回不到控制台的命令行下,那么这个程序就是前台运行,默认执行程序的时候就是前台运行的。


(2)后台运行:后台运行就是让这个程序运行,而且让这个程序让出控制台,这时候这个程序还能运行,而且还能不影响当前控制台的使用。在执行一个程序的时候在后面加上&符号就行,如 ./xxx &.



总结:根文件系统制做的流程和原理分析


(1)咱们的内核在启动后最后要去挂载根文件系统,执行根文件系统下的linuxrc这个程序,也就是init进程,也就是进程1,执行这个进程为了从内核态进入到用户态,这时才代表操做系统真正的运行起来了


(2)先经过nfs的文件夹形式的根文件系统调试好,搭建主机端的nfs服务器,配置开发板内核支持nfs协议。bootargs传参告诉内核是nfs的根文件系统。


(3)咱们linuxrc程序实际上是busybox这个程序,咱们在网上下载这个busybox程序,任意版本就行,由于咱们busybox这个程序未来是要在咱们的开发板上运行的,因此编译这个程序的时候必须用arm的交叉编译工具链,因此咱们将这个程序下载下来后要看makefile中CROSS_COMPINE这个环境变量的值是否是咱们交叉编译工具链所在的位置,ARCH架构是否是arm,以后再参考老师的提供的文档用make menuconfig对busybox进行配置,有错误的话,进行排查,配置的时候要安装路径也配置好,编译好后安装到咱们的根文件系统文件夹下,主机端建立的文件夹,这个位置是nfs通讯的那个文件夹。


(4)安装好后,这个时候根文件系统就有linuxrc这个程序了,开发板系统启动时执行了这个程序,可是由于busybox要调用/etc下的inittab这配置文件,因此咱们要在etc目录下添加一个这个inittab配置文件,这个配置文件应该很好懂,看了就知道,不知道能够去百度。


(5)添加了inittab配置文件后,在启动的时候说找不到/etc/init.d目录下的rcS程序,由于inittab这个配置文件中,第一个配置项就是执行这个rcS程序,因此在etc目录下建立init.d目录,而且将rcS配置文件添加进来,咱们打开rcS能够发现这里面有一系列内容,由于要mount -a挂载全部文件系统,因此须要在etc目录下添加一个fstab这个配置文件,由于这个配置文件中有不少挂载点,因此要在根文件系统根目录下建立这些挂载点,由于rcS中涉及到主机名,看内容知道主机名被指定在/bin/hostname -F /etc/sysconfig/HOSTNAME中,因此要在etc目录下建立sysconfig目录建立HOSTNAME文件,这个文件中的内容就是咱们的主机名,我写的是why210,想让这个主机名生效,在咱们命令行下显示出来就须要profile这个配置文件的配合,因此还要在etc目录下添加这个profile配置文件,这个时候在启动就能够在命令行下看到主机名了。


(6)为了实现用户登陆还有密码,由于这个用户登陆和密码在busybox中是支持的,因此busybox中的程序就有这个的实现,因此咱们为了让用户登陆在命令行出现以前就出现,咱们就要在inittab配置文件,在命令行出来以前添加这个用户登陆的执行程序,因此添加了一个action和process,用户登陆很密码须要两个文件的配合,能够在Ubuntu中将/etc下的passwd和shadow复制到咱们的根文件系统etc目录下,一个中告诉了用户登陆后的目录,一个中记录了密文密码。在这两个文件的配合下,咱们的用户登陆就能够实现了。可是提示这个须要有id号,因此将咱们使用的串口id号添加到对应的这个inittab中的配置项的id中。

(7)为了实现动态连接的程序能够在开发板上运行,须要将arm-linux-gcc对应的动态连接库文件拷贝到咱们的根文件系统下的lib目录中。以支持交叉编译的动态连接库。

(8)以后就能够制做成可烧录的镜像了,步骤以下


dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240

losetup  /dev/loop1 rootfs.ext2

mke2fs -m 0 /dev/loop1 10240

mount -t ext2 /dev/loop1 ./ext2_rootfs/


复制咱们的根文件系统文件夹形式的内容到ext2_roofs文件中,这样就能够放在roofs.ext2镜像中了


umount /dev/loop1

losetup -d /dev/loop1

相关文章
相关标签/搜索