1_5.4.2_根文件系统_构建根文件系统之init进程分析_P

发布者:创新火箭最新更新时间:2021-08-20 来源: eefocus关键字:根文件系统  init 手机看文章 扫描二维码
随时随地手机看文章

想知道这个这个文件系统里面有哪些东西,我们需要跟着init进程继续分析,看这个进程需要哪些东西。


在根文件系统里面有很多命令,比如cp,ls等等,这些命令也就相对一个应用程序,这些命令可能有成千上百种。


对于这么多的命令,在嵌入式领域中,我们使用busybox,它是ls,cp,cd这些命令的组合,我们编译busybox的时候得到一个应用程序叫busybox,我们执行的ls,cp这些指令,实际上执行的都是这些指令到busybox的链接,比如在shell中输入ls,其实就是执行了busybox ls。


可以看到,ls和copy都是到busybox的链接。

在这里插入图片描述

使用ls和busybox ls是一样的。

在这里插入图片描述

事实上,在嵌入式系统,这个/sbin/init也是到busybox的链接。

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

所以说,我们想要确定这个init进程做了哪些事情,就需要找到busybox的源码,来分析一下。


找到配套的busybox,解压并用SI创建一个工程来分析一下。

在这里插入图片描述

在SI中导入busybox源码,可以看到文件中有一个cp.c,cp.c中有一个cp_main函数,可以推测,使用cp命令就是调用了cp_main函数。

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

同样,也有一个init.c文件,init.c文件中有一个init_main函数。

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

我们需要分一下这个init_main。


先猜测一下,init程序会做什么事情呢?


答:回顾一下,u-boot的目的是启动内核,内核的目的是启动应用程序。


内核怎么启动应用程序呢?


答:内核首先启动了init进程,它位于/sbin/init或其他,由这个进程来启动其他的应用程序。


不同的客户要启动的应用程序各不相同,我们怎么知道要启动哪些应用程序呢?


答:应该还要有一个配置文件,这个配置文件决定了后续还要启动哪些应用程序。


所以,init进程至少要做以下三件事:


读取配置文件;

解析配置文件;

执行用户程序。

阅读源码看下是不是这样。


打开init.c,查看init_main函数,前面是设置信号,先不管。

在这里插入图片描述

继续向下看,初始化控制台(之前打开了控制台,这里初始化一下)等等。

在这里插入图片描述

接着向下看,我们启动内核时没有传入任何参数,所以argc小于1,执行parse_inittab,从名字就可以看出来,这个是解析init table。

在这里插入图片描述

打开parse_inittab,可以看到首先是打开一个文件/etc/inittab,显然这个就是配置文件,在linux系统中,配置文件一般都放在etc目录下。打开配置文件后面就是解析了。

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

解析之前,我们先看一下/etc/inittab,打开/etc/inittab,可以看到inittab的格式。

在这里插入图片描述

这些配置文件的目的是启动不同的应用程序,根据这个目的,我们可以猜测一下配置文件里面肯定会有:


指定执行哪些应用程序;

指定何时执行这些应用程序。

根据文档说明可以知道,id项会被加上/dev/,也就是/dev/id,用作控制终端(也就是我们的标准输入,标准输出,标准错误,stdin,stdout,stderr : printf,scanf,err)。

在这里插入图片描述

然后是runlevels,这里说可以完全忽略掉。

在这里插入图片描述

然后是action,指示何时执行,process,指示执行的应用程序或脚本。红框是action的取值范围。

在这里插入图片描述

继续分析源码,可以看到如果没有这个文件,那么就执行默认项,否则解析配置文件。

在这里插入图片描述

下面是对配置文件的一些解析,如果是#开头的就忽略掉。

在这里插入图片描述

然后id是加上/dev/前缀,解析完最终要调用new_init_action。显然,要了解这些配置项怎么起作用,需要来解析一下这个new_init_action。

在这里插入图片描述

以默认配置(即fopen INITTAB失败时)的new_init_action为例,来解析一下。


new_init_action(ASKFIRST, bb_default_login_shell, VC_2);

在这里插入图片描述

在源码里面搜索一下bb_default_login_shell,可以看到,就是"-/bin/sh",VC_2就是"/dev/tty2"。

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

所以


new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");


就等于


new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");


从函数定义可以看出,action(执行时机)是ASKFIRST,command(应用程序或脚本)是-/bin/sh,id(终端)是/dev/tty2。

在这里插入图片描述

接着分析new_init_action,可以看到有一个init_action_list,可以猜测这是一个初始化动作的链表。

在这里插入图片描述

查看init_action_list的定义,可以看到init_action_list是一个指向init_action结构体的指针。

在这里插入图片描述

可以猜测,这个new_init_action函数的作用:


创建一个init_action结构,并填充;

把这个结构放入init_action_list链表。

在这里插入图片描述

