配置KCONFIG 出错

错误提示

 

Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
See Linux Documentation/init.txt for guidance.
[<c003051c>] (unwind_backtrace+0x0/0xec) from [<c0286048>] (panic+0x40/0xc4)
[<c0286048>] (panic+0x40/0xc4) from [<c002a56c>] (init_post+0x9c/0xbc)
[<c002a56c>] (init_post+0x9c/0xbc) from [<c00085ec>] (kernel_init+0x108/0x140)
[<c00085ec>] (kernel_init+0x108/0x140) from [<c002be40>] (kernel_thread_exit+0x0
/0x8)

 

找到一个比较好的讲解

/linuxrc错误(2)
2008-12-18 15:34

对应后两种情况。从代码中看到,必须要配制CONFIG_BLK_DEV_RAM才会支持image-initrd。否则全当成cpio-initrd的形式处理。
对于是cpio-initrd的情况。直接将其释放到根目录。对于是image-initrd的情况。将其释放到/initrd.image.最后将initrd内存区域归入伙伴系统。这段内存就可以由操作系统来做其它的用途了。
接下来,内核对这几种情况又是怎么处理的呢?不要着急。往下看:
回到kernel_init()这个函数:

static int __init kernel_init(void * unused)

{
         …….
         …….
         do_basic_setup();
         /*

         * check if there is an early userspace init. If yes, let it do all

         * the work
         */
         if (!ramdisk_execute_command)

                   ramdisk_execute_command = "/init";

         if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {

                   ramdisk_execute_command = NULL;

                   prepare_namespace();
         }
         /*

         * Ok, we have completed the initial bootup, and

         * we're essentially up and running. Get rid of the

         * initmem segments and start the user-mode stuff..

         */
         init_post();
         return 0;
}
ramdisk_execute_command:在kernel解析引导参数的时候使用。如果用户指定了init文件路径,即使用了“init=”,就会将这个参数值存放到这里。
如果没有指定init文件路径。默认为/init
对应于前面一段的分析,我们知道,对于initramdisk和cpio-initrd的情况,都会将虚拟根文件系统释放到根目录。如果这些虚拟文件系统里有/init这个文件。就会转入到init_post()。
Init_post()代码如下:

static int noinline init_post(void)

{
         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 "Warning: unable to open an initial console./n");

         (void) sys_dup(0);
         (void) sys_dup(0);
         if (ramdisk_execute_command) {
                   run_init_process(ramdisk_execute_command);

                   printk(KERN_WARNING "Failed to execute %s/n",

                                     ramdisk_execute_command);
         }
         /*
         * We try each of these until one succeeds.
         *

         * The Bourne shell can be used instead of init if we are

         * trying to recover a really broken machine.
         */
         if (execute_command) {
                   run_init_process(execute_command);

                   printk(KERN_WARNING "Failed to execute %s. Attempting "

                                               "defaults.../n", execute_command);

         }
         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.");
}
从代码中可以看中,会依次执行指定的init文件,如果失败,就会执行/sbin/init, /etc/init,, /bin/init,/bin/sh
注意的是,run_init_process在调用相应程序运行的时候,用的是kernel_execve。也就是说调用进程会替换当前进程。只要上述任意一个文件调用成功,就不会返回到这个函数。如果上面几个文件都无法执行。打印出没有找到init文件的错误。
对于image-hdr或者是虚拟文件系统中没有包含 /init的情况,会由prepare_namespace()处理。代码如下:

void __init prepare_namespace(void)

