学习交流加

  • 个人qq:
    1126137994
  • 个人微信:
    liu1126137994
  • 学习交流资源分享qq群:
    962535112

上一篇文章,我们修改了内核代码改了系统的分区,但是最后启动,发现虽然我们可以挂载之前的文件系统,但是无法启动init进程。说明我们新移植的内核不支持我们之前制作的老的文件系统(点击查看上一篇文件:上一篇文章)。今天我们来制作新的文件系统。

我们用的是哪一个编译器编译的内核,就用哪一个编译器编译文件系统的应用程序:

1.编译Busybox

获取busybox源码1.20.0版本的(下载地址:下载地址),把下载好的源码拿到Linux系统解压,进入到源码目录:
然后直接:
make menuconfig (交叉编译)
出现如下界面:

选择:
Busybox Settings —>
Build Options —>
Cross Compiler prefix (NEW)
然后会出现可以输入的横条,在里面输入我们的编译器的前缀:

配置好后,退出保存保存配置。
然后直接输入:
make (编译)
编译完成后,我们把它安装到/work/nfs_root目录下,进入到这个目录,建立一个目录:
mkdir fs_mini_mdev_new (新的文件系统目录)

然后切换到busybox目录,进行安装(安装命令可以查看README):
make install CONFIG_PREFIX=/work/nfs_root/fs_mini_mdev_new
第一步已经完成,busybox已经安装好,下一步是安装库。

2.安装库

我们查看到我们的编译工具的路径:
echo $PATH
得知编译工具的路径为:
/work/tools/usr/local/arm/4.3.2/bin
进入到这个目录
/work/tools/usr/local/arm/4.3.2
输入find -name lib
找到很多库如下:

用到的库只有这两个:
./arm-none-linux-gnueabi/libc/armv4t/usr/lib
./arm-none-linux-gnueabi/libc/armv4t/lib
我们只需要把这两个库拷贝过来就行:

先在fs_mini_mdev_new目录下建立以lib目录:
然后把/work/tools/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib目录下的所有.so文件拷贝到fs_mini_mdev_new目录下的lib目录:

