对initramfs文件系统和busybox之间暧昧关系的分析理解
1. initramfs没有大小限制,no max size limit!
2. bootloader必须传递initramfs.gz的实际大小,否则kernel解压完之后,就会halt在那里[luther.gliethttp]
如果initramfs文件比较小,大小在200k左右,那么kernel能启动但是会提示:
Initramfs unpacking failed: compression method gzip not configured
如果initramfs文件/sbin/下含有modprobe程序,那么必定出现如下情况:
Uncompressing Linux....................................................
............... done, booting the kernel.然后就halt在这里没有任何输出了.
pc机上/sbin/modprobe可以正常使用,包括busybox生成的x86工具,使用qemu模拟时,
都能正常,可能是busybox在arm上的一个bug,所以make install之后的busybox需要
首先删除/sbin/modprobe文件,因为kernel/kmod.c会调用用户空间的这个程序,
致使不能启动kernel,可以将modprobe链接建立在/bin/目录下,这样就不会有任何问题了[luther.gliethttp]
3. 看来nfs是一个最容易让内核启动的方式,很适合用于最开始验证能否正常启动.[luther.gliethttp]
4. 因为built-in的usr/initramfs_data.cpio地址为__initramfs_start,它会在进入populate_rootfs
时,直接被释放到rootfs根目录/下,而__initramfs_start这个cpio包中已经含有了如下默认的3个文件,
luther@gliethttp:/luther/linux-2.6.30.4/usr$ cpio -i -t < initramfs_data.cpio
/dev
/dev/console
/root
1 block
所有我们定义的/根目录可以不需要/dev和/root这2个目录.[luther.gliethttp]
如下是我的目录,它用来生成initramfs.gz
luther@gliethttp:/vobs/nfs$ ls
bin etc init proc sbin sys
luther@gliethttp:/vobs/nfs$ tree etc proc sys
etc
|-- fstab
|-- init.d
| `-- rcS
`-- inittab
proc
sys
1 directory, 3 files
luther@gliethttp:/vobs/nfs$
redboot作如下修正[luther.gliethttp]
==> do_exec
params->hdr.tag = ATAG_INITRD2; // ATAG_INITRD修改
不论使用luther@gliethttp:/vobs/nfs$ find . | cpio -o -H newc | gzip > /vobs/tftp-dir/initramfs.gz
还是使用luther@gliethttp:/vobs/works/linux-2.6.30.4$ scripts/gen_initramfs_list.sh -o /vobs/tftp-dir/initramfs.gz /vobs/nfs/
一下测实结果相同.
luther@gliethttp:/vobs/tftp-dir$ ls -l initramfs.gz // 删除符号连接/sbin/modprobe
-rw-r--r-- 1 luther luther 896121 2009-08-06 21:24 initramfs.gz
luther@gliethttp:/vobs/tftp-dir$ ls -l initramfs.gz // 添加上符号连接/sbin/modprobe
-rw-r--r-- 1 luther luther 896133 2009-08-06 21:26 initramfs.gz
RedBoot> load -v -r -b 0x800000 initramfs.gz
Raw file loaded 0x00800000-0x008dac78, assumed entry at 0x00800000
RedBoot> fis load zImage // 删除符号连接/sbin/modprobe
RedBoot> exec -c "console=ttyAM0,115200" -r 0x800000 -s 0xdac79 // 能够正常启动[luther.gliethttp]
RedBoot> load -v -r -b 0x800000 initramfs.gz
Raw file loaded 0x00800000-0x008dac84, assumed entry at 0x00800000
RedBoot> fis load zImage // 添加上符号连接/sbin/modprobe
RedBoot> exec -c "console=ttyAM0,115200" -r 0x800000 -s 0xdac85 // 不能启动[luther.gliethttp]
Uncompressing Linux....................................................
............... done, booting the kernel.然后就halt在这里没有任何输出了.
下面为python计算文件大小,和文件实际大小一致[luther.gliethtp]
>>> 0xdac79
896121
>>> 0xdac85
896133
>>>
最后发现只要/sbin/目录下加入名为modprobe的程序就一定会halt系统,
这个问题折腾了老子2个晚上了,linux下怪现象多多的[luther.gliethtp]
不过后来仔细一想,问题总有它出错的原因,尤其软件这东西,所以想到可能是kernel
内部含有对/sbin/modprobe的引用,结果一搜,还真是这个原因,嘿嘿,终于能有一个解释了[luther.gliethttp]
kernel/kmod.c:50:char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
/**
* __request_module - try to load a kernel module
* @wait: wait (or not) for the operation to complete
* @fmt: printf style format string for the name of the module
* @...: arguments as specified in the format string
*
* Load a module using the user mode module loader. The function returns
* zero on success or a negative errno code on failure. Note that a
* successful module load does not mean the module did not then unload
* and exit on an error of its own. Callers must check that the service
* they requested is now available not blindly invoke it.
*
* If module auto-loading support is disabled then this function
* becomes a no-operation.
*/
int __request_module(bool wait, const char *fmt, ...)
{
va_list args;
char module_name[MODULE_NAME_LEN];
unsigned int max_modprobes;
int ret;
char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
static char *envp[] = { "HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL };
static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
* would be to run the parents of this process, counting how many times
* kmod was invoked. That would mean accessing the internals of the
* process tables to get the command line, proc_pid_cmdline is static
* and it is not worth changing the proc code just to handle this case.
* KAO.
*
* "trace the ppid" is simple, but will fail if someone's
* parent exits. I think this is as good as it gets. --RR
*/
max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
atomic_inc(&kmod_concurrent);
if (atomic_read(&kmod_concurrent) > max_modprobes) {
/* We may be blaming an innocent here, but unlikely */
if (kmod_loop_msg++ < 5)
printk(KERN_ERR
"request_module: runaway loop modprobe %s\n",
module_name);
atomic_dec(&kmod_concurrent);
return -ENOMEM;
}
ret = call_usermodehelper(modprobe_path, argv, envp,
wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
atomic_dec(&kmod_concurrent);
return ret;
}
最后如下.o文件中都对__request_module实现了引用,这也难怪出现
困扰了老子2个晚上的启动不起来的问题了[luther.gliethttp]
Binary file arch/arm/boot/Image matches
Binary file block/genhd.o matches
Binary file block/elevator.o matches
Binary file block/built-in.o matches
Binary file crypto/api.o matches
Binary file crypto/crypto_algapi.o matches
Binary file crypto/crypto.o matches
Binary file crypto/algapi.o matches
Binary file crypto/built-in.o matches
Binary file drivers/mtd/mtdpart.o matches
Binary file drivers/mtd/chips/gen_probe.o matches
Binary file drivers/mtd/chips/built-in.o matches
Binary file drivers/mtd/chips/chipreg.o matches
Binary file drivers/mtd/mtd.o matches
Binary file drivers/mtd/built-in.o matches
Binary file drivers/media/video/built-in.o matches
Binary file drivers/media/video/tuner.o matches
Binary file drivers/media/video/v4l2-common.o matches
Binary file drivers/media/video/tuner-core.o matches
Binary file drivers/media/common/built-in.o matches
Binary file drivers/media/common/tuners/tda8290.o matches
Binary file drivers/media/common/tuners/built-in.o matches
Binary file drivers/media/built-in.o matches
Binary file drivers/built-in.o matches
Binary file drivers/char/built-in.o matches
Binary file drivers/char/tty_ldisc.o matches
Binary file drivers/char/misc.o matches
Binary file fs/nls/nls_base.o matches
Binary file fs/nls/built-in.o matches
Binary file fs/built-in.o matches
Binary file fs/filesystems.o matches
Binary file fs/exec.o matches
Binary file fs/char_dev.o matches
Binary file kernel/kmod.o matches
kernel/kmod.c:117:EXPORT_SYMBOL(__request_module);
Binary file kernel/built-in.o matches
Binary file kernel/exec_domain.o matches
Binary file kernel/.kmod.c.swp matches