最小根文件系统的构建(基于JZ2440)

  1. u-boot:启动内核

  2. 内核: 启动应用程序

  3. 构建:根文件系统(应用程序存放处)

1 init进程

内核启动的最后一步是启动init进程, 代码在内核里init/main.c文件中,执行步骤如下

  1. 打开设备 open("/dev/console") (同时执行两次sys_dup(0),分别为标准输入、标准输出、标准错误,它们对应的文件描述符分别是0、1、2,其均指向同一设备)
  2. run_init_process("…")(…为命令行参数所指定 或 /sbin/init 或 /etc/init 或 /bin/init 或 /bin/sh)

Linux-2.6.22.6/init中的main.c 部分

/* This is a non __init function. Force it to be noinline otherwise gcc
 * makes it inline to init() and it becomes part of init.text section
 */
static int noinline init_post(void)
{
	free_initmem();
	unlock_kernel();
	mark_rodata_ro();
	system_state = SYSTEM_RUNNING;
	numa_default_policy();

	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		printk(KERN_WARNING "Warning: unable to open an initial console.\n");

	(void) sys_dup(0);
	(void) sys_dup(0);

	if (ramdisk_execute_command) {
		run_init_process(ramdisk_execute_command);
		printk(KERN_WARNING "Failed to execute %s\n",
				ramdisk_execute_command);
	}

	/*
	 * We try each of these until one succeeds.
	 *
	 * The Bourne shell can be used instead of init if we are
	 * trying to recover a really broken machine.
	 */
	if (execute_command) {
		run_init_process(execute_command);
		printk(KERN_WARNING "Failed to execute %s.  Attempting "
					"defaults...\n", execute_command);
	}
	run_init_process("/sbin/init");
	run_init_process("/etc/init");
	run_init_process("/bin/init");
	run_init_process("/bin/sh");

	panic("No init found.  Try passing init= option to kernel.");
}

init 程序

  1. 读取配置文件
  2. 解析配置文件
  3. 执行用户程序

2 构建最小根文件系统

2.1 环境

kernel:Linux-2.6.22.6,uImage_2.6;u-boot:u-boot-1.16,uboot.bin;busybox:busybox-1.7.0_patched;交叉编译器:arm-linux-gcc-3.4.5

2.1.1 编译busybox

2.1.1.1 什么是busybox

BusyBox 是一个集成了三百多个最常用Linux命令和工具的软件。BusyBox 包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令,也包含了 Android 系统的自带的shell。(来至百度百科)

BusyBox 将许多具有共性的小版本的UNIX工具结合到一个单一的可执行文件。这样的集合可以替代大部分常用工具比如的GNU fileutils , shellutils等工具,BusyBox提供了一个比较完善的环境,可以适用于任何小的嵌入式系统。(来至百度百科)

  1. tar xjf busybox-1.7.0_patched.tar.bz2 解压busybox;

    F:\嵌入式linux\jz2440\linux资料\002_JZ2440资料光盘_20180516(免费)\资料光盘\B盘

  2. 进入busybox 目录下的INSTALL文件查看编译过程

     make menuconfig     # This creates a file called ".config"
     make                # This creates the "busybox" executable
     make install        # or make CONFIG_PREFIX=/path/from/root install
    
  3. 执行 vi Makefile 添加如下内容,设置交叉编译工具

    将176行代码 CROSS_COMPILE   ?=  改为 CROSS_COMPILE   ?= arm-linux-
    
  4. 执行make menuconfig,设置“TAB”键补全

    Busybox Settings  --->
    	Busybox Library Tuning  --->
    		[*]   Tab completion 
    
  5. 执行 make

  6. 执行 mkdir /work/nfs_root/third_fs 在网络文件夹下创建一个文件夹

  7. 执行 make CONFIG_PREFIX=/work/nfs_root/third_fs install 安装到之前创建的文件夹中

  8. 执行 cd /work/nfs_root/third_fs 进入之前创建的文件夹中, 执行 ls -l 可以看到以下内容

    image-20200621201159193

