根文件系统的制作

根文件系统的启动流程

  1. 打开/dev/console,并执行sys_dup(0),sys_dup(0),即将标准输入输出错误重定位到console终端,而该console也是串口0的输出。
  2. run_init_process为跳转指令,只要执行了就不再返回。若用户指定了execute_command=xxx则执行run_init_process(execute_command),一般指定为linuxrc文件,若未指定或出错依次判断执行/sbin下的init程序、etc/init、/bin/init、/bin/sh文件,都没有则启动失败。
  3. 通过busybox构建init文件。
  4. 读取和解析init文件的配置文件,根据配置文件启动用户程序

BUSYBOS源码分析

busybox -> init_main
				parse_inittab
					fopen(INITTAB,"r");//打开etc/inittab配置文件
					new_init_action;//创建了多个init_action结构存入链表中
				run_actions;//根据时机执行链表中的程序

相关函数解析:
inittab的格式:<id> : <runlevels> : <action> : <process>
				id -> /dev/id ,用作终端:stdin,stdout,stderr:ptintf,scanf,err
				runlevels:忽略
				action:执行时机
				process:指定用户程序或脚本
				
new_init_action(action,process, id);
			创建一个init_action结构,填充
			把这个结构放入init_action_list链表

run_actions:执行一系列时机的用户程序
			run_actions(SYSINIT);
				waitfor(a,0);						//执行应用程序,等待他结束
					->run(a);								//创建子进程
					->waitpid(runpid, &status, 0);		//等待子进程结束
				delete_init_action(a);				//从init_action_list链表中删除
			run_actions(WAIT);
				waitfor(a,0);						//执行应用程序,等待他结束
					->run(a);								//创建子进程
					->waitpid(runpid, &status, 0);		//等待子进程结束
				delete_init_action(a);				//从init_action_list链表中删除
			run_actions(ONCE);
				run(a);								//创建子进程
				delete_init_action(a);				//从init_action_list链表中删除
			while(1){
				run_actions(RESPAWN);
					if(a->pid == 0){
						a->pid = run(a);
					}
				run_actions(ASKFIRST);
					if(a->pid == 0){
						a->pid = run(a); 			//打印:Please press Enter to activate this console,并等待回车,创建子进程
					}
				wpid = wait(NULL); 			//等待子进程退出
				while(wpid > 0){
					a->pid = 0;						//退出后设置pid=0
				}
			}

小结

构建最小根文件系统五要素:

  1. /dev/console /dev/null, null用于若未指定console则将标准输入输出错误定向到null中。
  2. init文件的构建—>busybox工具
  3. /etc/inittab 配置文件
  4. 配置文件中指定的程序
  5. C库,支持文件系统启动中的一系列文件操作等库函数。

