zoukankan      html  css  js  c++  java
  • 分析无法进入Linux系统的原因

    上文:http://www.cnblogs.com/long123king/p/3549701.html

    linux_no_root

       1: static int __init kernel_init(void * unused)
       2: {
       3:  ......
       4:  
       5:     if (!ramdisk_execute_command)
       6:         ramdisk_execute_command = "/init";
       7:  
       8:     if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
       9:         ramdisk_execute_command = NULL;
      10:         prepare_namespace();
      11:     }
      12:  
      13:     /*
      14:      * Ok, we have completed the initial bootup, and
      15:      * we're essentially up and running. Get rid of the
      16:      * initmem segments and start the user-mode stuff..
      17:      */
      18:  
      19:     init_post();
      20:     return 0;
      21: }

    如何在Source Insight中查找sys_access在哪里,直接找是找不到了,不如通过”Ctrl + /”来全局查找,查找:

       1: SYSCALL_DEFINE2(access

    这里面是对/init做一下检测,看看是否存在该文件,sys_access用来检测是否有权限访问该文件。

    返回值不为0,代表无法访问该文件,就执行prepare_namespace另作准备。

    如果这里可以访问/init文件,那么就直接调用该文件来进行初始化设置。

    因此,可以推测,prepare_namespace与initrd中的/init的作用类似。


       1: /*
       2:  * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
       3:  */
       4: void __init prepare_namespace(void)
       5: {

    注释的意思,决定挂载点,加载内存盘。

       1: if (root_delay) {
       2:         printk(KERN_INFO "Waiting %dsec before mounting root device...
    ",
       3:                root_delay);
       4:         ssleep(root_delay);
       5:     }

    是用来在挂载根文件系统之前,等待某些比较慢的IO设备准备好根设备。

    root_device_name就是我们在grub中通过root=/dev/sda1设置的根文件设备。

       1: static int __init root_dev_setup(char *line)
       2: {
       3:     strlcpy(saved_root_name, line, sizeof(saved_root_name));
       4:     return 1;
       5: }
       6:  
       7: __setup("root=", root_dev_setup);
       1: if (saved_root_name[0]) {
       2:     root_device_name = saved_root_name;
       3:     if (!strncmp(root_device_name, "mtd", 3) ||
       4:         !strncmp(root_device_name, "ubi", 3)) {
       5:         mount_block_root(root_device_name, root_mountflags);
       6:         goto out;
       7:     }
       8:     ROOT_DEV = name_to_dev_t(root_device_name);
       9:     if (strncmp(root_device_name, "/dev/", 5) == 0)
      10:         root_device_name += 5;
      11: }

    对于root=/dev/sda1,将root_device_name设置成sda1。

    ROOT_DEV = name_to_dev_t(root_device_name);

    在这之前,已经获取到了ROOT_DEV的描述符。

       1: if (initrd_load())
       2:     goto out;
       3:  
       4: /* wait for any asynchronous scanning to complete */
       5: if ((ROOT_DEV == 0) && root_wait) {
       6:     printk(KERN_INFO "Waiting for root device %s...
    ",
       7:         saved_root_name);
       8:     while (driver_probe_done() != 0 ||
       9:         (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
      10:         msleep(100);
      11:     async_synchronize_full();
      12: }
      13:  
      14: is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
      15:  
      16: if (is_floppy && rd_doload && rd_load_disk(0))
      17:     ROOT_DEV = Root_RAM0;
      18:  
      19: mount_root();
      20:  
      21: devtmpfs_mount("dev");
      22: sys_mount(".", "/", NULL, MS_MOVE, NULL);
      23: sys_chroot((const char __user __force *)".");

    如果initrd_load()成功了,就跳过mount_root这一步,这表明initrd_load()如果成功,就已经将root根文件系统给挂载好了。

    否则,调用mount_root/mount_block_root,尝试以各种可能的文件系统挂载根文件系统

       1: static char * __initdata root_fs_names;
       2: static int __init fs_names_setup(char *str)
       3: {
       4:     root_fs_names = str;
       5:     return 1;
       6: }
       7:  
       8: static unsigned int __initdata root_delay;
       9:  
      10: __setup("rootfstype=", fs_names_setup);
       1: static int __init do_mount_root(char *name, char *fs, int flags, void *data)
       2: {
       3:     int err = sys_mount(name, "/root", fs, flags, data);
       4:     if (err)
       5:         return err;
       6:  
       7:     sys_chdir((const char __user __force *)"/root");
       8:     ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
       9:     printk(KERN_INFO
      10:            "VFS: Mounted root (%s filesystem)%s on device %u:%u.
    ",
      11:            current->fs->pwd.mnt->mnt_sb->s_type->name,
      12:            current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ?
      13:            " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
      14:     return 0;
      15: }

    因此,这里的错误在于,没有正确地执行initrd中的初始化程序,也没有成功地mount根文件系统。

    明明是ext2的根文件系统,为什么没有被mount上呢?这是问题的根本原因。

  • 相关阅读:
    vue2.0 微信分享
    小程序开发:canvas在画布上滑动,页面跟着滑动问题
    前端AES解密
    vue2上传图片到OSS
    vue给不同环境配置不同打包命令
    vue页面绑定数据,渲染页面时会出现页面闪烁
    解决微信浏览器无法使用window.location.reload刷新页面
    vue列表拖拽组件 vue-dragging
    千万别在Java类的static块里写会抛异常的代码!
    linux shell的一些配置
  • 原文地址:https://www.cnblogs.com/long123king/p/3558093.html
Copyright © 2011-2022 走看看