根文件系统的烧写与构建

一、烧写文件系统

我们怎么烧写一个根文件系统呢?
如下:再uboot里面输入y命令,然后使用DNW进行烧写。(注意:如果你的DNW的驱动安装有问题,你去看韦东山有一个操作文档。最好使用这个:dnw_100ask.exe)。
然后使用DNW软件选择fs_mini.yaffs2文件,这时就会把fs_mini.yaffs2这个文件系统烧写到开发板。
在这里插入图片描述
烧写完成之后在uboot里输入b命令启动系统。从提示信息(“please press enter to activate the console”)可以看出我们按"enter"键就会已经启动sh应用程序,因此我们按键盘字母,在串口里能够显示出来,这说明sh程序已经启动、发挥作用了。
在这里插入图片描述

二、根文件启动第1个程序

看下图:
我们知道,uboot启动内核,内核启动应用程序,而应用程序就位于根文件系统。应用程序有很多(a1、a2、b1、b2等等等)。
在这里插入图片描述
看下图的内核启动流程
mount root是挂接根文件系统,init_post函数就是用来执行应用程序的。也就是说内核会先执行“挂接跟文件系统”的工作,然后执行应用程序。(应用程序在根文件系统中,内核想要调用应用程序的话就得与跟文件系统建立联系,即挂接)
在这里插入图片描述
好,我们来分析内核文件的main.c文件,来看里面的init_post函数,分析以下怎么启动应用程序的:

.......
static int noinline init_post(void)
{
    
    
	free_initmem();
	unlock_kernel();
	mark_rodata_ro();
	system_state = SYSTEM_RUNNING;
	numa_default_policy();

/*----------------------01首先打开设备/dev/console,打开第0个文件指向/dev/console--------------------*/
	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
/*----------------------01打开设备/dev/console之后,复制第1、2个文件并指向/dev/console---------------*/
	(void) sys_dup(0);
	(void) sys_dup(0);
/*解释一下/dev/console
*printf、scanf、err这三个函数是标准输入、标准输出、标准错误,这三个函数都是从/dev/console文件里输入输出的。上面的文件(第0、1、
2)这三个文件分别代表printf、scanf、err这三个函数
*可以看出,/dev/console就是串口的意思。
*/

	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.
	 */

/*------------02分析一下下面的语句-------------------------*/
/*execute_command如果为真,则执行execute_command,
否则执行/sbin/init(一去不复返),如果也不成功,则执行/etc/init(一去不复返),再不成功则执行/bin/init(一去不复返),再不成功
则执行/bin/sh。
execute_command是什么呢?execute_command就是你在u-boot里面输入的命令,比如你在u-boot里面输入print。好,看看execute_command具
体是啥,去看程序。
*/
	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");//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.");
}

......
static int __init init_setup(char *str)
{
    
    
	unsigned int i;

	execute_command = str;
	/*
	 * In case LILO is going to boot us with default command line,
	 * it prepends "auto" before the whole cmdline which make字符字符s
	 * the shell think it should execute a script with such name.
	 * So we ignore all arguments entered _before_ init=... [MJ]
	 */
	for (i = 1; i < MAX_INIT_ARGS; i++)
		argv_init[i] = NULL;
	return 1;
}
__setup("init=", init_setup);//这个init_setup函数就是读取你在u-boot里输入的字符(即命令,如openJTAG>>print的print),然后
//执行init=xxx。如我们执行openJTAG>>print,则init=/linuxrc,即去执行文件/linuxrc。
......

总结一下就是:
内核总是首先打开根文件系统的/dev/console目录,打开第0、1、2个文件。如下图所示:
在这里插入图片描述
第一个应用程序可能是execute_command /sbin/init、/etc/init、/bin/init、/bin/sh中的一个。
如果execute_command如果为真,则执行execute_command。否则执行/sbin/init。若没有/sbin/init程序,就执行下一条语句即执行/etc/init。如果没有/etc/init的话就执行下一条即执行/bin/init。若没有/bin/init,则执行下一条语句即执行/bin/sh。
注意,这里说的这几个程序都是一旦执行就会一去不复返的,比如如果执行了execute_command,那么/sbin/init、/etc/init、/bin/init、/bin/sh都没有机会执行了。