BUSYBOX

  1. make menuconfig中配置指定编译工具,也可以在Makefile中修改
    Busybox Settings —>
    Build Options —>
    (arm-none-linux-gnueabi-) Cross Compiler prefix
    Build BusyBox as a static binary (no shared libs) //静态编译
  2. 在菜单中勾选上需要的支持系统命令,默认一般均配置好了
  3. make 编译
  4. make install 将编译后生成的文件安装到 _install目录下,也可以创建新目录,make CONFIG_PREFIX=/x/x install安装到指定目录中
  5. 生成bin linuxrc sbin usr 的子目录,已完成基本的linux系统常用命令与启动文件linuxrc
  6. 在_install目录下新建子目录:dev 、etc、mnt、proc、var、tmp、sys、root
  7. 将交叉工具链中的c库中的动态库的链接文件拷贝到_install目录下的lib目录。cp xxx/lib/* .so * . -d,-d表示拷贝链接文件,否则将拷贝原库文件,会非常大。
  8. 删除该lib目录下的静态库,.a后缀文件,或删除没用到的库,对其进行裁剪,一般尽量小于8M
  9. 将现成的文件系统中的/etc目录下配置文件和启动脚本拷贝到当前/etc下,也可以自行创建,第一个应用程序linuxrc会解析/etc目录下的配置文件和脚本,/etc下几个文件的分析:
    1. inittab: " ::sysinit:/etc/init.d/rcS " 指定启动运行的脚本文件
    2. init.d/rcS:mount挂载根文件系统的目录,创建ptc文件,即终端输入中的命令提示"[xxxx]:",支持热拔插,做一系列挂载文件系统后的初始化步骤。如果指定了mount -a 则依赖于fstab文件。
    3. fstab:指定要挂载的目录
    4. profile:指定提示符,指定环境变量(系统命令路径、库路径)
  10. 在/dev目录下创建console与null设备结点:mknod dev/console c 5 1,对应串口输出的设备结点,mknod dev/console c 1 3。

手动制作/etc目录下的配置文件

目录example下有各文件编写格式的说明

  1. 在/etc目录下创建inittab配置文件,写入:
    console::askfirst:-/bin/sh #指定输出终端
  2. 指定启动脚本,挂载内核proc文件系统(于内核进程相关),etc目录下创建init.d目录,并在此目录下创建rcS文件,写入:
    mount -t proc none /proc,并且在配置文件中写入:::sysinit:etc/init.d/rcS,指定启动脚本。其中启动脚本中还有另一种方式挂载根文件系统:mount -a,该方法依赖于fastab文件。
  3. 利用mdev机制,自动创建/dev下的设备结点。
    在fastab中添加以下语句:
    proc /proc proc defaults 0 0
    sysfs /sys sysfs defaults 0 0
    tmpfs /dev tmpfs defaults 0 0
    在rcS目录中继线添加以下语句:
    mkdir /dev /pts
    mount -t devpts devpts /dev/pts
    echo /sbin/mdev > /proc/sys/kernel/hotplug #支持热拔插,自动创建设备结点
    mdev -s #将内核原先有的设备驱动结点都创建出来
inittab的格式:<id> : <runlevels> : <action> : <process>
   			id -> /dev/id ,用作终端:stdin,stdout,stderr:ptintf,scanf,err
   			runlevels:忽略
   			action:执行时机
   			process:指定用户程序或脚本

fastab的格式:device		mount-point		type	options	 dump	fsck	order

制作ramdisk格式的根文件系统镜像

要将文件系统烧入开发板,需要做镜像文件

nfs rootfs:可读写,保持在内存中,用于开发调试
cramfs :只读,安全性高,保存在Nor/Nand,一般用于存放重要信息的区域
jffs2:可读写,保存在 Nor/Nand,日志文件系统,掉电不会丢失数据
yaffs1:可读性,小页512B,
yaffs2:可读写,大页2048B,保存在Nand,用在手机领域
ext2/ext3:可读写,保存在硬盘,用在电脑
ext2 over ramdisk:可读写,将内存虚拟为磁盘,将访问内存模拟访问文件,由于是访问内存方式则掉电数据即丢失。

一般都是混合起来使用,将不同数据存放于不同格式区中。

制作步骤:

  1. cd ~
  2. 制作一个8M的镜像。dd用来制作映像,if为input file,of为output file,bs为区块大小,count为区块数量,if=/dev/zero将镜像文件一开始全清零,然后of=ramdisk生成ramdisk映像。
    dd if=/dev/zero of=ramdisk bs=1k count=8192
  3. 将ramdisk映像制作为ext2的文件格式,其中linux默认支持mkfs.ext2命令:
    mkfs.ext2 -F ramdisk
  4. 目前该文件系统镜像为空内容,需要将我们前面做的文件系统拷贝进去,一般是通过将ramdisk挂载到文件系统目录下:
    在mnt目录下新建initrd目录,作为挂载点
    mount -t ext2 ramdisk /mnt/initrd
    将之前制作的文件系统_install目录拷贝到initrd目录下:cp xxx initrd -a,这里注意文件系统大小必须小于ramdisk的空间大小
  5. 压缩ramdisk文件
    gzip --best -c ramdisk > ramdisk.gz
  6. 格式化为uboot识别的格式
    mkimage -n “ramdisk” -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img
  7. 制作成功生成ramdisk.img镜像文件

若读者为tftp方式挂载根文件系统的话,将其拷贝的/tftpboot目录下
cp ramdisk.img /tftpboot/。修改uboot中的启动参数bootcmd:

setenv bootcmd tftp 41000000 uImage \;tftp 42000000 设备树.dtb\;tftp 43000000 ramdisk.img\;bootm 41000000 43000000 42000000 

注意:setenv语句中不能直接以分号;进行语句拆分,它为特殊字符,需用转义符" \ "。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值