简单说明:从搭建环境,安装虚拟机开始移植4.9内核到jz2440开发板,目的是复习Linux交叉编译环境和系统构建的过程
构建最小根文件系统
根文件系统和文件系统的区别:
文件系统是对一个存储设备上的数据进行组织的机制,这种机制有利于用户和操作系统交互
根文件系统是一种文件系统,不仅具有普通文件系统存储数据文件的功能,还是内核启动mount
的第一个文件系统
Linux进程启动分析
- 内核源码分析:init/main.c
static int noinline init_post(void)
/* 创建标准输入,标准输出,标准错误 */
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);
/* execute_command 在 boot命令行参数中设置为 init=/linuxrc */
if (execute_command)
/* 启动第一个程序,是死循环,不会退出 */
run_init_process(execute_command);
}
/* 第一个应用程序一般是execute_command 或者是"/sbin/init",一般不会调用到后面的 */
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
init程序的执行过程 :(配置文件/etc/inittab)
1 读取配置文件
2 解析配置文件
2.1 配置文件指定应用程序
2.2 指定何时执行
3 执行用户程序
init程序就是busybox
linuxrc 和 /sbin/init 都是busybox的链接,都指向 /bin/busybox
busybox根据/etc/inittab里面的项进行系统初始化,最后执行 /etc/init.d/rcS 脚本
busybox 的 执行顺序:/sbin/init > /etc/inittab > /etc/init.d/rcS
- /etc/inittab 格式 —根据busybox的文档inittab
<id>:<runlevels>:<action>:<process>
1 id => /dev/id 用作终端:stdin,stdout... 可以省略
2 runlevels : 忽略
3 action : 执行时机,
sysinit,
respawn,
askfirst,
wait,
once,
restart,
ctrlaltdel,
shutdown
4 process : 应用程序或脚本
由此可以推出:init程序需要准备东西(即最小根文件系统)
1 /dev/console /dev/null
2 /etc/inittab 文件
3 配置文件里指定的应用程序
4 C库(glibc)
5 init程序本身,来源于busybox
制作最小根文件系统
配置,编译busybox
下载链接 : https://busybox.net/downloads/
下载版本:1.20.0
配置安装方法:查看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
解压
tar xjf busybox-1.20.0.tar.bz2
配置
cd busybox-1.20.0.tar.bz2
make menuconfig 完成后保存,因为需要生成.config配置文件
设置交叉编译工具链:
vi Makefile
CROSS_COMPILE ?=arm-linux-
编译
make
安装
创建安装的文件夹,-p表示递归创建
sudo mkdir /work/nfs_root/first_fs -p
安装,安装有错误要修改文件夹的权限
make CONFIG_PREFIX=/work/nfs_root/first_fs install
查看文件夹,已经创建了相应的目录了:
zhanghui@ubuntu:/work/nfs_root/first_fs$ ls
bin linuxrc sbin usr
构建最小根文件系统:(按照init进程分析的结果)####
1 创建/dev/console /dev/null设备节点
mkdir dev
// 查看虚拟机的 /dev/console /dev/null 节点信息:
zhanghui@ubuntu:/work/nfs_root/first_fs/dev$ ls /dev/console /dev/null -l
crw------- 1 root root 5, 1 Jun 12 00:26 /dev/console
crw-rw-rw- 1 root root 1, 3 Jun 12 00:24 /dev/null
//创建设备节点,字符设备/主/次设备号
sudo mknod console c 5 1
sudo mknod null c 1 3
2 创建/etc/inittab
mkdir etc
vi inittab
console::askfirst:-/bin/sh
3 安装C库
C库的位置在:
zhanghui@ubuntu:/work/sys/opt/FriendlyARM/toolschain/4.4.3/lib$ ls
gcc libcloog.so.0.0.0 libgmpxx.la libmpc.la libmpfr.so libmp.so.3 libppl_c.so.2.1.0 libpwl.la
ldscripts libgmp.la libgmpxx.so libmpc.so libmpfr.so.1 libmp.so.3.1.14 libppl.la libpwl.so
libcloog.la libgmp.so libgmpxx.so.4 libmpc.so.2 libmpfr.so.1.2.2 libppl_c.la libppl.so libpwl.so.4
libcloog.so libgmp.so.3 libgmpxx.so.4.1.0 libmpc.so.2.0.0 libmp.la libppl_c.so libppl.so.7 libpwl.so.4.0.0
libcloog.so.0 libgmp.so.3.5.0 libiberty.a libmpfr.la libmp.so libppl_c.so.2 libppl.so.7.1.0
创建lib目录:
mkdir /work/nfs_root/first_fs/lib
拷贝C库到lib目录:
cp *.so* /work/nfs_root/first_fs/lib -d
4 指定应用程序
— 没有应用程序
5 完善最小根文件系统
创建proc文件系统
mkdir proc
在/etc/inittab中加上:
::sysinit:/etc/init.d/rcS
再创建init.d/rcS脚本文件
mkdir init.d
vi rcS
sudo chmod +x rcS
// 自动挂载proc文件系统
mount -t proc none /proc
另外一种方法:
vi rcS
#mount -t proc none /proc
mount -a
mount -a 依赖于/etc/fstab
创建fstab, vi fstab 添加
proc /proc proc defaults 0 0
- fstab的格式: 执行mount -a 后将挂接proc tmpfs 文件系统
# device mount-pount type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
6 增加udev机制(自动创建设备节点)
— busybox里面的简化版本 mdev
mkdir sys
vi etc/fstab
添加:
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
vi etc/init.d/rcS
添加:
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
制作根文件系统映像文件
制作yaffs2文件系统
- 制作工具
yaffs_source_util_larger_small_page_nand.tar.bz2 (韦东山)
tar xjf yaffs_source_util_larger_small_page_nand.tar.bz2
cd /work/sys/Development_util_ok/yaffs2/utils(里面含有makefile)
make
- 编译结果:
zhanghui@ubuntu:/work/sys/Development_util_ok/yaffs2/utils$ ls -l
total 144
-rw------- 1 zhanghui zhanghui 1770 Jul 7 2008 Makefile
-rwxrwxr-x 1 zhanghui zhanghui 22768 Jun 12 01:22 mkyaffs2image
-rw------- 1 zhanghui zhanghui 19669 Jul 7 2008 mkyaffs2image.c
-rw-rw-r-- 1 zhanghui zhanghui 12408 Jun 12 01:22 mkyaffs2image.o
-rwxrwxr-x 1 zhanghui zhanghui 18496 Jun 12 01:22 mkyaffsimage
-rw------- 1 zhanghui zhanghui 16206 Feb 28 2008 mkyaffsimage.c
-rw-rw-r-- 1 zhanghui zhanghui 11160 Jun 12 01:22 mkyaffsimage.o
... ...
我们使用 mkyaffs2image 这个工具
拷贝到系统目录:
sudo cp mkyaffs2image /usr/local/bin/
sudo chmod +x /usr/local/bin/mkyaffs2image
切换到最小根文件系统目录的上一级:
cd /work/nfs_root/
创建映像:
/* 目录 名称 */
mkyaffs2image first_fs first_fs.yaffs2
创建成功:
zhanghui@ubuntu:/work/nfs_root$ ls
first_fs first_fs.yaffs2
制作jffs2文件系统
- u-boot 命令行参数设置
set bootargs noinitrd console=ttySAC0,115200 root=/dev/mtdblock3
rootfstype=jffs2 init=/linuxrc
- 制作jffs2文件系统
工具:
mtd-utils-05.07.23.tar.bz2
zlib-1.2.3.tar.gz
解压
tar xzf zlib-1.2.3.tar.gz
配置
./configure --shared --prefix=/usr
编译 安装
make
sudo make install
解压
tar xjf mtd-utils-05.07.23.tar.bz2
cd mtd-utils-05.07.23/util/
make
sudo make install
制作:
cd /work/nfs_root/
mkfs.jffs2 -n -s 2048 -e 128KiB -d first_fs -o first_fs.jffs2
搭建NFS文件系统
虚拟机
1 安装nfs文件系统
sudo apt-get install nfs-kernel-server
sudo vi /etc/exports 添加:
/work/nfs_root/first_fs 192.168.3*(rw,sync,no_subtree_check)
sudo service portmap restart
sudo service nfs-kernel-server restart
2 虚拟机允许:
sudo vi /etc/exports
添加网络文件系统目录
3 本地挂载
sudo mount -t nfs -o nolock 192.168.3.61:/work/nfs_root/first_fs /mnt
单板
1 手动挂载:
mount -t nfs -o nolock 192.168.1.19:/work/nfs_root/first_fs /mnt
2 直接从NFS启动:设置启动参数
1 服务器IP
2 设置自己的IP
命令行格式:
参考内核文档 :Documentation/filesystems/nfs/nfsroot.txt
root=/dev/nfs
nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>::eth0:off
gw-ip :网关,随便写
netmask : 子网掩码 255.255.255.0
下载文件系统并测试
至此,应该做的准备工作已经全部做完,现在验证内核是否能成功启动(实际移植顺序应该是边移植边验证)
1 内核本身不支持yaffs2文件系统,因此yaffs2文件系统暂时不支持
2 网卡驱动还没有移植,因此NFS文件系统还不能用
3 因此,首先使用jffs2验证
- 过程中遇到的一些错误及其处理
1 注意最小文件系统的lib库需要复制
/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib
里面的库文件
arm-none-linux-gnueabi 是新的工具链
2 配置内核增加EABI接口:
make menuconfig
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL)
EABI简介:ABI 指的是应用程序二进制接口,类比及API,ABI是二进制级别的兼容。
E指的是Embedded,嵌入的
好处:
支持软件浮点和硬件实现浮点功能混用
系统调用的效率更高
后今后的工具更兼容
软件浮点的情况下,EABI的软件浮点的效率要比OABI高很多
3 无法创建节点错误:
can't open /dev/ttySAC0: No such file or directory
解决方法:
make menuconfig 搜索 DEVTMPFS 把相关自动创建节点的配置项设置为Y即可
- 到现在为止,内核已经成功启动!
/ # ls
bin etc linuxrc sbin tmp
dev lib proc sys usr
/ #
- 接下来,
1 移植DM9000网卡驱动,挂载NFS文件系统
2 移植yaffs文件系统
3 移植LCD驱动
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!