历史上的今天
返回首页

历史上的今天

今天是:2025年08月20日(星期三)

正在发生

2021年08月20日 | 1_5.3.4_内核配置裁剪及启动流程_内核启动流程分析之内核启

2021-08-20 来源:eefocus

内核的最终目的:运行应用程序(在根文件系统里面,需要挂接根文件系统)。


一下运行应用程序前要做什么事情?


1.处理u-boot传入的参数

从第一个文件(arch/arm/kernel/head.S)开始分析。


查找head.S,发现还有一个bootcompressed目录下的head.S文件,这是什么文件呢?

在这里插入图片描述

我们编译出来的内核可能会很大,有没有办法让它变小一点呢?


答:有的,使用压缩将文件变小。


在压缩后的文件前面加上一个自解压代码。本来代码是从原来的文件开始运行,现在使用压缩后的文件,代码就从自解压代码开始运行。自解压代码会将后面的压缩文件解压出来,然后再从解压缩后的代码开始运行。可以看出,这是一种时间换空间的方法。


打开kerenl中的head.S文件,从上往下看。


开始这边会检查处理器ID,查看内核是否支持这种处理器,如果不支持就跳转到error_p中去,支持就继续往下执行。

在这里插入图片描述

然后还要检查机器ID,这个机器ID是由u-boot在启动内核时传入的。

在这里插入图片描述

在启动内核时,uboot将机器ID传过来,对于2440的开发板,启动ID是MACH_TYPE_S3C2440,也就是362。

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

点入__lookup_machine_type查看具体的实现过程,其中r4的点(".")是虚拟地址。

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

其中,__arch_info_begin和__arch_info_end是在链接脚本中定义的,可以看到,他们分别表示(.arch.info.init)段的起始地址和结束地址,是从(0xc0000000) + 0x00008000开始增长的,所以他们也是虚拟地址。

在这里插入图片描述

那么,(.arch.info.init)段中包含了什么?


使用grep “(.arch.info.init)” * -nR搜索,可以看到在include/asm-arm/mach/arch.h文件下有定义。

在这里插入图片描述

打开该文件查看,可以看到这是一个宏定义,传入_type和_name,然后会定义一个属性为(".arch.info.init")段的结构体。其中 __uesd的意思是告诉编译器,这一段有用,这样即使这一段没有用到,编译器也不会报警告 。

在这里插入图片描述

在archarmmach-s3c2440的mach-smdk2440.c文件中有如下定义:

在这里插入图片描述

将它们综合起来就是定义了一个只读的静态machine_desc结构体,结构体名字为__mach_desc_S3C2440,然后是它的一些参数。

在这里插入图片描述

查看machine_desc结构体的定义,可以看到nr,这个就是机器ID,还可以看到boot_params,这是启动参数的入口地址,都是和机器相关的描述。显然,内核支持多少单板,里面就应该有多少个这样的结构体。

在这里插入图片描述

通过这个结构体,内核的机器ID就和之前的u-boot传入的机器ID联系起来了。2440的机器ID,2410的机器ID还有很多其他的机器ID都存在这里,启动时逐一比较,找到相同的机器ID就说明内核有支持,否则就不支持。


之后就是逐个比较,直到全部比较完或者找到一致的机器ID了, 如果全部找完都没有找到一致的,那么说明不支持,那就让r5等于0,然后退出调用。(blo表示(无符号数)小于跳转)

在这里插入图片描述

接下来是建立列表,为什么要建立列表?


答:我们的SDRAM是从0x30000000开始的,但是链接脚本的起始地址却是(0xc0000000) + 0x00008000,显然,这个地址并不对应一个真实存在的内存,事实上这是一个虚拟地址,所以需要建立一个页表,这个页表会提供给MMU使用,用于虚拟地址和物理地址之间的转换。

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

接着向下看,通过注释可以知道,后续会使能MMU,然后跳转__mmap_switched,最后跳转到start_kernel。其中,start_kernel是内核的第一个C函数。

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

下面两幅图就是ARM处理器的Linux内核启动过程。

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

启动内核查看,可以看到看到自解压的调试信息和输出内核打印信息。

在这里插入图片描述

