小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Linux虛擬文件系統(tǒng)(安裝根文件系統(tǒng))

 lifei_szdz 2013-06-22
安裝根文件系統(tǒng)式系統(tǒng)初始化的關(guān)鍵部分。Linux內(nèi)核允許根文件系統(tǒng)放在很多不同的地方,比如硬盤分區(qū)、軟盤、通過(guò)NFS共享的遠(yuǎn)程文件系統(tǒng)以及保存在ramdisk中。內(nèi)核要在變量ROOT_DEV中尋找包含根文件系統(tǒng)的磁盤主設(shè)備號(hào)。當(dāng)編譯內(nèi)核時(shí),或者像最初的啟動(dòng)裝入程序傳遞一個(gè)合適的“root”選項(xiàng)時(shí),根文件系統(tǒng)可以被指定為/dev目錄下的一個(gè)設(shè)備文件。

相關(guān)閱讀:

http://www./Linux/2012-02/53771.htm

安裝根文件系統(tǒng)分為兩個(gè)階段:

1,內(nèi)核安裝特殊rootfs文件系統(tǒng),該文件系統(tǒng)僅提供一個(gè)作為初始安裝點(diǎn)的空目錄

start_kernel()->vfs_caches_init()->mnt_init()->init_rootfs()

[cpp]
  1. /*初始化根文件系統(tǒng)*/  
  2. int __init init_rootfs(void)  
  3. {  
  4.     int err;  
  5.     /*初始化ramfs_backing_dev_info*/  
  6.     err = bdi_init(&ramfs_backing_dev_info);  
  7.     if (err)  
  8.         return err;  
  9.     /*注冊(cè)rootfs_fs_type文件類型*/  
  10.     err = register_filesystem(&rootfs_fs_type);  
  11.     if (err)/*如果出錯(cuò),銷毀上面初始化的*/  
  12.         bdi_destroy(&ramfs_backing_dev_info);  
  13.   
  14.     return err;  
  15. }  
[cpp]
  1. static struct backing_dev_info ramfs_backing_dev_info = {  
  2.     .name       = "ramfs",  
  3.     .ra_pages   = 0,    /* No readahead */  
  4.     .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK |  
  5.               BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |  
  6.               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,  
  7. };  
[cpp]
  1. /** 
  2.  *  register_filesystem - register a new filesystem 
  3.  *  @fs: the file system structure 
  4.  * 
  5.  *  Adds the file system passed to the list of file systems the kernel 
  6.  *  is aware of for mount and other syscalls. Returns 0 on success, 
  7.  *  or a negative errno code on an error. 
  8.  * 
  9.  *  The &struct file_system_type that is passed is linked into the kernel  
  10.  *  structures and must not be freed until the file system has been 
  11.  *  unregistered. 
  12.  */  
  13.  /*注冊(cè)一個(gè)新的文件系統(tǒng)*/  
  14. int register_filesystem(struct file_system_type * fs)  
  15. {  
  16.     int res = 0;  
  17.     struct file_system_type ** p;  
  18.   
  19.     BUG_ON(strchr(fs->name, '.'));  
  20.     if (fs->next)  
  21.         return -EBUSY;  
  22.     INIT_LIST_HEAD(&fs->fs_supers);  
  23.     write_lock(&file_systems_lock);  
  24.     /*從system_type鏈表中查找指定名稱的file_system_type*/  
  25.     p = find_filesystem(fs->name, strlen(fs->name));  
  26.     if (*p)  
  27.         res = -EBUSY;  
  28.     else  
  29.         *p = fs;  
  30.     write_unlock(&file_systems_lock);  
  31.     return res;  
  32. }  

根文件系統(tǒng)定義如下

[cpp]
  1. static struct file_system_type rootfs_fs_type = {  
  2.     .name       = "rootfs",  
  3.     .get_sb     = rootfs_get_sb,  
  4.     .kill_sb    = kill_litter_super,  
  5. };  

下面看看他的兩個(gè)函數(shù)

[cpp]
  1. /*獲得根目錄的sb*/  
  2. static int rootfs_get_sb(struct file_system_type *fs_type,  
  3.     int flags, const char *dev_name, void *data, struct vfsmount *mnt)  
  4. {  
  5.     return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,  
  6.                 mnt);  
  7. }  