现在,假设没有配置文件,根据默认的配置来反推出默认的配置文件,看看它是什么内容。

在这里插入图片描述

其中,773行可以省略,这是因为在PC上,如果系统资源不足,就会把某些不用的进程释放到硬盘中去,将内存空间空出来,但是在嵌入式系统中一般不会这样做,所以if不会进去。

/* Swapoff on halt/reboot */

if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");


最终,反推出来的默认的配置文件如下:

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

那么,构建了这样一个链表,之后要怎么使用呢?继续往下看。


构建链表之后就是执行,先执行SYSINIT这一类的动作,然后是WAIT,然后是ONCE。

在这里插入图片描述

再接下来是一个死循环。

在这里插入图片描述

前面说过,action决定了执行时机,它的取值范围有八个,但是inittab中没有说明这些值代表什么意思,我们结合代码分析一下。

在这里插入图片描述

首先分析一下run_action函数,可以看到,上面说的8个action在这里都有对应的执行程序。

在这里插入图片描述

首先看一下SYSINIT,它调用了两个函数waitfor和delete_init_action,这两个函数的作用分别是:


执行应用程序,并等待它执行完毕(waitfor);

在链表中删除执行完的init程序(delete_init_action)。

在这里插入图片描述

waitfor的源码如下,可以看到先执行run(a),该函数会创建process子进程,然后在while循环中waitpid,等待a执行完毕。

在这里插入图片描述

delete_init_action则是在链表中删除执行完的init程序。

在这里插入图片描述

再看一下run函数,函数前面执行了很多系统调用,最后是一个BB_EXECVP,它也是一个系统调用,用来执行子进程。

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

所以,SYSINIT的功能就是系统初始化,在系统最开始的时候执行,并且执行的时候,系统会等待它执行完毕,执行完毕后就会从链表删除。

然后是WAIT,它的作用和SYSINIT类似,只是它是在SYSINIT之后执行,先执行SYSINIT然后再执行WAIT。


然后是ONCE,可以看到它和SYSINIT也是类似的,只是系统不会等待它执行完毕,同样是执行一次后从链表删除。

在这里插入图片描述

然后是RESPAWN和ASKFIRST,只有在pid等于0时才执行。


系统一开始的时候,pid都是0,只有开始执行该进程后,系统才会给它分配一个非0的pid。

在这里插入图片描述

可以看到,在init_main的while循环中,会不断的执行RESPAWN和ASKFIRST,然后在它们执行完毕后再将它们的pid清零,这样它们才可以再次执行。

在这里插入图片描述

那么,RESPAWN和ASKFIRST有什么区别呢?


这就要从run函数来分析了,在run函数中,当action包含ASKFIRST时,在执行该process前,会先在标准输出输出一条询问信息,此时只有输入回车才会继续向下运行,

在这里插入图片描述

这就是RESPAWN和ASKFIRST的差别,ASKFIRST从名字也可以看出来,在执行前先询问一下。


八个action,我们分析了SYSINIT,WAIT,ONCE,RESPAWN,ASKFIRST五个,还有restart,ctrlaltdel,shutdown是做什么用的呢?


在init_main函数的开头,我们看到有一些信号量,这些信号量调用的函数里面,就会用到这些action。

在这里插入图片描述

ctrlaltdel_signal就会来执行ctrlaltdel这一类的函数,restart和shutdown也是类似的。

在这里插入图片描述

回顾一下,init_main函数至少需要这三项:


打开终端/dev/console;(还需要一个/dev/null)

需要配置文件/etc/inittab;

配置文件里指定的应用程序;

需要注意的是,如果在配置文件中不设置id的话,那么该进程的标准输入,标准输出,标准错误,就都定义到/dev/null里去。


假设我们写一个简单的应用程序,这些函数都不是它自己实现的,而是C库实现的,所以还需要一个库文件。


int main(void)

{

printf("hello, world!n"); //C库

fopen(); //C库

fwrite(); //C库

fclose(); //C库

}


另外,init程序本身也是busybox,所以一个最小的根文件系统,需要以下五种组成:


/dev/console和/dev/null;

init应用程序 ==> busybox;

配置文件/etc/inittab;

配置文件指定的应用程序;

C库;

构建这五种东西,就可以构建出一个根文件系统了,下一节我们就来创建它。

关键字:根文件系统  init 引用地址:1_5.4.2_根文件系统_构建根文件系统之init进程分析_P

上一篇:1_5.4.1_根文件系统_构建根文件系统之启动第1个程序_P
下一篇:1_5.4.3_根文件系统_构建根文件系统之busybox_P

推荐阅读最新更新时间:2024-10-25 08:32