其中内核的打印信息就是通过printk(linux_banner)输出的。

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

我们在u-boot中还设置了启动参数,刚刚分析了这么多,都没有关于启动参数,那么启动参数要在哪里使用呢?


答:在内核的第一个程序,也就是start_kernel中使用。所以我们还要继续分析start_kernel。


查看start_kernel,这两个函数就是用来处理启动参数的。

在这里插入图片描述

再回过头来看下,启动参数有哪些东西,之前分析的笔记如下,其中命令行参数是由getenv(“bootargs”)获得的,这些参数都存在内存起始地址为0x30000100的地方。

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

启动内核的最终目的是执行应用程序,而应用程序是在根文件系统里面的,所以需要先挂接根文件系统,梳理了一下调用关系。

在这里插入图片描述

挂接根文件系统,那么需要挂接到哪一个根文件系统呢?


答:挂接的根文件系统是根据传入的启动参数决定的,在u-boot中查看,可以看到挂接的是第四个分区上面(从0开始)。

在这里插入图片描述

内核在mount_root中挂载根文件系统,那么在prepare_namespace中就要决定挂接的是哪个根文件系统。我们以此入手,来分析一下这些参数怎么处理。


从变量名可以看出,ROOT_DEV就是根文件系统,它的设置与saved_root_name有关,可以猜测一下,这个变量保存的应该就是根文件系统的名字。

在这里插入图片描述

查看saved_root_name的调用关系,可以看到root_dev_setup和__setup,作用是在解析命令行参数时,如果遇到root=,那就会调用root_dev_setup函数,这个函数就将这个root=后面的数据保存到了saved_root_name里去。

在这里插入图片描述

查看saved_root_name定义,可以看到,saved_root_name是一个最多64字节的字符型数组。

在这里插入图片描述

根据之前的经验,可以推测这个__setup应该也是一个宏,而且这个宏应该在某一个头文件中定义,搜索__setup,可以看到,在init.h文件中定义了这个宏。

在这里插入图片描述

进入init.h,可以看到如下定义。

在这里插入图片描述

和__setup(“root=”, root_dev_setup);一起展开,结果如红框所示,也就是定义了一个char型的数组和一个结构体,结构体里面有三个成员,一个char型的数组,一个函数,还有一个参数early,同时结构体的段属性被强制定义为了.init.setup。

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

可以在链接脚本中找到这个段(.init.setup),再来搜索一下__setup_start和__setup_end,这样我们就知道这些命令行是被怎样调用的了。


在这里插入图片描述

搜索发现,在两个函数中有用到,分别是obsolete_checksetup和do_early_param,可以猜测,那么early会在do_early_param中用到。

在这里插入图片描述

显然,不是do_early_param函数。

在这里插入图片描述

应该是在obsolete_checksetup中使用。

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

所以,u-boot传入的命令行参数,在内核的(.init.setup)段都会一一对应,等u-boot传入后再来一条一条的处理。


内核的启动流程就是这样,回过头来再说一个问题,现在是root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,我们说过在flash中无分区表,这些分区都是在代码中写死的,那么写在哪里呢?

在这里插入图片描述

答:启动内核的时候会打印分区的信息,我们可以搜索分区名来查找在哪里设置这些分区。

在这里插入图片描述

可以看到,应该是在common-smdk.c文件中定义的。

在这里插入图片描述

打开common-smdk.c文件查看一下,这就是它的分区,在代码里面写死的。

在这里插入图片描述

推荐阅读

史海拾趣

Auris公司的发展小趣事

在Auris公司的发展历程中,2017年夏天的一次收购事件具有重要意义。Auris以8000万美元的价格收购了Hansen Medical,这是一家专门开发工具来操控导管的公司。这次收购不仅增强了Auris在手术机器人领域的技术实力,也为其后续的产品研发和市场拓展提供了更多可能性。

科通(COMTEK)公司的发展小趣事

为了进一步扩大市场份额,科通技术积极实施国际化战略。公司在全球范围内设立了多个办事处和分公司,加强了与国际市场的联系和合作。同时,科通技术还积极参加国际电子展会和论坛等活动,展示公司的最新产品和技术成果,提升了公司的国际知名度和影响力。