[cpp]
  1. int get_sb_nodev(struct file_system_type *fs_type,  
  2.     int flags, void *data,  
  3.     int (*fill_super)(struct super_block *, void *, int),  
  4.     struct vfsmount *mnt)  
  5. {  
  6.     int error;  
  7.     /*獲得sb結(jié)構(gòu)*/  
  8.     struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);  
  9.   
  10.     if (IS_ERR(s))  
  11.         return PTR_ERR(s);  
  12.   
  13.     s->s_flags = flags;  
  14.     /*這里實(shí)際調(diào)用ramfs_fill_super,對(duì)sb結(jié)構(gòu)的屬性進(jìn)行設(shè)置*/  
  15.     error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);  
  16.     if (error) {  
  17.         deactivate_locked_super(s);  
  18.         return error;  
  19.     }  
  20.     s->s_flags |= MS_ACTIVE;  
  21.     simple_set_mnt(mnt, s);/*設(shè)置mnt和sb關(guān)聯(lián)*/  
  22.     return 0;  
  23. }  
[cpp]
  1. /** 
  2.  *  sget    -   find or create a superblock 
  3.  *  @type:  filesystem type superblock should belong to 
  4.  *  @test:  comparison callback 
  5.  *  @set:   setup callback 
  6.  *  @data:  argument to each of them 
  7.  */  
  8.  /*查找或創(chuàng)建一個(gè)sb結(jié)構(gòu)*/  
  9. struct super_block *sget(struct file_system_type *type,  
  10.             int (*test)(struct super_block *,void *),  
  11.             int (*set)(struct super_block *,void *),  
  12.             void *data)  
  13. {  
  14.     struct super_block *s = NULL;  
  15.     struct super_block *old;  
  16.     int err;  
  17.   
  18. retry:  
  19.     spin_lock(&sb_lock);  
  20.     if (test) {  
  21.         list_for_each_entry(old, &type->fs_supers, s_instances) {  
  22.             if (!test(old, data))  
  23.                 continue;  
  24.             if (!grab_super(old))  
  25.                 goto retry;  
  26.             if (s) {  
  27.                 up_write(&s->s_umount);  
  28.                 destroy_super(s);  
  29.             }  
  30.             return old;  
  31.         }  
  32.     }  
  33.     if (!s) {/*如果找不到sb,從內(nèi)存中申請(qǐng)一個(gè)*/  
  34.         spin_unlock(&sb_lock);  
  35.         s = alloc_super(type);  
  36.         if (!s)  
  37.             return ERR_PTR(-ENOMEM);  
  38.         goto retry;  
  39.     }  
  40.           
  41.     err = set(s, data);  
  42.     if (err) {  
  43.         spin_unlock(&sb_lock);  
  44.         up_write(&s->s_umount);  
  45.         destroy_super(s);  
  46.         return ERR_PTR(err);  
  47.     }  
  48.     /*初始化得到的sb結(jié)構(gòu)*/  
  49.     s->s_type = type;  
  50.     strlcpy(s->s_id, type->name, sizeof(s->s_id));  
  51.     /*加入鏈表尾*/  
  52.     list_add_tail(&s->s_list, &super_blocks);  
  53.     list_add(&s->s_instances, &type->fs_supers);  
  54.     spin_unlock(&sb_lock);  
  55.     get_filesystem(type);  
  56.     return s;  
  57. }  
[cpp]
  1. /*所有超級(jí)塊對(duì)象都以雙向循環(huán)鏈表的形式鏈接在一起,量表中第一個(gè) 
  2. 元素用super_blocks變量表示,而超級(jí)塊對(duì)象的s_list字段存放指向鏈表 
  3. 相鄰元素的指針*/  
  4. LIST_HEAD(super_blocks);  
