Openwrt内部工具链改为外部工具链:kernel panic - not syncing: No init found. Try passing init= option to kernel.

13 篇文章 3 订阅
3 篇文章 0 订阅

一、环境:openwrt+linux 2.6.31

1、内部toolchain

make menuconfig 内部toolchain配置如下: [*] Advanced configuration options (for developers)  --->  [*]   Toolchain Options  --->


编出的toolchain为:staging_dir/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2目录

用该toolchain编出的firmware可以再设备中正常运行。

2、外部toolchain

目的:由于每次checkout代码都需要重新编toolchain,耗时很长,为了节省这部分时间,决定将上面已经编好的toolchain作为一个独立的目录,只要放置于编译环境的固定目录即可。

操作:

make menuconfig 外部toolchain配置如下: [*] Advanced configuration options (for developers)  --->  [*]   Toolchain Options  --->

Base system  ---> --- libc Configuration  ---> libc shared library base directory配置为:
/opt/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2
Base system  ---> --- libgcc  Configuration  ---> libgcc shared library base directory 配置为:
/opt/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2
Base system  ---> --- libpthread Configuration  ---> libpthread shared library base directory 配置为:

/opt/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2

注:其他配置默认。

配置完成,make成功。


3、运行

把生成的firmware文件放在设备中运行,启动时出现错误:kernel panic - not syncing: No init found.  Try passing init= option to kernel.

从内核代码中找到该log的打印是在init/main.c

static noinline int init_post(void)
	__releases(kernel_lock)
{
	/* need to finish all async __init code before freeing the memory */
	async_synchronize_full();
	free_initmem();
	unlock_kernel();
	mark_rodata_ro();
	system_state = SYSTEM_RUNNING;
	numa_default_policy();

	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n");

	(void) sys_dup(0);
	(void) sys_dup(0);

	current->signal->flags |= SIGNAL_UNKILLABLE;

	if (ramdisk_execute_command) {
		run_init_process(ramdisk_execute_command);
		printk(KERN_WARNING "Failed to execute %s\n",
				ramdisk_execute_command);
	}

	/*
	 * We disable the "init" processing command to workaround
	 * the bootloader implementation
	 * This needs to be removed in the long term as it removes
	 * the opportunity to modify the boot program
	 */
	run_init_process("/etc/preinit");
	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= option to kernel.");
}

打印该log的原因是,执行系统的第一个应用程序init失败。可能的原因:

1、rootfs分区不对,init程序文件找不到;

2、init程序文件找到了,但执行错误(依赖的库文件有问题)


二、分析:

对比了两种toolchain编出的rootfs,发现用外部toolchain编出的rootfs中,少了/lib/libuClibc-0.9.33.2.so, /lib/ld-uClibc-0.9.33.2.so, /lib/ld-uClibc.so.0,三个库文件,看来是linux启动时在执行/sbin/init程序时由于缺少这些库文件导致运行出错,进而出现kernel panic。


需要找出缺少该文件的原因及解决方案。

线索:在make menuconfig 中配置Base system  ---> --- libc Configuration  ---> libc shared library files (use wildcards)有相关库的配置:

默认配置为:./lib/ld{-*.so,*.so.*}./lib/lib{anl,c,cidn,crypt,dl,m,nsl,nss_dns,nss_files,resolv,util}{-*.so,.so.*}

发现这些模糊配置没有匹配上面缺少的三个文件(/lib/libuClibc-0.9.33.2.so, /lib/ld-uClibc-0.9.33.2.so, /lib/ld-uClibc.so.0

结论:看来是这些表达式的问题了。


三、解决方案

修改配置Base system  ---> --- libc Configuration  ---> libc shared library files (use wildcards)如下:

./lib/ld{-*.so,-uClibc.so.*,-linux*.so.*} ./lib/lib{uClibc,anl,c,cidn,crypt,dl,m,nsl,nss_dns,nss_files,resolv,util}{-*.so,.so.*}

  该配置是属于CONFIG_LIBC_FILE_SPEC的,其定义是在package/toolchain/Makefile中,具体定义如下:

  define Package/libc/install
    for file in $(call qstrip,$(CONFIG_LIBC_FILE_SPEC)); do \
        dir=`dirname $$$$file` ; \
        $(INSTALL_DIR) $(1)/$$$$dir ; \
        $(CP) $(call qstrip,$(CONFIG_LIBC_ROOT_DIR))/$$$$file $(1)/$$$$dir/ ; \
    done ; \
    exit 0
  endef
看来就是这个package负责安装这些库文件的。

所以,执行make package/toolchain/clean && make package/toolchain/install V=s,完成后检查rootfs,发现缺少的三个文件出现了。

最后,重新make,将生成的firmware放在板子上运行,现在系统可以正常运行了。大笑大哭


四、总结

在更换toolchain时,容易出现库文件丢失的情况,导致系统无法正常启动。

所以在更换toolchain时,要谨慎比较前后的差异。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值