{
         int is_floppy;
         if (root_delay) {

                   printk(KERN_INFO "Waiting %dsec before mounting root device.../n",

                          root_delay);
                   ssleep(root_delay);
         }

         /* wait for the known devices to complete their probing */

         while (driver_probe_done() != 0)
                   msleep(100);
         //mtd的处理
         md_run_setup();
         if (saved_root_name[0]) {

                   root_device_name = saved_root_name;

                   if (!strncmp(root_device_name, "mtd", 3)) {

                            mount_block_root(root_device_name, root_mountflags);

                            goto out;
                   }

                   ROOT_DEV = name_to_dev_t(root_device_name);

                   if (strncmp(root_device_name, "/dev/", 5) == 0)

                            root_device_name += 5;

         }
         if (initrd_load())
                   goto out;

         /* wait for any asynchronous scanning to complete */

         if ((ROOT_DEV == 0) && root_wait) {

                   printk(KERN_INFO "Waiting for root device %s.../n",

                            saved_root_name);

                   while (driver_probe_done() != 0 ||

                            (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)

                            msleep(100);
         }

         is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;

         if (is_floppy && rd_doload && rd_load_disk(0))

                   ROOT_DEV = Root_RAM0;
         mount_root();
out:

         sys_mount(".", "/", NULL, MS_MOVE, NULL);

         sys_chroot(".");
}
这里有几个比较有意思的处理,首先用户可以用root=来指定根文件系统。它的值保存在saved_root_name中。如果用户指定了以mtd开始的字串做为它的根文件系统。就会直接去 。这个文件是mtdblock的设备文件。
否则将设备结点文件转换为ROOT_DEV即设备节点号
然后,转向initrd_load()执行initrd预处理后,再将具体的根文件系统
注意到,在这个函数末尾。会调用sys_mount()来移动当前文件系统 点到”/”目录下。然后将根目录切换到当前目录。这样,根文件系统的 点就成为了我们在用户空间所看到的”/”了.
对于其它根文件系统的情况,会先经过initrd的处理。即

int __init initrd_load(void)

{
         if (mount_initrd) {

                   create_dev("/dev/ram", Root_RAM0);

                   /*

                   * Load the initrd data into /dev/ram0. Execute it as initrd

                   * unless /dev/ram0 is supposed to be our actual root device,

                   * in that case the ram disk is just set up here, and gets

                   * mounted in the normal path.
                   */

                   if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {

                            sys_unlink("/initrd.image");
                            handle_initrd();
                            return 1;
                   }
         }
         sys_unlink("/initrd.image");
         return 0;
}
建立一个ROOT_RAM)的设备节点,并将/initrd/.image释放到这个节点中,/initrd.image的内容,就是我们之前分析的image-initrd。
如果根文件设备号不是ROOT_RAM0( 用户指定的根文件系统不是/dev/ram0就会转入到handle_initrd()
如果当前根文件系统是/dev/ram0.将其直接 就好了。
handle_initrd()代码如下:

static void __init handle_initrd(void)

{
         int error;
         int pid;

         real_root_dev = new_encode_dev(ROOT_DEV);

         create_dev("/dev/root.old", Root_RAM0);

         /* mount initrd on rootfs' /root */

         mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);

         sys_mkdir("/old", 0700);

         root_fd = sys_open("/", 0, 0);

         old_fd = sys_open("/old", 0, 0);

         /* move initrd over / and chdir/chroot in initrd root */

         sys_chdir("/root");

         sys_mount(".", "/", NULL, MS_MOVE, NULL);

         sys_chroot(".");
         /*

         * In case that a resume from disk is carried out by linuxrc or one of

         * its children, we need to tell the freezer not to wait for us.

         */
         current->flags |= PF_FREEZER_SKIP;

         pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);

         if (pid > 0)

                   while (pid != sys_wait4(-1, NULL, 0, NULL))

                            yield();

         current->flags &= ~PF_FREEZER_SKIP;

         /* move initrd to rootfs' /old */
         sys_fchdir(old_fd);

         sys_mount("/", ".", NULL, MS_MOVE, NULL);

         /* switch root and cwd back to / of rootfs */

         sys_fchdir(root_fd);
         sys_chroot(".");
         sys_close(old_fd);
         sys_close(root_fd);

         if (new_decode_dev(real_root_dev) == Root_RAM0) {

                   sys_chdir("/old");
                   return;
         }
         ROOT_DEV = new_decode_dev(real_root_dev);
         mount_root();

         printk(KERN_NOTICE "Trying to move old root to /initrd ... ");

         error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);

         if (!error)
                   printk("okay/n");
         else {

                   int fd = sys_open("/dev/root.old", O_RDWR, 0);

                   if (error == -ENOENT)

                            printk("/initrd does not exist. Ignored./n");

                   else
                            printk("failed/n");

                   printk(KERN_NOTICE "Unmounting old root/n");

                   sys_umount("/old", MNT_DETACH);

                   printk(KERN_NOTICE "Trying to free ramdisk memory ... ");

                   if (fd < 0) {
                            error = fd;
                   } else {

                            error = sys_ioctl(fd, BLKFLSBUF, 0);

                            sys_close(fd);
                   }

                   printk(!error ? "okay/n" : "failed/n");

         }
}
先将/dev/ram0 ,而后执行/linuxrc.等其执行完后。切换根目录,再 具体的根文件系统.
到这里。文件系统 的全部内容就分析完了.
五:小结
在本小节里。分析了根文件系统的 流程。并对几个虚拟根文件系统的情况做了详细的分析。理解这部份,对我们构建linux嵌入式开发系统是很有帮助的.
PS:参考资料:ibm技术论坛的<<Linux2.6 内核的 Initrd 机制解析>>                 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值