[cpp]
  1. /** 
  2.  *  alloc_super -   create new superblock 
  3.  *  @type:  filesystem type superblock should belong to 
  4.  * 
  5.  *  Allocates and initializes a new &struct super_block.  alloc_super() 
  6.  *  returns a pointer new superblock or %NULL if allocation had failed. 
  7.  */  
  8. static struct super_block *alloc_super(struct file_system_type *type)  
  9. {     
  10.     /*從內(nèi)存中申請(qǐng)sb*/  
  11.     struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);  
  12.     static const struct super_operations default_op;  
  13.   
  14.     if (s) {  
  15.         if (security_sb_alloc(s)) {  
  16.             kfree(s);  
  17.             s = NULL;  
  18.             goto out;  
  19.         }  
  20.         /*初始化*/  
  21.         INIT_LIST_HEAD(&s->s_files);  
  22.         INIT_LIST_HEAD(&s->s_instances);  
  23.         INIT_HLIST_HEAD(&s->s_anon);  
  24.         INIT_LIST_HEAD(&s->s_inodes);  
  25.         INIT_LIST_HEAD(&s->s_dentry_lru);  
  26.         init_rwsem(&s->s_umount);  
  27.         mutex_init(&s->s_lock);  
  28.         lockdep_set_class(&s->s_umount, &type->s_umount_key);  
  29.         /* 
  30.          * The locking rules for s_lock are up to the 
  31.          * filesystem. For example ext3fs has different 
  32.          * lock ordering than usbfs: 
  33.          */  
  34.         lockdep_set_class(&s->s_lock, &type->s_lock_key);  
  35.         /* 
  36.          * sget() can have s_umount recursion. 
  37.          * 
  38.          * When it cannot find a suitable sb, it allocates a new 
  39.          * one (this one), and tries again to find a suitable old 
  40.          * one. 
  41.          * 
  42.          * In case that succeeds, it will acquire the s_umount 
  43.          * lock of the old one. Since these are clearly distrinct 
  44.          * locks, and this object isn't exposed yet, there's no 
  45.          * risk of deadlocks. 
  46.          * 
  47.          * Annotate this by putting this lock in a different 
  48.          * subclass. 
  49.          */  
  50.         down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);  
  51.         s->s_count = S_BIAS;  
  52.         atomic_set(&s->s_active, 1);  
  53.         mutex_init(&s->s_vfs_rename_mutex);  
  54.         mutex_init(&s->s_dquot.dqio_mutex);  
  55.         mutex_init(&s->s_dquot.dqonoff_mutex);  
  56.         init_rwsem(&s->s_dquot.dqptr_sem);  
  57.         init_waitqueue_head(&s->s_wait_unfrozen);  
  58.         s->s_maxbytes = MAX_NON_LFS;  
  59.         s->dq_op = sb_dquot_ops;  
  60.         s->s_qcop = sb_quotactl_ops;  
  61.         s->s_op = &default_op;  
  62.         s->s_time_gran = 1000000000;  
  63.     }  
  64. out:  
  65.     return s;  
  66. }  

kill_litter_super的過(guò)程相反,這里不再寫了。

構(gòu)造根目錄是由init_mount_tree()函數(shù)實(shí)現(xiàn)的,該函數(shù)在前面已經(jīng)介紹過(guò)了。


2,安裝實(shí)際根文件系統(tǒng)

關(guān)于__setup宏

__setup宏來(lái)注冊(cè)關(guān)鍵字及相關(guān)聯(lián)的處理函數(shù),__setup宏在include/linux/init.h中定義,其原型如下:
__setup(string, _handler);
其中:string是關(guān)鍵字,_handler是關(guān)聯(lián)處理函數(shù)。__setup只是告訴內(nèi)核在啟動(dòng)時(shí)輸入串中含有string時(shí),內(nèi)核要去
執(zhí)行_handler。String必須以“=”符結(jié)束以使parse_args更方便解析。緊隨“=”后的任何文本都會(huì)作為輸入傳給
_handler。下面的例子來(lái)自于init/do_mounts.c,其中root_dev_setup作為處理程序被注冊(cè)給“root=”關(guān)鍵字:
 __setup("root=", root_dev_setup);

比如我們?cè)趩?dòng)向參數(shù)終有

  noinitrd root=/dev/mtdblock2 console=/linuxrc

 setup_arch解釋時(shí)會(huì)發(fā)現(xiàn)root=/dev/mtdblock2,然后它就會(huì)調(diào)用root_dev_setup

[cpp]
  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);  


Start_kernel->rest_init->init-> prepare_namespace->