2.1.2 构建etc目录

init 进程根据 etc/initab 文件来创建其他子进程,比如调用脚本文件配置IP地址、挂接
其他文件系统,最后启动shell等。

etc目录下的内容取决于要运行的程序,这里只需要创建3个文件: etc/initab、
etc/init.d/rcS、etc/fstab。

  1. third_fs 中创建 etc 文件夹,然后在 etc 目录下创建 inittab 文件并添加 console::askfirst:-/bin/sh,如下(etc/inittab文件中的每条目录用来定义一个子进程,并确定它的启动方法,格式::::

    image-20200621202929656

    以让标准输入/标准输出/标准错误都指向控制台;

2.1.3 构建dev目录

这里使用 mdev 来构建 dev,mdev 是 udev 的简化版本,它也是通过读取内核信息来创建设备文件。mdev的用法在busybox- 1.7.0/doc/mdev.txt文件中。

mdev的用途主要有两个

  1. 初始化/dev目录、动态更新
  2. 动态更新不仅是更新/dev目录,还支持热拔插,即接入、卸下设备时执行
    某些动作。

要使用mdev,需要内核支持sysfs文件系统,为了减少对Flash的读写,还要支持tmpfs文件系统。参考命令如下

$ mount -t tmpfs mdev I /dev	/*使用内存文件系统,减少对Flash的读写*/
$ mkdir /dev/pts		/* devpts用来支持外部网络连接(telnet)的虚拟终端*/
$ mount -t devpts devpts /dev/pts
$ mount-t sysfs sysfs /sys	/* mdev通过sysfs文件系统获得设备信息*/
$ echo /bin/mdev> /proc/sys/kernel/hotplug /* 设置内核,当有设备拔插时调用/bin/mdev 程序*/
$ mdev -S	/*在/dev目录下生成内核支持的所有设备的结点*/

mdev 是通过 init 进程来启动的,在使用 mdev 构造 /dev 目录之前,init 进程至少
要用到设备文件有 /dev/console 和 /dev/null,所以要建立这两个设备文件,执行以下步骤进行创建

  1. third_fs 中执行 mkdir dev && cd dev 创建dev文件夹并进入

  2. 执行 ls /dev/console /dev/null -l 查看虚拟机中设备 consolenull 的信息,然后在 dev 目录下创建相同的设备,如下(sudo mknod console c 5 1sudo mknod null c 1 3)

image-20200621202134272

这里还未使用mdev,mdev在2.1.8小节出使用,以完善最小根文件系统。

2.1.4 安装glibc库

  1. third_fs 中执行 mkdir lib 创建 lib 目录,然后在 /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中执行 cp *.so* /work/nfs_root/third_fs/lib/ -d, 将C库拷贝到根文件系统的 lib 目录中, -d 表示将是链接的文件依然以链接的形式拷贝;

2.1.5 设置网络文件系统

  1. 执行 sudo vi /etc/exports 添加 /work/nfs_root/third_fs *(rw,nohide,insecure,no_subtree_check,async,no_root _squash),设置 third_fs 为NFS文件并能被别人挂载,配置nfs后重启nfs sudo /etc/init.d/nfs-kernel-server restart
  2. 执行 set bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.11:/work/nfs_root/third_fs ip=192.168.1.12:192.168.1.11:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0 设置开发板启动自动挂载根文件系统,

2.1.6 用proc进行改进

  1. 至此内核已经可以挂载我们上面创建的根文件系统了,但还是缺乏部分文件(不能使用ps等命令)

    image-20200622102739618

    因此需要在根文件系统中创建 proc 目录,同时执行 mount -t proc none /proc 手动挂载虚拟文件系统(proc是内核提供的虚拟文件系统)

    image-20200622103114026

  2. etc/inittab 中添加 ::sysinit:/etc/init.d/rcS脚本文件,然后执行如下命令,并添加相应内容

    image-20200621205353433

    让开发板自动挂载内核中的proc虚拟文件系统

2.1.7 最小根文件系统所含内容

  1. 至此,最小根文件系统即构造完毕,内容如下

    bin中存放的是ps等各种命令,均为指向busybox的链接文件

    image-20200622105925422

    dev中存放的是我们之前创建的设备字符文件,etc中存放的是配置文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ctQzolMy-1592847912711)(mdPics/image-20200622110146836.png)]

    lib中存放的是我们之前拷贝的glibc库,以 .so 结尾的动态库文件

    image-20200622110546347

    proc中存放的是内核的虚拟文件系统

    image-20200622113641469

    sbin中存放的是ifconfig/reboot等命令,均为指向busybox的链接文件

    image-20200622111148680

    usr中存放的内容如下,它们都是指向busybox的链接文件

    image-20200622111724609

