热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

根文件系统启动分析及其制作

根文件系统启动分析启动根文件系统过程UBOOT:启动内核内核:启动应用程序Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定

根文件系统启动分析 

启动根文件系统过程
UBOOT:启动内核
内核:启动应用程序

Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动
应用程序的运行是依赖文件系统的。(所以需要挂接根文件系统) 

 

 

执行应用程序在“init_post”这个函数中。 

static int noinline init_post(void)
{free_initmem();unlock_kernel();mark_rodata_ro();system_state
&#61; SYSTEM_RUNNING;numa_default_policy();if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) <0)printk(KERN_WARNING "Warning: unable to open an initial console.\n");(void) sys_dup(0);(void) sys_dup(0);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.*/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");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");panic("No init found. Try passing init&#61; option to kernel.");
}

第一个函数free_initmem怀着好奇心看了看&#xff0c;发现点击进去就见到两个没有定义也查询不到声明的函数&#xff1a;

困扰良久之后&#xff0c;终于找到了问题&#xff0c;这两个函数是uboot中的宏定义&#xff0c;内核中有一些参数或者函数是调用的uboot中的。期间通过谷歌查找这个问题的时候&#xff0c;发现了一个不错的网站&#xff0c;可以查询符号被定义和引用的文件及目录&#xff0c;也是因为这个&#xff0c;发下韦老师课程添加si工程的时候一个纰漏&#xff0c;应该把asm-generic添加进入工程&#xff1a;

看看下面的引用&#xff0c;我们可以发现init/main.c是引用了这个符号的。

&#xff08;网址点击这里&#xff09;

后面的函数先不一一分析&#xff0c;等之后熟悉了的时候&#xff0c;记得回来好好分析一下linux kernel源码&#xff0c;对我们一定是有必要的。

 

上面截图的三个函数&#xff0c;首先是open一个控制台设备&#xff1a;这里以可读可写打开 /dev/console 设备
这三个文件代表标准输入&#xff0c;标准输出&#xff0c;标准错误
这也是之前linux系统编程中说到文件描述符的时候说过的&#xff0c;0&#xff1a;标准输入 1:标准输出 2&#xff1a;标注错误
写程序时经常用到 printf 标准输出,scanf 标准输入,err()标准错误。它们是指 3 个文件。
假设 open(dev/console) 是打开的第 1 个文件。 sys_dup(0)是指复制的意思&#xff0c;
复制后是第 2 个文件&#xff0c;则有了第 1 个文件和第 2 个文件。第 2 个文件也是指向 dev/console
另一个 sys_dup(0) 也是复制文件&#xff0c;则这个是第 3 个文件&#xff0c;也是指向 dev/console 这个文件。

意思是&#xff0c;所有的 printf 打印信息都会从 dev/console 打印出来。
输入时也是从 dev/console 这个文件输入的。想输入错误信息也是从 dev/console 这个文
件输出的。这个文件 dev/console 对应终端。在我们这个例子中 dev/console 对应串口 0.
对于其他设备&#xff0c;这个 dev/console 可能是 键盘液晶。

复制之前随笔一段&#xff1a;

 

2.run_init_process 启动第一个应用程序&#xff1a;
一般来说第一个应用程序运行后&#xff0c;就不会从系统返回了。
这个应用程序&#xff1a;
&#xff08;1&#xff09;要么是 UBOOT 传进来的命令行参数&#xff1a; 如init&#61;linuxrc 这个样子
&#xff08;2&#xff09;要么是 sbin/init,要是 sbin/init 不成功&#xff0c;则还有 /etc/init bin/init,bin/sh

查找 execute_command 符号在哪里被引用&#xff0c;可以借助source insight的relation视图&#xff1a;

 

如果设置了 init&#61; 某个文件&#xff08;例如 linuxrc&#xff09; ,那么这个 execute_command 就等于这个文件(linuxrc). 

 

 

则上面的意思是&#xff1a;如果execute_command 不为NULL&#xff0c;则会用 run_init_process 启动这个应用 程序 execute_command
run_init_process(execute_command);若这个程序没有死掉没有返回&#xff0c;那么函数
run_init_process 就不会返回。我们第一个程序一般来说都是一个死循环。
若没有定义 execute_command&#xff0c;则往下执行&#xff1a;