[cpp]
  1. /* 
  2.  * Prepare the namespace - decide what/where to mount, load ramdisks, etc. 
  3.  */  
  4. void __init prepare_namespace(void)  
  5. {  
  6.     int is_floppy;  
  7.   
  8.     if (root_delay) {  
  9.         printk(KERN_INFO "Waiting %dsec before mounting root device...\n",  
  10.                root_delay);  
  11.         ssleep(root_delay);  
  12.     }  
  13.   
  14.     /* 
  15.      * wait for the known devices to complete their probing 
  16.      * 
  17.      * Note: this is a potential source of long boot delays. 
  18.      * For example, it is not atypical to wait 5 seconds here 
  19.      * for the touchpad of a laptop to initialize. 
  20.      */  
  21.     wait_for_device_probe();  
  22.     /*創(chuàng)建/dev/ram0,必須得,因?yàn)閕nitrd要放到/dev/ram0里*/  
  23.     md_run_setup();  
  24.   
  25.     if (saved_root_name[0]) {/*saved_root_name為從啟動(dòng)參數(shù)"root"中獲取的設(shè)備文件名*/  
  26.         root_device_name = saved_root_name;  
  27.         if (!strncmp(root_device_name, "mtd", 3) ||  
  28.             !strncmp(root_device_name, "ubi", 3)) {/*如果設(shè)備名開頭為這兩個(gè)*/  
  29.             mount_block_root(root_device_name, root_mountflags);  
  30.             goto out;  
  31.         }  
  32.         /*主設(shè)備號(hào)和次設(shè)備號(hào)*/  
  33.         ROOT_DEV = name_to_dev_t(root_device_name);  
  34.         if (strncmp(root_device_name, "/dev/", 5) == 0)  
  35.             root_device_name += 5;/*濾掉'/dev/'字符*/  
  36.     }  
  37.   
  38.     if (initrd_load())  
  39.         goto out;  
  40.   
  41.     /* wait for any asynchronous scanning to complete */  
  42.     if ((ROOT_DEV == 0) && root_wait) {  
  43.         printk(KERN_INFO "Waiting for root device %s...\n",  
  44.             saved_root_name);  
  45.         while (driver_probe_done() != 0 ||  
  46.             (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)  
  47.             msleep(100);  
  48.         async_synchronize_full();  
  49.     }  
  50.   
  51.     is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;  
  52.   
  53.     if (is_floppy && rd_doload && rd_load_disk(0))  
  54.         ROOT_DEV = Root_RAM0;  
  55.     /*實(shí)際操作*/  
  56.     mount_root();  
  57. out:  
  58.     devtmpfs_mount("dev");/*devfs從虛擬的根文件系統(tǒng)的/dev umount*/  
  59.     sys_mount(".""/", NULL, MS_MOVE, NULL);/*將掛載點(diǎn)從當(dāng)前目錄【/root】(在mount_root函數(shù)中設(shè)置的)移到根目錄*/  
  60.     /*當(dāng)前目錄即【/root】(真正文件系統(tǒng)掛載的目錄)做為系統(tǒng)根目錄*/  
  61.     sys_chroot(".");  
  62. }  

mount_root操作

[cpp]
  1. void __init mount_root(void)  
  2. {  
  3. #ifdef CONFIG_ROOT_NFS   
  4.     if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {  
  5.         if (mount_nfs_root())  
  6.             return;  
  7.   
  8.         printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");  
  9.         ROOT_DEV = Root_FD0;  
  10.     }  
  11. #endif   
  12. #ifdef CONFIG_BLK_DEV_FD   
  13.     if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {  
  14.         /* rd_doload is 2 for a dual initrd/ramload setup */  
  15.         if (rd_doload==2) {  
  16.             if (rd_load_disk(1)) {  
  17.                 ROOT_DEV = Root_RAM1;  
  18.                 root_device_name = NULL;  
  19.             }  
  20.         } else  
  21.             change_floppy("root floppy");  
  22.     }  
  23. #endif   
  24. #ifdef CONFIG_BLOCK/*這里是一般流程*/   
  25.     create_dev("/dev/root", ROOT_DEV);/*用系統(tǒng)調(diào)用創(chuàng)建"/dev/root"*/  
  26.     mount_block_root("/dev/root", root_mountflags);  
  27. #endif   
  28. }  
[cpp]
  1. void __init mount_block_root(char *name, int flags)  
  2. {  
  3.     /*從cache中分配空間*/  
  4.     char *fs_names = __getname_gfp(GFP_KERNEL  
  5.         | __GFP_NOTRACK_FALSE_POSITIVE);  
  6.     char *p;  
  7. #ifdef CONFIG_BLOCK   
  8.     char b[BDEVNAME_SIZE];  
  9. #else   
  10.     const char *b = name;  
  11. #endif   
  12.     /*獲得文件系統(tǒng)類型,如果在bootoption里有, 
  13.     則就為這個(gè)文件系統(tǒng)類型,如果沒(méi)有指定, 
  14.     則返回ilesytem鏈上所有類型,下面再對(duì)每個(gè)進(jìn)行嘗試.*/  
  15.     get_fs_names(fs_names);  
  16. retry:  
  17.     for (p = fs_names; *p; p += strlen(p)+1) {  
  18.         /*實(shí)際的安裝工作,這里調(diào)用了mount系統(tǒng)調(diào)用 
  19.         將文件系統(tǒng)掛到/root目錄,p為文件系統(tǒng)類型,由get_fs_names得到 
  20.         */  
  21.         int err = do_mount_root(name, p, flags, root_mount_data);  
  22.         switch (err) {  
  23.             case 0:  
  24.                 goto out;  
  25.             case -EACCES:  
  26.                 flags |= MS_RDONLY;  
  27.                 goto retry;  
  28.             case -EINVAL:  
  29.                 continue;  
  30.         }  
  31.             /* 
  32.          * Allow the user to distinguish between failed sys_open 
  33.          * and bad superblock on root device. 
  34.          * and give them a list of the available devices 
  35.          */  
  36. #ifdef CONFIG_BLOCK   
  37.         __bdevname(ROOT_DEV, b);  
  38. #endif   
  39.         printk("VFS: Cannot open root device \"%s\" or %s\n",  
  40.                 root_device_name, b);  
  41.         printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");  
  42.   
  43.         printk_all_partitions();  
  44. #ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT   
  45.         printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "  
  46.                "explicit textual name for \"root=\" boot option.\n");  
  47. #endif   
  48.         panic("VFS: Unable to mount root fs on %s", b);  
  49.     }  
  50.   
  51.     printk("List of all partitions:\n");  
  52.     printk_all_partitions();  
  53.     printk("No filesystem could mount root, tried: ");  
  54.     for (p = fs_names; *p; p += strlen(p)+1)  
  55.         printk(" %s", p);  
  56.     printk("\n");  
  57. #ifdef CONFIG_BLOCK   
  58.     __bdevname(ROOT_DEV, b);  
  59. #endif   
  60.     panic("VFS: Unable to mount root fs on %s", b);  
  61. out:  
  62.     putname(fs_names);  
  63. }  
  64.    
