文章目录
-
u-boot:启动内核
-
内核: 启动应用程序
-
构建:根文件系统(应用程序存放处)
1 init进程
内核启动的最后一步是启动init进程, 代码在内核里init/main.c文件中,执行步骤如下
- 打开设备 open("/dev/console") (同时执行两次sys_dup(0),分别为标准输入、标准输出、标准错误,它们对应的文件描述符分别是0、1、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 程序
- 读取配置文件
- 解析配置文件
- 执行用户程序
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提供了一个比较完善的环境,可以适用于任何小的嵌入式系统。(来至百度百科)
-
tar xjf busybox-1.7.0_patched.tar.bz2 解压busybox;
F:\嵌入式linux\jz2440\linux资料\002_JZ2440资料光盘_20180516(免费)\资料光盘\B盘
-
进入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
-
执行 vi Makefile 添加如下内容,设置交叉编译工具
将176行代码 CROSS_COMPILE ?= 改为 CROSS_COMPILE ?= arm-linux-
-
执行make menuconfig,设置“TAB”键补全
Busybox Settings ---> Busybox Library Tuning ---> [*] Tab completion
-
执行 make
-
执行 mkdir /work/nfs_root/third_fs 在网络文件夹下创建一个文件夹
-
执行 make CONFIG_PREFIX=/work/nfs_root/third_fs install 安装到之前创建的文件夹中
-
执行 cd /work/nfs_root/third_fs 进入之前创建的文件夹中, 执行 ls -l 可以看到以下内容
2.1.2 构建etc目录
init 进程根据 etc/initab 文件来创建其他子进程,比如调用脚本文件配置IP地址、挂接
其他文件系统,最后启动shell等。
etc目录下的内容取决于要运行的程序,这里只需要创建3个文件: etc/initab、
etc/init.d/rcS、etc/fstab。
-
在 third_fs 中创建 etc 文件夹,然后在 etc 目录下创建 inittab 文件并添加 console::askfirst:-/bin/sh,如下(etc/inittab文件中的每条目录用来定义一个子进程,并确定它的启动方法,格式::::)
以让标准输入/标准输出/标准错误都指向控制台;
2.1.3 构建dev目录
这里使用 mdev 来构建 dev,mdev 是 udev 的简化版本,它也是通过读取内核信息来创建设备文件。mdev的用法在busybox- 1.7.0/doc/mdev.txt文件中。
mdev的用途主要有两个
- 初始化/dev目录、动态更新
- 动态更新不仅是更新/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,所以要建立这两个设备文件,执行以下步骤进行创建
-
在 third_fs 中执行 mkdir dev && cd dev 创建dev文件夹并进入
-
执行 ls /dev/console /dev/null -l 查看虚拟机中设备 console 和 null 的信息,然后在 dev 目录下创建相同的设备,如下(sudo mknod console c 5 1 和 sudo mknod null c 1 3)
这里还未使用mdev,mdev在2.1.8小节出使用,以完善最小根文件系统。
2.1.4 安装glibc库
- 在 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 设置网络文件系统
- 执行 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
- 执行 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进行改进
-
至此内核已经可以挂载我们上面创建的根文件系统了,但还是缺乏部分文件(不能使用ps等命令)
因此需要在根文件系统中创建 proc 目录,同时执行 mount -t proc none /proc 手动挂载虚拟文件系统(proc是内核提供的虚拟文件系统)
-
在 etc/inittab 中添加 ::sysinit:/etc/init.d/rcS脚本文件,然后执行如下命令,并添加相应内容
让开发板自动挂载内核中的proc虚拟文件系统
2.1.7 最小根文件系统所含内容
-
至此,最小根文件系统即构造完毕,内容如下
bin中存放的是ps等各种命令,均为指向busybox的链接文件
dev中存放的是我们之前创建的设备字符文件,etc中存放的是配置文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ctQzolMy-1592847912711)(mdPics/image-20200622110146836.png)]
lib中存放的是我们之前拷贝的glibc库,以 .so 结尾的动态库文件
proc中存放的是内核的虚拟文件系统
sbin中存放的是ifconfig/reboot等命令,均为指向busybox的链接文件
usr中存放的内容如下,它们都是指向busybox的链接文件
2.1.8 完善根文件系统
-
改善proc虚拟文件挂载方式,使用 mount -a 进行挂载,它会去读取etc/fstab内的内容并挂载相应的文件系统,执行如下命令创建fstab
将 etc/init.d/rcS 中的内容修改为
-
使用 mdev (udev的简化版本),自动创建/dev/设备节点(取代手动创建设备节点,省事),再third_fs中创建sys目录并将etc/fstab的内容修改为
将etc/init.d/rcS的内容修改为
使用 mdev 之前 dev 下的内容为
使用 mdev 之后 dev 下的内容如下(仅为部分截图),可以发现 proc 下挂载了许多文件系统,同时 dev 目录下的设备节点也多了许多
至此,最小根文件系统已经比较完善了。
2.1.9 错误聚集地(问题还未解决,解决后将会进行更新)
- 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
-
tar xjf busybox-1.20.2.tar.bz2 解压busybox;
-
执行make menuconfig,设置交叉编译
Busybox Settings ---> Build Options ---> (arm-linux-) Cross Compiler prefix
-
执行 make
-
执行 mkdir /work/nfs_root/fourth_fs 在网络文件夹下创建一个文件夹
-
执行 make CONFIG_PREFIX=/work/nfs_root/fourth_fs install 安装到之前创建的文件夹中
2.2.3 安装glibc库
-
进入交叉编译文件中(例:/usr/local/arm/4.3.2),执行如下命令查找库文件
然后执行如下命令将库文件拷贝到根文件系统中
2.2.4 构建etc目录
-
执行 sudo cp third_fs/etc fourth_fs/ -rf 将之前创建的third_fs内的etc拷贝到新建的根文件系统中
2.2.5 构建dev目录
- 执行 mkdir dev && cd dev
- 执行 sudo mknod console c 5 1 和 sudo mknod null c 1 3
2.2.6 构建其他目录
- 执行 mkdir proc tmp sys root, 创建其他需要的目录
2.2.7 错误聚合
-
rmmod时出现如下错误
在lib目录下创建modules(空目录即可)解决错误
-
然后又来了个问题,用rmmod卸载驱动依然出错(崩溃中…)
在lib/modules 下创建3.4.2目录(空目录即可)解决问题