1_5.4.2_文件系统_构建文件系统init进程分析_P
想知道这个这个文件系统里面有哪些东西,我们需要跟着init进程继续分析,看这个进程需要哪些东西。 在根文件系统里面有很多命令,比如cp,ls等等,这些命令也就相对一个应用程序,这些命令可能有成千上百种。 对于这么多的命令,在嵌入式领域中,我们使用busybox,它是ls,cp,cd这些命令的组合,我们编译busybox的时候得到一个应用程序叫busybox,我们执行的ls,cp这些指令,实际上执行的都是这些指令到busybox的链接,比如在shell中输入ls,其实就是执行了busybox ls。 可以看到,ls和copy都是到busybox的链接。 使用ls和busybox ls是一样的。 事实上,在嵌入式系
[单片机]
1_5.4.2_<font color='red'>根</font><font color='red'>文件系统</font>_构建<font color='red'>根</font><font color='red'>文件系统</font>之<font color='red'>init</font><font color='red'>进程</font><font color='red'>分析</font>_P
构建文件系统(2)Busybox init 进程
讲init进程的启动过程从/etc/inittab出发。 内核启动init进程时已经打开/dev/console设备作为控制台,一般情况下Busybox init程序就使用/dev/console, 如果内核启动init进程的同时设置了环境变量CONSOLE或console,则使用环境变量所指定的设备。 1、/etc/inittab文件的相关文档和示例代码都在Busybox 的examples/inittab文件中。 vi examples/inittab 内容如下(红色字为格式重要部分): # /etc/inittab init(8) configuration for BusyBox # # Copyright (C) 199
[单片机]
ARM-Linux移植之(三)——init进程启动流程分析
我们通常使用Busybox来构建根文件系统的必要的应用程序。Busybox通过传入的参数来决定执行何种操作。当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分析这个函数,看init进程究竟是怎样一个流程。我分析的Busybox源码是1.7.0版本的,其他版本会略有不同。部分代码省略我们只看关键性代码。 首先看init_main函数 int init_main(int argc, char **argv); int init_main(int argc, char **argv) { …………………………….. …………………………….. //初始化控制台 console_i
[单片机]
OK6410A 开发板 (八) 19 linux-5.11 OK6410A start_kernel 功能角度 第三阶段之init进程
arch_call_rest_init rest_init pid = kernel_thread(kernel_init, NULL, CLONE_FS); pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); cpu_startup_entry(CPUHP_ONLINE); 内核进程1的创建过程 arm linux 内核源码剖析.pdf P407 内核进程1开始运行的时刻 kthreadd - schedule - __schedule - context_switch 此函数执行后, kernel_init 开始运行 内核进程1
[单片机]
init 进程和inittab 引导指令
init 进程是系统所有进程的起点,内核在完成内核引导以后,即在本线程(进程)空间内加载init 程序,它的进程号是1。init 程序读取/etc/inittab 文件作为其行为指针,根据initab 描述文件的内容建立相应的进程。initab 文件中描述了系统默认的运行级别,运行rc 启动脚本,进行用户的登录,X Window 登录等工作。Initab 文件的主体部分如下: view plain copy print ? # Default runlevel. The runlevels used by RHS are: # 0 - halt (Do NOT set initdefault to this
[单片机]
Linux init进程详解(ZT)
Linux init进程详解  一、什么是INIT:   init是Linux系统操作中不可缺少的程序之一。   所谓的init进程,它是一个由内核启动的用户级进程。   内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。   内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。   二、运行级别   那么,到底什么是运行级呢?   简单的说,运行
[嵌入式]
3.5文件系统的制作
根文件系统其实包含两个含义:1.是根。2.是文件系统。 根:就是第一个的意思。必须有的。 文件系统:就是我们在编译linux内核看到的: 上面的目录和文件就是文件系统的。 接下来我们就来创建文件系统: 创建目录: 1.2.创建设备文件: 这里我们需要下面文件: 1.3.加入配置文件: 把它解压开,在把它的内容拷贝到/rootfs/etc: 接着是添加内核模块: 1.4.添加内核模块: 首先是编译内核模块: Make modules ARCH=arm CROSS_COMPILE=arm-linux- 这个编译的过程会有点久。 最后编译好了内核模块,接下来就是拷贝到我们的
[单片机]
3.5<font color='red'>根</font><font color='red'>文件系统</font>的制作
使用busybox构建yaffs2文件系统(前言)
(一) 根文件系统启动过程 由于默认的内核命令行上有init=/linuxrc, 因此,在文件系统被挂载后,运行的第一个程序是根目录下的linuxrc。 这是一个指向/bin/busybox的链接,也就是说,系统起来后运行的第一个程序也就是busybox本身。 这种情况下,busybox首先将试图解析/etc/inittab来获取进一步的初始化配置信息(参考busybox源代码init/init.c中的parse_inittab()函数)。如果根文件目录中并没有/etc/inittab这个配置文件,根据busybox的逻辑,它将生成默认的配置 /etc/init.d/rcS 这个开机脚本. rcS这个脚本要完成一些必要目录的挂载:
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved