制作文件系统

本文详细介绍了Linux根文件系统、内核参数配置以及BusyBox的编译与初始化过程。主要内容包括BootLoader中的bootargs设置、Linux内核的编译与配置,特别是根文件系统的组成和作用。此外,还讲解了如何定制初始化脚本rcS,以及通过 BusyBox 编译生成根文件系统所需的基本动态库和配置文件。最后,文章提到了烧录流程,涉及UBOOT、内核镜像、设备树和根文件系统的烧写。
摘要由CSDN通过智能技术生成

uboot - kernel - 根文件系统 - 应用

根文件系统,它是内核启动时所挂载(mount)的第一个文件系统内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行

1BootLoader

需要需要修改的:

bootcmd
网络参数
bootargs 内核参数

1.1 bootargs 内核参数

语法: < name > = < value >
常见:
在这里插入图片描述

配置Linux内核

在这里插入图片描述

  1. 从官网下载的源码解压之后有这些文件;
    在这里插入图片描述
  2. 这里面都是一些Linux支持的官方开发板
    在这里插入图片描述
  3. 在arm/configs中是一些已经准备好的配置;这些配置是对内核的设置,什么编译进去内核等等

在这里插入图片描述
5. Linux-4.9.88$ vi Makefile ,对CROSS_COMPILE和ARCH进行配置
6. 图形化界面make menuconfig配置也就是以上步骤的图形化,最后都会生成一个隐藏的.config文件;用于编译镜像内核
7. 进行配置,make config。这个是使用make menuconfig配置的内容;也可以使用make 100ask_imx6ull_defconfig,使用别人写好的配置;这些对镜像没有影响,但是影响设备树
8. 编译镜像文件,make zImage -j6
9. 编译内核模块,make modules -j4
10. 编译设备树,make dtbs。
11.实际上生成的 zImage 是一个通用的内核文件,而dtbs可以表示特定的平台了。

在这里插入图片描述
最后生成如图,可以看到设备树和你用的配置相关。

3 根文件系统

3.1 根文件系统

1、Linux启动后;其他文件系统挂载的挂载点(也是一个目录)。
2、这是因为kernel的VFS机制支持很多文件系统。

3.2 根文件系统的组成

1、根文件存在的位置必须能让内核读取;内核必须支持根文件所在介质的驱动;
2、init=/linuxrc 指定了Linux第一个用户程序,该程序存在在根文件内;
3、基本的目录和配置文件。
在这里插入图片描述
举个栗子:
在启动内核之前,修改一下bootargs

setenv bootargs 'boot=/dev/nfs nfs=192.168.5.11:/home/lcx/mini_Linux_system ip=192.168.5.9 init=/linuxrc console=ttySAC0,115200'

在这里插入图片描述
由于已经实现使用busybox写好了linuxrc 所以能正常启动。
如果报错去/linux-4.xx.xx 下查看Documentation/init.r=txt

4 生成根文件

4.1 根文件系统定制 于busybox编译之前完成的

在这里插入图片描述
在这里插入图片描述

linuxrc是初始化程序,是一个链接
lrwxrwxrwx 1 lcx lcx   11 Oct 11 08:13 linuxrc -> bin/busybox
本质上busybox的elf文件,一个二进制文件。

4.1.1 理解初始化函数(inittab和rcS)

/home/lcx/source/busybox-1.27.0/init/init.c

--------------
/* Figure out where the default console should be */
        console_init();
        set_sane_term();
        xchdir("/");
        setsid();
....
parse_inittab(); //调用配置文件


static void parse_inittab(void)
{
#if ENABLE_FEATURE_USE_INITTAB
        char *token[4];
        parser_t *parser = config_open2("/etc/inittab", fopen_for_read);

        if (parser == NULL)
#endif
        {
                /* No inittab file - set up some default behavior */
                /* Sysinit */
                new_init_action(SYSINIT, INIT_SCRIPT, "");
                /* Askfirst shell on tty1-4 */
                new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
                new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
                new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
                new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
                /* Reboot on Ctrl-Alt-Del */
                new_init_action(CTRLALTDEL, "reboot", "");
                /* Umount all filesystems on halt/reboot */
                new_init_action(SHUTDOWN, "umount -a -r", "");
                /* Swapoff on halt/reboot */
                new_init_action(SHUTDOWN, "swapoff -a", "");
                /* Restart init when a QUIT is received */
                new_init_action(RESTART, "init", "");
                return;
        }

#if ENABLE_FEATURE_USE_INITTAB
        /* optional_tty:ignored_runlevel:action:command
         * Delims are not to be collapsed and need exactly 4 tokens
         */
        while (config_read(parser, token, 4, 0, "#:",
                                PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
                                /* order must correspond to SYSINIT..RESTART constants */
               //支持的八种动作类型
                static const char actions[] ALIGN1 =
                        "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
                        "ctrlaltdel\0""shutdown\0""restart\0";
                int action;
                char *tty = token[0];

                if (!token[3]) /* less than 4 tokens */
                        goto bad_entry;
                action = index_in_strings(actions, token[2]);
                if (action < 0 || !token[3][0]) /* token[3]: command */
                        goto bad_entry;
                /* turn .*TTY -> /dev/TTY */
                if (tty[0]) {
                        tty = concat_path_file("/dev/", skip_dev_pfx(tty));
                }
                new_init_action(1 << action, token[3], tty);
                if (tty[0])
                        free(tty);
                continue;
 bad_entry:
                message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d",
                                parser->lineno);
        }
        config_close(parser);
#endif
}

/如果有配置文件执行默认,其中最重要的是系统吃实话rcS
#ifndef INIT_SCRIPT
#define INIT_SCRIPT  "/etc/init.d/rcS"
#endif

该init.c主要是/etc/inittab进行解析,其中也会调用一些配置;没有配置就调用默认。
parse_inittab就是解析/etc/inittab;new_init_action复制完成一些配置;

* Now run everything that needs to be run */
        /* First run the sysinit command */
        run_actions(SYSINIT);
        check_delayed_sigs();
        /* Next run anything that wants to block */
        run_actions(WAIT);
        check_delayed_sigs();
        /* Next run anything to be run only once */
        run_actions(ONCE);

之后在由run_actions运行。

总结:
1、初始化究竟完成了什么是由parse_inittab()调用配置/etc/inittab;
2、默认/etc/inittab为 INIT_SCRIPT “/etc/init.d/rcS”,由busybox创建的。

4.1.2 配置文件inittab:

./home/lcx/source/busybox-1.27.0/examples/inittab
./home/lcx/source/busybox-1.27.0/examples/bootfloppy/etc/inittab

./home/lcx/source/busybox-1.27.0/examples/bootfloppy/etc/inittab
::sysinit:/etc/init.d/rcS  用的也是rcS脚本
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r

用的也是rcS脚本

总结如何定制初始化过程?
1、修改自己的inittab文件,让init.c中的parse_inittab()解析我们的配置文件从而执行不同的命令动作;
2、不用inittab文件,修改启动脚本INIT_SCRIPT 也就是/etc/init.d/rcS

4.1.3 编写rcS定制启动过程(重要)

#! /bin/sh

for scrpit in /etc/init.d/S[0-9][0-9]*
do
   if [ -x $script ];then
        ehco"rcS:$scrpit"
        /bin/sh -c $scrpit
   fi
done

echo "-----rcS endl-----"

通过for的循环去读取脚本文件,然后执行;
修改rcS负责启动其他脚本,其他脚本负责启动服务

4.1.4 总结

1、启动初始函数init() —— 读取inittab中的动作 —— 没有inittab启用/etc/init.d/rcS —— 应用
2、所以可以修改rcS(不仅仅是脚本也可以是C)定制系统。


4.2 busybox编译配置生成过程

在ubuntu上对busybox进行交叉编译,以生成可以执行的二进制文件

  1. 下载解压;
  2. 修改Makefile
ARCH = arm
CROSS_COMPILE = arm-linux-gnueabi-
  1. make deconfig
  2. 或者启动图形化直接make menuconfig;注意需要编译为静态库;并在busybox setting中设置交叉编译器前缀
    在这里插入图片描述
  3. make && make install
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
一些常用命令软链接等等。

以上是在busybox中的配置


以下是对根文件系统中的文件配置

5 完善根文件系统 于busybox编译完成之后

5.1 解决动态库依赖

在这里插入图片描述
补全目录,并查看所依赖的动态库。
注意:由于是为ARM服务的,除了busybox之外还需要arm的库;这个库就是安装交叉编译器的库

查看动态库依赖
readelf -d busybox|grep NEEDED

ld-linux-armhf.so.3 ——> 实现动态库的链接
c库的选择:glibc ——> 更全面完善

echo 'main(){}'| arm-linux-gnueabihf-gcc -E -v -
用于查看当前编译模式下头文件和库文件的路径

进入/usr/arm-linux-gnueabihf中查看库文件

lcx@ubuntu:/usr/arm-linux-gnueabihf$ find -name libc.so.6
./lib/libc.so.6
lcx@ubuntu:/usr/arm-linux-gnueabihf$ find -name libm.so.6
./lib/libm.so.6
lcx@ubuntu:/usr/arm-linux-gnueabihf$ find -name ld-linux-armhf.so.3
./lib/ld-linux-armhf.so.3

或者直接拷了整个lib过去
将库拷贝到mini
将所有库拷贝到系统中。

5.2 补充配置和设备文件

mkdir dev
cd dev
mknod -m 666 tty1 c 4 1
mknod -m 666 tty2 c 4 2
mknod -m 666 tty3 c 4 3
mknod -m 666 tty4 c 4 4
mknod -m 666 console c 5 1
mknod -m 666 null c 1 3

配置文件:
将实例文件中的etc全部拷贝至根文件系统的etc中。
注意,这个inittab和init.d就是上面的rcS
在这里插入图片描述
到此为止,根文件系统已经完成,可以挂载使用


烧录过程(以MfgTool为例)

  1. BootStrap 阶段
打开mfgtool2-yocto-mx-evk-emmc.vbs 
脚本会根据芯片型号选择怎么烧写,通过USB OTG 向DDR中下载uboot 
  1. 启动Linux系统后才是烧写uboot、zImage、.dtb(设备树)和根文件系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值