嵌入式爱好者

开机自启中inittab由来

2024-9-27 16:22| 发布者: zhichao| 查看: 19| 评论: 0

类目: T113i系列产品  >  linux     文档编号: 1540

开机启动大致过程

1、uboot环境变量指定传参。

2、内核启动init,得到第一个进程,并转到用户态。

3、init根据配置文件启动系统服务和应用程序。

我们查看uboot环境变量时,可以看到setargs_mmc指定启动方式时,有一条是init=${init},其中${init}中的init是环境变量init=/init

init=/init
setargs_mmc=setenv  bootargs earlycon=${earlycon} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root}  init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${eth0_mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1

由此我们可以得知,在uboot阶段就已经对启动做了传参配置(有些平台是/linuxrc文件)

内核初始化完毕之后运行init进程,init的进程号为1,是所有进程的父进程,其他软件也同时开始运行。转变为用户态init程序。init程序通过/etc/inittab文件进行配置。

我们查看内核源码kernel/linux-5.4/init/main.c,里边有kernel_init函数,这个函数执行时所对应的进程被称为init进程,就是进程1。

在T113中kernel_init调用了kernel_init_freeable,kernel_init_freeable中打开了控制台

        /* Open the /dev/console on the rootfs, this should never fail */
        if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
                pr_err("Warning: unable to open an initial console.\n");

        (void) ksys_dup(0);
        (void) ksys_dup(0);

这里打开了/dev/console文件,并且复制了2次文件描述符,得到了3个文件描述符,分别是0、1、2,就是所谓的标准输入、标准输出、标准错误这3个文件描述符。进程1打开了这3个文件描述符,因此从进程1衍生出来的所有进程,默认都具有这3个文件描述符。

但是init进程想要从内核态转变为用户态,就必须运行一个用户态的应用程序。要运行这个应用程序就必须找到这个应用程序,要找到这个应用程序就必须挂载根文件系统,因为所有的应用程序都在文件系统中。我们可以在源码中找到init进程通过prepare_namespace函数挂载根文件系统

        if (ksys_access((const char __user *)
                        ramdisk_execute_command, 0) != 0) {
                ramdisk_execute_command = NULL;
                prepare_namespace();
        }

接着用到了uboot环境变量传参,指定根文件系统的分区等信息。uboot的传参cmdline中init=/init表示根文件系统的根目录中的 init 程序就是“init应用程序”,函数进行判断和执行。

判断init程序
        if (ramdisk_execute_command) {
                ret = run_init_process(ramdisk_execute_command);
                if (!ret)
                        return 0;
                pr_err("Failed to execute %s (error %d)\n",
                       ramdisk_execute_command, ret);
        }
执行init程序
        if (execute_command) {
                ret = run_init_process(execute_command);
                if (!ret)
                        return 0;
                panic("Requested init %s failed (error %d).",
                      execute_command, ret);
        }

“init进程”从内核态进程转变为用户态进程。转变过程中进程号没有改变(还是进程1)

上述是内核启动init程序的过程,那么init程序又是什么呢?这个二进制文件位于根文件系统,是一个软连接,指向了根文件系统中的/bin/busybox这个命令

root@ok113i:/# ls -l
lrwxrwxrwx  1 root root   11 Sep 11  2024 init -> bin/busybox

前文中我们提到init程序通过/etc/inittab文件进行配置,我们查看配置文件/etc/inittab,这个文件中定义的登记项都是以“:”隔开的四个段。

格式 id:runlevels:action:process

举个栗子:

::sysinit:/etc/init.d/rcS 是我们开机自启脚本启动命令,即:系统初始化时在所有的运行级别运行命令/etc/init.d/rcS

id:它是每个登记项的标识符,用于唯一标识每个登记项,不能重复,指定它在其上运行的终端,例如运行的tty

runlevels:系统的运行级别,表示processaction要在哪个级别下运行,该段中可以定义多个运行级别,各级别之间直接写不用分隔符;如果为空,表示在所有的运行级别运行。Linux的运行级别有:

0:表示关机

1:表示单用户模式,在这个模式中,用户登录不需要密码,默认网卡驱动是不被加载,一些服务不能用。

2:表示多用户模式,NFS服务不开启

3,表示命令行模式

4,这个模式保留未用

5,表示图形用户模式

6,表示重启系统

action:表示对应登记项的process在一定条件下所要执行的动作。举例几个常用的

sysinit 前缀用于指定在系统初始化期间应运行的命令。

null::sysinit: 用于指示这个命令不需要在系统启动时运行,而是在系统运行过程中根据需要运行。这种命令通常用于设置环境变量或者创建符号链接,这些操作在系统启动时可能还不需要,但是在系统运行过程中可能需要。

respawn 不管何时终止都重新启动进程(守护进程)

shutdown 关机时运行的命令

process:表示启动哪个程序或脚本或执行哪个命令等


已解决

未解决

只是看看

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2024-11-22 08:49

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部