最后打印&#xff1a;

panic("No init found.  Try passing init&#61; option to kernel.");

 

现在重新下载一下文件系统试试看呢&#xff1a;重新下载fs_mini_yaffs2文件系统

现在进入了文件系统。

可以看到进程为1的应用程序是init&#xff1a;

可见第一个应用程序&#xff1a; init 是内核启动的第一个应用程序。
其中的 -sh 就是当前的应用的程序&#xff0c;就是当前接收的这个串口。输入字符回显字符。就是
sh 这个程序接收这些东西。

busybox的引入&#xff1a;可以看到这些ls cp mkdir等常见命令是busybox的软连接。

所以要知道 init 进制做的哪些事&#xff0c;就得看 busybox 源码。


1.建立 busybox 源码 SI 工程&#xff0c;加入全部代码。

&#xff08;1&#xff09; .猜测 init 程序要做的事情。
UBOOT 的目标是启动内核&#xff0c;内核的目的是启动应用程序&#xff0c;第一个应用程序是/sbin/init&#xff08;或
其他 init&#xff09;&#xff0c;但最终目标还是启动客户的“用户应用程序”。如手机程序&#xff1b;监控程序等。
这样显然会有一个“配置文件”&#xff0c;在这个文件里指定需要执行哪些不同客户的“应用程序”。
init 程序要读取这个&#xff1a;配置文件
再解析这个&#xff1a;配置文件
根据这个“配置文件”&#xff1a;执行客户的用户程序

2.分析 init.c 源码&#xff1a; init_main函数

2).分析 /etc/inittab 配置文件。
busybox 中有 inittab 说明文档。在busybox-1.7.0\busybox-1.7.0\examples目录下有inittab说明。
inittab格式:

:::
是启动不同用户的应用程序。则会有&#xff1a;
指定要执行的程序。
何时执行程序。
id 项&#xff1a; /dev/id 用作终端&#xff08;终端&#xff1a; stdin-printf,stdout-scanf,stderr-err 注&#xff1a;对于console控制台来说&#xff0c;它的输入是我用户层的输出&#xff0c;所以&#xff0c;stdin——》printf&#xff09;
会加上一个 /dev 前缀。作为“控制终端”&#xff08;controlling tty&#xff09;。
id 可以省略。
runlevels 项&#xff1a;
完全可以忽略掉。
action 项&#xff1a;
指示程序何时执行。
process 项&#xff1a;
是应用程序或脚本。

终于看到数据结构中讲的linux内核链表了。。。可以回过去看看这个思路。

 

/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL,
"reboot", "");
这里id为空&#xff0c; runlevels 忽略。 action是“CTRLALTDEL” ;应用程序是“reboot”。
&#xff1a;&#xff1a; ctrlaltdel:reboot
/* Umount all filesystems on halt/reboot */ 当关闭或重启系统时卸载所有的文件系统
new_init_action(SHUTDOWN,
"umount -a -r", "");
::shutdown:umount
-a -r
/* Swapoff on halt/reboot */
当PC机有资源不够用时&#xff0c;会将当前内存中的某些应用程序置换到硬盘上。嵌入式中不同这项。
if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
/* Prepare to restart init when a HUP is received */
new_init_action(RESTART,
"init", "");
::restart:init
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell,
"");
::askfirst:
-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
tty2::askfirst:
-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
tty3::askfirst:
-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
tty4::askfirst:
-/bin/sh
/* sysinit */
new_init_action(SYSINIT, INIT_SCRIPT,
"");
::sysinit:
/etc/init.d/rcS

 5.可见&#xff0c; parse_ininttab 解析这个 inittab 时&#xff0c;先打开 /etc/inittab 。再创建很多结构放到链表中。
 

到这里我发现&#xff0c;分析代码的工作靠写博客是不行&#xff0c;还是得自己去分析理解别人的执行流程&#xff0c;所以&#xff0c;只听课不自己去分析&#xff0c;是学不好的。