咱们第一节烧写的根文件系统,启动系统后执行的第一个程序就是/etc/init,即根文件的第一个应用程序。

上面咱们说的/sbin/init、/etc/init、/bin/init、/bin/sh都是文件系统的应用程序。

三、init进程分析

这个init其实就是busybox。
你去看本文的4.1,我们把busybox安装到我们的根文件系统之后,会发现在我们的根文件系统中生成了bin linuxrc sbin usr四个文件/文件夹。可以认为busybox是由bin linuxrc sbin usr组成的

3.1关于busybox

首先我们知道,在linux中输入的ls、cp、cd、find等命令实际上本质都是应用程序。
其实吧,这些应用程序被集成到了一个叫busybox的东西(busybox这个东西很牛,把ls、cp、cd、find等程序集成了,并且占用的内存空间很小,这就是它的优势)所谓busybox,你去看这篇文章:https://blog.csdn.net/feelinghappy/article/details/92133067
这篇文章里涉及到linux命令In -s 源文件 目标文件,如果你不懂,请去看:https://blog.csdn.net/adsadadaddadasda/article/details/78799086

我们在sourse insight中建立一个工程然后打开busybox文件(压缩文件名为busybox-1.7.0.tar.bz2),然后在工程中搜索cp,会发现有一个cp.c文件,里面有一个cp_main函数。分析一下:
比如我们输入cp命令,则cp是一个链接,链接到busybox cp,busybox 会调用cp.c文件的cp_main函数,这个函数就是cp的定义函数。

3.2 init进程分析

这节可以不用看,但是你只需要直到一个最小根文件包括什么就可以了,如本小节3.2的最后一幅图片所示!!!

内核通过内核中的/sbin/init(第一个应用程序)去启动客户的应用程序(比如你自己写的监控程序),在busybox里有init.c。
同样,/sbin/init也会调用init.c中的init_main函数,这个函数做了什么是呢?我们猜测:
在这里插入图片描述
好,我们看源码init_main(),看看init做了什么,我们分析源码,得出框架如下:
(你要是看不懂,就回去看视频吧)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
经过分析发现,我们的最小跟文件系统包括以下五个部分:
(init本身就是一个busybox)
(所谓C库,就是程序中的printf()、fopen()、scanf()都是在C库中)
在这里插入图片描述

四、构建根文件系统

我们这节的目的就是构造根文件系统

4.1构建根文件系统之busybox

构建根文件系统之busybox其实就是完成上图的第二项——根文件系统的init

我们首先把busybox-1.7.0_patched.tar.bz2文件拷贝到Ubuntu,然后解压。

解压得到的文件夹里面有一个INSTALL文件教你如何编译,如下:
在这里插入图片描述
上图的第6行代表配置(如何配置,你去看韦东山的书——完全手册,或者去看视频。其实对于初学者,不用你去修改配置)
上图的第7行为编译
上图的第8行为安装(如果直接执行make install就直接就默认安装到pc了,这是绝对不允许的。因此你要加上安装地址,也就是说,你可以在linux中新建立一个文件夹(即你要构建的根文件系统的文件夹),以把它安装到这个文件夹中)。

具体安装操作如下:
tar xjf busybox-1.7.0_patched.tar.bz2

cd ./busybox-1.7.0

make menuconfig进入菜单栏,直接退出就行。

vi Makefile 打开Makefile 你的Makefile要有arm-linux-,如下图所示。
在这里插入图片描述
执行make 如果你编译错误的话就请去百度,是有解决的。

好,我们建立一个根文件系统的文件夹,我们起名为first_fs
执行命令如下:
在这里插入图片描述

然后按照INSTALL文件的安装方法,执行
make CONFIG_PREFIX=/home/lioker/Desktop/dfs_root/first_fs install

然后我们到first_fs文件夹下看看,发现有4个目录,如下图:
在这里插入图片描述

然后你会发现ls是指向busybox的:
在这里插入图片描述
操作到这里,我们就构建完成了根文件系统的busybox。也就是说我们构建了根文件系统的一部分了。

4.2构建跟文件系统的dev目录、ect目录和其他目录

4.2.1构建跟文件系统的dev目录

我们的任务是建立dev的console和null。

我们先看看linux系统中的dev的console和null的主设备号和次设备号。
ls /dev/console /dev/null -l
在这里插入图片描述

好,我们来开始操作

首先在first_fs中建立一个dev文件夹:
mkdir dev
然后cd dev
然后sudo mknod console c 5 1 (注:mknod命令用于创建Linux中的字符设备文件和块设备文件。 执行这个语句就会生成一个console字设备文件)
然后ls /dev/console /dev/null -l
我们ls -l查看一下我们创建的console和null:
在这里插入图片描述

至此,dev目录构建完成!

4.2.2构建跟文件系统的etc目录

首先执行 cd ./… 进入到first_fs目录

mkdir etc创建etc目录
vi etc/inittab
在打开的inittab文件中假如console::askfirst:-/bin/sh(意思是说加入/bin/sh程序,依靠console的标准输入、标准输出和标准错误)
在这里插入图片描述
etc目录构建完成

4.3加入C库

我们首先在first_fs目录下创建一个lib目录
mkdir lib

然后我们找到韦东山的arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2文件,然后解压
在这里插入图片描述
然后执行ls -l你可以看到很多库
我们把这些库中的.so文件拷贝到我们刚刚创建的first_fs/lib目录,操作如下:

lioker:lib$ cp *.so* /home/lioker/Desktop/dfs_root/first_fs/lib -d

在这里插入图片描述
至此,我们完成了我们的最小根文件系统,完成了下图的1、2、3、5项:
注意:第4项是指定我们自己的应用程序的,我们在本文的第 节再来添加此项。
在这里插入图片描述
好,最小跟文件系统已经创建完毕了,怎么把它添加到我们的开发板呢,我们得把它制作成映像文件(yaffs文件或者是jffs文件),看下一节。

4.4制作/使用根文件系统的映像文件(yaffs / jffs文件)

首先在电脑中找到韦东山的yaffs_source_util_larger_small_page_nand.tar.bz2文件,拷贝到linux桌面然后解压。
然后cd进入到下面的文件夹中执行make命令进行编译:
/home/lioker/Desktop/Development_util_ok/yaffs2/utils
在这里插入图片描述
你刚刚执行的make就编译出来了下面这些工具:
在这里插入图片描述
而我们需要的工具是上图的第二个工具,即mkyaffs2image,我们把这个工具拷贝到我们的linux系统中去。
并且为/usr/local/bin/mkyaffs2image修改权限。
操作如下:

lioker:utils$ sudo cp mkyaffs2image /usr/local/bin
[sudo] password for lioker: 
lioker:utils$ sudo chmod +x /usr/local/bin/mkyaffs2image 

然后我们cd到dfs_root文件夹下,我们输入下面的语句,就可以把dfs_root文件夹下的first_fs映像成一个.yaffs2文件,操作如下:

lioker:dfs_root$ mkyaffs2image first_fs/ first_fs.yaffs2
lioker:dfs_root$ ls
first_fs  first_fs.yaffs2

好,映像成功。我们把first_fs.yaffs2从linux中拷贝到win电脑系统中,然后烧写到开发板中。

猜你喜欢

转载自blog.csdn.net/weixin_45519751/article/details/107727542
今日推荐