cp /work/tools/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/*so*  /work/nfs_root/fs_mini_mdev_new/lib -d (-d代表原来是链接文件,拷贝过来之后还是链接文件)

还有一个库需要添加:
在/work/nfs_root/fs_mini_mdev_new/usr目录下创建一个lib目录,然后把编译器中的usr/lib目录下的库拷贝过来:

cp /work/tools/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib/*so*  /work/nfs_root/fs_mini_mdev_new/usr/lib -d

库已经添加完了,接下来是构造一些其他目录(etc,dev目录等):

3.构造etc目录:

3.1创建etc/inittab文件
在/work/nfs_root/fs_mini_mdev_new目录下,创建inittab文件,里面内容如下:

# /etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

3.2创建etc/init.d/rcS文件
这是一个脚本问价,可以在里面添加想自动执行的命令。以下命令配置IP地址、挂接/etc/fstab指定的文件系统。

#!/bin/sh
ifconfig eth0 192.168.1.104
mount -a

其中:
第一行表示这是一个脚本文件,运行时使用/bin/sh解析。
第三行挂接/etc/fstab文件指定的所有文件系统。
最后还要更改它的属性,使它能够执行:

chmod +x etc/init.d/rcS

3.3、创建etc/fstab文件
内容如下,表示执行“mount -a”命令后将挂接proc、tmpfs文件系统

# device     mount-point     type     options    dump    fsck    order

proc          /proc           proc    defaults     0      0
tmpfs         /tmp            tmpfs   defaults     0      0

/etc/fstab 文件被用来定义文件系统的“静态信息”,这些信息被用来控制mount命令的行为(详细信息参考《嵌入Linux应用开发完全手册》,这里不做详细解释)。

4.构建dev目录

该目录下存放的是设备文件。设备文件是Linux系统中特有的文件类型,在Linux系统下,以文件的方式访问各种外设,即通过读写某个设备文件来操作某个具体硬件。比如通过“/dev/ttySAC0”文件可以操作串口0,通过“/dev/mtdblock1”可以访问MTD设备(NAND Flash、NOR Flash等)的第二个分区。

/dev的创建有3种方法。
(1)手动创建
在制作根文件系统的时候,就在/dev目录下创建需要操作的设备文件比如ttySAC0等。系统挂接根文件系统后,就可以使用/dev目录下的设备文件了。
(2)使用devfs文件系统:这种方法已经过时
(3)使用udev
udev是一个用户程序,它能够根据系统中硬件设别的状态更新设备文件,包括设备文件的创建、删除等。
使用udev机制也不需要在/dev目录下创建设备节点,它需要一些用户程序的支持,并且内核要支持sysfs文件系统。它的操作比较复杂,但是灵活性比较高。
在busybox中,有一个mdev命令,它是udev命令的简化版。

那么我们就使用mdev来创建设备文件

要在内核启动时自动运行mdev,需要修改etc/fstab文件来自动挂载文件系统、修改etc/init.d/rcS文件加入要自动运行的命令。
*etc/fstab的修改:

# device     mount-point     type     options    dump    fsck    order

proc          /proc           proc    defaults     0      0
tmpfs         /tmp            tmpfs   defaults     0      0
sysfs         /sys            sysfs   defaults     0      0
tempfs        /dev            tempfs  defaults     0      0

*etcinit.d/rcS的修改:

#!/bin/sh
ifconfig eth0 192.168.1.104
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

另外,mdev是通过init进程来启动的,在使用mdev构造/dev目录之前,init进程至少要用到的设备文件为/dev/console和/dev/null,所以要建立这两个文件:

mkdir dev
cd dev
sudo mknod console c 5 1
sudo mknod null c 1 3

5.构建其他目录
其他目录可以是空目录,如下:

mkdir proc mnt sys root

现在我们的/work/nfs_root/fs_mini_mdev_new目录下就是一个非常小的根文件系统。开发板可以将它作为网络根文件系统直接启动。如果要烧写进开发板,还要将它制作为一个文件,称为映像文件。

6.制作文件系统映像文件
接下来,我们来制作文件系统的映像文件:
6.1首先需要编译制作jffs2映像文件的工具(具体源码可以自行下载,也可以加我q1126137994问起要)
在我的Linux系统目录/work/tools/mtd-utils-05.07.23.tar.bz2是MTD设备的工具包,编译它生成mkfs.jffs2工具,用它来将一个目录制作成jffs2文件系统映像文件。
这个工具包需要zlib压缩包,先安装zlib。在我的目录/work/GUI/xwindow/X/deps下有zlib源码zlib-1.2.3.tar.gz,执行以下命令进行安***r> cd /work/GUI/xwindow/X/deps
tar xzf zlib-1.2.3.tar.gz
cd zlib-1.2.3
./configure --shared --prefix=/usr
make
sudo make install

然后编译mkfs.jffs2
cd /work/tools
tar xjf mtd-utils-05.07.23.tar.bz2
cd mtd-utils-05.07.23/util
make
sudo make install

6.2制作jffs2映像文件
使用如下命令:
cd /work/nfs_root/fs_mini_dev_new (这是我自己的目录,根据个人的不同进入到不同的目录)
mkfs.jffs2 -n -s 2048 -e 128KiB -d fs_mini_mdev_new -o fs_mini_mdev_newlyy.jffs2

上面-n 表示不要在每个擦除块上都加上清楚标志,-s 2018 表示我们的NAND Flash的一页的大小为2048字节,-e 128KiB 表示一个擦除快大小为128KiB ,-d 表示根文件系统的目录,-o表示输出的文件。

好了,文件系统制作完毕了。下面我们来烧写系统:

nfs 30000000 192.168.1.101:/work/nfs_root/fs_mini_mdev_newlyy.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 260000 $filesize
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=jffs2
nfs 32000000 192.168.1.101:/work/nfs_root/uImage_new
bootm 32000000

串口打印,可以正常启动了,整个系统终于跑起来了,哈哈哈:

完美!!!费了这么大的功夫,终于搞定了这个文件系统的制作,还好没有出现什问题。

注释:
在视频教程中,出现了错误:Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200。

分析这个错误:在内核中搜索字符串:exitcode,通过函数层层调用的分析,最终找到:do_exit(SIGKILL);执行了这个调用,才出现错误代码4,原因是编译内核用的编译工具是eabi接口的,我们需要重新配置内核使用EABI接口:

在内核目录下输入:
make meniconfig
然后依次选择:
Kernel Features —>
[*] Use the ARM EABI to compile the kernel

这下应该就完全没有问题了,内核配置好后,重新编译烧写启动,就OK啦!!!!

想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。