最小的根文件系统需要的项&#xff1a;&#xff08;init 进程需要&#xff09;
1.打开终端&#xff1a; /dev/console&#xff0c; /dev/NULL
不设置 inittab 格式中的 id(标准输入、输出和标准错误)时&#xff0c;就定位到 /dev/NULL 中去&#xff0c;如果设置了inittab&#xff0c;就定位到/dev/console中去。
2.init 程序本身就是 busybox .&#xff08;原因见下&#xff0c;busybox的配置和编译&#xff09;
3.需要配置文件&#xff1a; /etc/inittab
4.配置文件若指定了某些应用程序或执行脚本--这些必须存在&#xff0c;不存在会有默认的。
5.应用程序需要的库&#xff08;fopenfwrite 等函数需要&#xff0c;c库&#xff0c;glibc&#xff09; 。


Makefile 中的交叉编译的指定。在 linux 中一般交叉编译工具的指定以 CROSS 开头。
交叉编译器可以在 Makefile 中直接定义。没法在配置图形项(make menuconfig)
定义的情况下&#xff0c;就在 Makefile 中直接定义。直接写成&#xff1a;加上前缀 arm-linux-
首先是官网下载busybox&#xff0c;解压缩&#xff0c;执行make menuconfig报错&#xff0c;百度解决问题&#xff1a;

进入主界面&#xff1a;

最新版的 busybox 可以在上面的图形界面配置交叉编译器。

这里在韦老师提供的busybox1.7.0&#xff0c;而我用的ubuntu16.04&#xff0c;编译就是有错误&#xff0c;百度必应谷歌都无果之后&#xff0c;选择官网下载了一个最新的busybox1.28.2&#xff0c;这样make menuconfig和make都一次性成功&#xff0c;下载地址&#xff1a;https://busybox.net/downloads/

 困扰了好久&#xff0c;最后还是找到一个解决办法&#xff0c;不然就只有回退ubuntu版本这个办法了&#xff0c;毕竟busybox不是自己写的啊。

下面以韦老师视频老版本的为例&#xff0c;新版本的1.28.2默认配置即可&#xff0c;这些常用配置早已默认给我们配置好了&#xff1a;

这是将 BusyBox 编译成一个静态的程序时&#xff0c;那么那些 C 库 也不需要了。除非用户的应用
程序指定需要库。这里不选表示用动态的。 C 库有两种&#xff0c; glibc uclibc&#xff0c;如果是用 glibc
态编译时&#xff0c;会有提示一个警告信息&#xff0c;可能在以后使用时出问题&#xff0c;所以这里不用静态编译。而用动态链接。
 

其实老版本的我也就手动配置了一个Tab complete&#xff0c;其他都是使用的默认&#xff0c;只是这个老版本毕竟不能适应新的ubuntu了。

/*

*更正&#xff1a;之前的老版本busybox报错&#xff0c;因为我少指定了一个东西&#xff0c;就是交叉编译器&#xff0c;需要在Makefile中增加&#xff1a;

*

*这样之后就不报错了&#xff0c;也就是老版本也可以使用&#xff0c;新版本自然为我们做的更多&#xff0c;肯定更好使用才会更新嘛。

*为什么会发现&#xff1f;因为我发现没有谷歌百度到这个问题或者谷歌百度的问题还是没有解决&#xff0c;还有就是学习群和论坛都没有 

*人提起这个问题&#xff0c;所以我想可能是我少了什么操作&#xff0c;果然检查一下&#xff0c;发下少了配置项。

*/

 

注意上方&#xff0c;linuxrc也是一个busybox的软链接文件。linuxrc你是否眼熟呢&#xff1f;对&#xff0c;它就是uboot传给内核的参数 init&#61;/linuxrc,

所以&#xff0c;之前说了&#xff0c;内核启动的第一个应用程序init&#xff0c;而init是执行linuxrc&#xff0c;而linuxrc是busybox的链接文件&#xff0c;所以init程序就等价于busybox应用程序。

 

first_fs创建 dev 目录&#xff0c;并创建这两个 字符文件设备。

mknod 创建 console &#xff0c; c 表示字符型设备&#xff0c; 5 是主设备号&#xff0c; 1 是次设备号。

      定位到“/dev/console”里面去。

