对Linux分区失败的一个研究

2019-07-12 19:29发布

嵌入式Linux操作系统目前已经广泛应用手机终端产品的开发,对于常见的嵌入式Linux操作系统,在终端主板上需要下载的软件包含几个部分:U-bootKernel、文件系统和用户应用程序。U-boot负责对文件系统和内核分行分区,主板在起动时加载主程序等工作;Kernel特定于嵌入式板子的定制内核以及内核的启动参数,并包括对某些功能的支持; 文件系统包括根文件系统和建立于Flash内存设备之上文件系统;用户应用程序是特定于用户的应用程序。 对硬件Flash的分区由U-boot来指定,通常第一个分区是bootloader、第二个分区是kernel、第三个分区是文件系统,其余的分区由用户来指定,比如用户想建立一个Jffs2类型的可写分区等。具体的分区指定方式是在/u-boot/include/configs目录下修改头文件,举例如下: bootlinux=bootoctlinux 2000000 root = /dev/mtdblock2  mtdparts = phys_mapped_flash: 512k(bootloader), 2048k(kernel), 6144k(cramfs)。上例中指出文件系统对应的设备文件是mtdblock2 ,分区有三个大小分区是512K2M6M        在实际工作中我们碰到一个问题,就是在增加分区达到一定的数目后,起动主板程序后,程序跑死并提示“Kernel panic”。 经过所得的测试,我们发现如果分区数目增加到10个以上时,会出现程序跑死的情况。对起动失败和起动成功的Log进行分析,我们发现在起动失败的Log中程序起动时对于U-boot的起动Log中打印出如下信息: argv[3]: mtdparts=phys_mapped_flash:512k(bootloader)ro,2048k(kernel),6144k(cramfs),128k(CFG),128k(bootloader_env),1024k(jffs2),1024k(delta),256k(delta_backup),128k(hold_area1),128k(mac_env) 这说明U-boot中已经把分区信息正确的设定好了,并传给了Kernel,下来进一步分析后面的Log信息,我们发现如下信息: RedBoot partition parsing not available 这里由Linux系统打印出错信息,说明分区在Kernel部分出错了! 为什么会出错呢?对此我们还需要进一步进行研究。 继续分析Log,我们又发现如下信息: Kernel command line: console=ttyS0,115200 bootoctlinux 2000000 root=/dev/mtdblock2 我们发现在此处,由U-boot传给Kernel的分区表信息丢失了!这是为什么呢?继续分析,我们初步判断可能是内核在处理分区信息时出错,那么打开Kernel部分代码,我们以Kernel command line为关键词进行搜索。 在文件Main.c (linux/init)中的函数asmlinkage void __init start_kernel(void)中有如下信息:       printk(KERN_NOTICE "Kernel command line: %s/n", saved_command_line); 上面的打印信息中有一个全局变量:saved_command_line,继续搜索代码发现有一处拷贝代码: Kernel的初始化代码的函数void __init parse_early_param(void)中有如下信息:       strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE); 在此我们又发现了对于拷贝这个数组的大小为:COMMAND_LINE_SIZE,由于这个数据保存的就是分区信息表,至此我们离问题的原因越来越接近了,是不是由于这个数组的大小不足以保存分区信息呢?继续分析我们发现COMMAND_LINE_SIZE值是256 至此我们可以确认这个问题产生的原因了,之后我们把这个数组的大小升级为512,分区问题终于得到了解决。