简单说明:从搭建环境,安装虚拟机开始移植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 协议 ,转载请注明出处!

从0移植4.9内核(1) 上一篇
数据结构-哈希表 下一篇