这里的fs_mini目录是韦老师书上写的&#xff0c;而我们这里创建的是first_fs目录下的lib。不可照搬&#xff1a;

 

 

 

这里韦老师加上x&#xff08;即可执行权限&#xff09;其实是多余的&#xff0c;因为这里mkyaffs2image已经具有可执行权限了&#xff1a;

上面mkyaffs2image的usage有用法说明。

 

这样就把first_fs中的busybox制作成了我们的first_fs.yaffs2文件系统了。

 NOTE&#xff1a;

在建立glibc库文件的时候&#xff0c;一定要加上 -d选项

cp *.so* /work/nfs_root/first_fs/lib -d

不加-d选项制作的yaffs2文件系统会大一倍多。

现在跟文件系统还需要改进&#xff1a;

5.完善根文件系统。
.挂载虚拟的根文件系统。

 

 在内核中&#xff0c;当前有哪些应用程序在跑&#xff0c;这些信息如何收集。是内核提供了一个虚拟的文件系统&#xff0c;叫 proc 文件系统。将这个内核提供的虚拟文件系统 proc 挂载一下。
所以&#xff0c;先是在文件系统上mkdir 然后mount挂载。

 

 

这里etc/fstab需要自己创建&#xff0c;按照上面的格式。etc/fstab格式可以在busybox目下搜索查看。mount -a之后&#xff0c;我们不用手动挂载就可以识别ps命令了&#xff1a;

 

在busybox目录下搜素mdev&#xff0c;有说明文档。这主要是学习韦老师的方法&#xff0c;他是怎么去接触学习这个。

 

 

 

 在没有使用mdev之前&#xff0c;ls dev只有2个&#xff0c;console和null&#xff0c;使用了之后&#xff0c;就一大堆设备了。

 

 

制作jaffs2文件系统具体步骤参考韦老师的书籍&#xff0c;这个主要用在nor flash上。

 

最后说一下网络文件系统&#xff1a;

网络文件系统。这个文件系统放在服务器上&#xff0c;内核启动时识别服务器上这个目录&#xff0c;将这个
目录当成 根文件系统。
这样便不需要每次烧写。

 NFS还是比较重要和有用的&#xff0c;也方便调试&#xff0c;可是我现在的设备不支持三网ping通&#xff08;或者说很难支持&#xff09;&#xff0c;之后如果需要&#xff0c;回看这个一章节韦老师的视频同时参考网络教程。



推荐阅读
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • java io换行符_Java IO:为什么从stdin读取时,换行符的数字表示出现在控制台上?...
    只是为了更好地理解我在讲座中听到的内容(关于Java输入和输出流),我自己做了这个小程序:publicstaticvoidmain(String[]args)thro ... [详细]
  • 刚开始crousera上学习<algorithmspart1>但对JAVA实在是不熟。******************************************** ... [详细]
  • 一文了解Python collections模块中的deque用法[python头条资讯]
    Python中文网有大量免费的Python入门教程,欢迎大家来学习。collections是Python内建的一个集合模块,deque是双边队列,具有队列和栈的性质,在list的基 ... [详细]
  • 796.[APIO2012]派遣在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为Master。 ... [详细]
  • 题目描述Takuru是一名情报强者,所以他想利用他强大的情报搜集能力来当中间商赚差价。Takuru的计划是让Hinae帮他去市场上买一个商品,然后再以另一个价格卖掉它。Takur ... [详细]
  • DescriptionclickmeSolution套路的状压期望DP题。。。考虑倒退期望:设fi,jrolepresentationstyleposi ... [详细]
  • P113:集成日志组件 logback 2彩色日志
    第二步,将控制台的日志改成彩色日志,便于查看修改logback.xml文件。 ... [详细]
  • 开发笔记:城市建设
    本文由编程笔记#小编为大家整理,主要介绍了城市建设相关的知识,希望对你有一定的参考价值。本文涉及:cdq分治、MST一道十分精妙的cdq分 ... [详细]
  • 题面传送门Solution看到什么最大值最小肯定二分啊。check直接跑一个二分图匹配就好了。orzztl!!!代码实现*mail:mle ... [详细]
author-avatar
史三万岁_710
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有