2.1.8 完善根文件系统

  1. 改善proc虚拟文件挂载方式,使用 mount -a 进行挂载,它会去读取etc/fstab内的内容并挂载相应的文件系统,执行如下命令创建fstab

    image-20200622124632835

    etc/init.d/rcS 中的内容修改为

    image-20200622123536549

  2. 使用 mdev (udev的简化版本),自动创建/dev/设备节点(取代手动创建设备节点,省事),再third_fs中创建sys目录并将etc/fstab的内容修改为

    image-20200622130905534

    将etc/init.d/rcS的内容修改为

    image-20200622131228971

    使用 mdev 之前 dev 下的内容为

    image-20200622131443343

    使用 mdev 之后 dev 下的内容如下(仅为部分截图),可以发现 proc 下挂载了许多文件系统,同时 dev 目录下的设备节点也多了许多

    image-20200622131756994

    至此,最小根文件系统已经比较完善了。

2.1.9 错误聚集地(问题还未解决,解决后将会进行更新)

  1. insmod xxx.ko正常,但是 cat /proc/devices 却没有(实则驱动并未装载成功)

2.2 环境

kernel:Linux-3.4.2,uImage_3.4;u-boot:u-boot-2012.04.01,uboot_new.bin;busybox:busybox-1.20.2;交叉编译器:arm-linux-gcc-4.3.2

2.2.1 更换交差编译器

2.2.2 编译busybox

  1. tar xjf busybox-1.20.2.tar.bz2 解压busybox;

  2. 执行make menuconfig,设置交叉编译

    Busybox Settings  ---> 
    	Build Options  ---> 
        	(arm-linux-) Cross Compiler prefix 	
    
  3. 执行 make

  4. 执行 mkdir /work/nfs_root/fourth_fs 在网络文件夹下创建一个文件夹

  5. 执行 make CONFIG_PREFIX=/work/nfs_root/fourth_fs install 安装到之前创建的文件夹中

2.2.3 安装glibc库

  1. 进入交叉编译文件中(例:/usr/local/arm/4.3.2),执行如下命令查找库文件

    image-20200622150153299

    然后执行如下命令将库文件拷贝到根文件系统中

    image-20200622150559454

2.2.4 构建etc目录

  1. 执行 sudo cp third_fs/etc fourth_fs/ -rf 将之前创建的third_fs内的etc拷贝到新建的根文件系统中

    image-20200622152322343

2.2.5 构建dev目录

  1. 执行 mkdir dev && cd dev
  2. 执行 sudo mknod console c 5 1sudo mknod null c 1 3

2.2.6 构建其他目录

  1. 执行 mkdir proc tmp sys root, 创建其他需要的目录

2.2.7 错误聚合

  1. rmmod时出现如下错误

    image-20200622201224517

    在lib目录下创建modules(空目录即可)解决错误

    image-20200622201358893

  2. 然后又来了个问题,用rmmod卸载驱动依然出错(崩溃中…)

    image-20200622201813079

    在lib/modules 下创建3.4.2目录(空目录即可)解决问题

    image-20200622202737412

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值