世纪金光(CENGOL)公司的发展小趣事

在碳化硅材料技术取得突破后,世纪金光迅速将这一技术应用于功率器件的研发与生产。公司成功开发出额定电压650-1700V、额定电流5-100A的碳化硅肖特基二极管(SBD)以及额定电压650-1200V、额定电流20-100A的金属-氧化物半导体场效应晶体管(MOSFET)。这些高性能的功率器件在电源PFC、充电桩充电模组、光伏逆变器、特种电源等领域得到了广泛应用,为客户提供了高效、可靠的解决方案。

Ememory Technology Inc公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,eMemory始终保持着对新技术和新市场的敏锐洞察力。公司不断推出新的硅智财产品和解决方案,以满足客户不断变化的需求。同时,eMemory还积极拓展国际市场,与全球多家知名芯片设计厂商建立了长期稳定的合作关系。这些努力使得eMemory在电子行业中保持着领先地位,并为其未来的发展奠定了坚实的基础。

Graseby Infrared公司的发展小趣事
如果以上检查均正常,可能是电动机本身故障,如绕组断路、轴承卡死等。可以尝试手动转动电动机轴,检查是否有阻力或异常声音。
Antiference公司的发展小趣事

Antiference公司最初以生产电磁屏蔽材料起家,但随着电子设备的普及和电磁干扰问题的日益严重,公司意识到单纯的材料生产已无法满足市场需求。于是,Antiference投入巨资研发新型电磁干扰抑制技术,成功开发出了一款能够显著降低电磁干扰的芯片。这款芯片迅速在市场上获得了广泛认可,Antiference也因此成为了电磁干扰抑制领域的领军企业。

问答坊 | AI 解惑

预测

本帖最后由 paulhyde 于 2014-9-15 09:10 编辑 共同学习  …

查看全部问答>

我的PIC单片机调试心得,给像我一样曾经苦苦寻觅的初学者一点启示

我是一位初学者,pic初学者,但是在单片机行当已经混迹多年了。说句实话,c开发环境都大同小异,只不过烧写和在线仿真大同小异。钻研了两天,收到了很多回应和启发。 下面应soso的请求,把最近的调试心得和大家分享 1、 先说说我要做的东西 说来 ...…

查看全部问答>

奥特曼Zigbee读书日记(二)--OSAL系统框架专题

9. TI协议栈所用系统框架探讨。 51的系统往往不是太大,但是几十K的程序,也足以让一个初学者望而却步。我们首先忽略C语言本身的难度,光是系统框架也让生手读起来很吃力,再加上这种到处是API跟\"define\"的程序,还没有正式学习协议部分就已经让 ...…

查看全部问答>

关于FPGA总线的问题

问题是这样的:从CPU过来的数据总线,接到FPGA了,FPGA后面又接了一个CPLD,等于说,FPGA既要将数据总线自己用,又要输出给CPLD用,该怎么实现了? 难题是数据总向是双向的不好办! 因为两片FPGA之间的连线资源较多,把它们之间的数据总结分为送 ...…

查看全部问答>

求89c52烧录软件

那位用这个,发给兄弟伙了...谢了...1005450581…

查看全部问答>

如何读写51程序

我想知道8051是如果从电脑下载到51芯片中的,我的板子是52,看了下芯片资料是用P30 P31串口写入的,就算烧写的时候,PSEN脚要拉低电平,这是怎么被拉低的,找了每天每找到 而且烧写的软件是用的驱动程序,这么复杂,应该不要用驱动就能送数据到51 ...…

查看全部问答>

有做ARM的大侠没有?keiluv3有下的没有?

有做ARM的大侠没有?keiluv3有下的没有?…

查看全部问答>

请问arm 模块驱动?

请问各位大虾,现在我用ARM模块作了一个模块,需要计算机把它识别成一个人体学输入设备,该模块现在用的是windows ce系统,请问是否可以做一个驱动程序?大概应该怎么做?…

查看全部问答>

CEdit控件不能输入

从CWnd继承一个类CInputInfoWnd,在CInputInfoWnd用Create动态创建Edit控件m_editTest,此Edit控件上可以看到输入光标,但不能输入任何东西?…

查看全部问答>