[cpp]
  1. static int __init do_mount_root(char *name, char *fs, int flags, void *data)  
  2. {  
  3.     /*mount系統(tǒng)調(diào)用來(lái)做實(shí)際的安裝文件系統(tǒng)工作*/  
  4.     int err = sys_mount(name, "/root", fs, flags, data);  
  5.     if (err)  
  6.         return err;  
  7.     /*改變當(dāng)前路徑到根目錄*/  
  8.     sys_chdir("/root");  
  9.     ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;  
  10.     printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",  
  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. }  

到此,根文件系統(tǒng)的安裝過(guò)程算是完成了,中間關(guān)于mount等系統(tǒng)調(diào)用將在后面分析??梢钥闯隹偟牟襟E主要有:

1,創(chuàng)建一個(gè)rootfs,這個(gè)是虛擬的rootfs,是內(nèi)存文件系統(tǒng)(和ramfs),后面還會(huì)指向具體的根文件系統(tǒng);

2,從系統(tǒng)啟動(dòng)參數(shù)中獲取設(shè)備文件名以及設(shè)備號(hào);

3,調(diào)用系統(tǒng)調(diào)用創(chuàng)建符號(hào)鏈接,并調(diào)用mount系統(tǒng)調(diào)用進(jìn)程實(shí)際的安裝操作;

4,改變進(jìn)程當(dāng)前目錄;

5,移動(dòng)rootfs文件系統(tǒng)根目錄上得已經(jīng)安裝文件系統(tǒng)的安裝點(diǎn);
rootfs特殊文件系統(tǒng)沒(méi)有被卸載,他只是隱藏在基于磁盤的根文件系統(tǒng)下了。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多