Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531811
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: 嵌入式

2009-08-06 22:20:33

对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
阅读(3440) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

gliethttp2009-09-07 20:39:22

浅析request_module内核驱动直接引用用户空间程序/sbin/modprobe http://blog.chinaunix.net/u1/38994/showart_2047504.html

gliethttp2009-08-07 08:22:57

还有一个就是uevent使用到的/sbin/hotplug,也是影响bringup开发板的致命程序