国产宅男网站在线|亚洲A级性爱免费视频|亚洲中精品级在线|午夜福利AA毛

  • <dd id="gf5jf"><th id="gf5jf"></th></dd>

    <cite id="gf5jf"><label id="gf5jf"></label></cite>
  • <div id="gf5jf"><listing id="gf5jf"></listing></div>
    學(xué)習(xí)啦 > 學(xué)習(xí)電腦 > 操作系統(tǒng) > Linux教程 > linux安裝文件系統(tǒng)

    linux安裝文件系統(tǒng)

    時間: 春健736 分享

    linux安裝文件系統(tǒng)

      Linux文件系統(tǒng)中的文件是數(shù)據(jù)的集合,文件系統(tǒng)不僅包含著文件中的數(shù)據(jù)而且還有文件系統(tǒng)的結(jié)構(gòu),所有Linux 用戶和程序看到的文件、目錄、軟連接及文件保護信息等都存儲在其中。下面大家與學(xué)習(xí)啦小編一起來學(xué)習(xí)一下吧。

      安裝linux文件系統(tǒng)

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

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

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

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

      [cpp] view plain copy print?

      /*初始化根文件系統(tǒng)*/

      int __init init_rootfs(void)

      {

      int err;

      /*初始化ramfs_backing_dev_info*/

      err = bdi_init(&ramfs_backing_dev_info);

      if (err)

      return err;

      /*注冊rootfs_fs_type文件類型*/

      err = register_filesystem(&rootfs_fs_type);

      if (err)/*如果出錯,銷毀上面初始化的*/

      bdi_destroy(&ramfs_backing_dev_info);

      return err;

      }

      [cpp] view plain copy print?

      static struct backing_dev_info ramfs_backing_dev_info = {

      .name = "ramfs",

      .ra_pages = 0, /* No readahead */

      .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |

      BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |

      BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,

      };

      [cpp] view plain copy print?

      /**

      * register_filesystem - register a new filesystem

      * @fs: the file system structure

      *

      * Adds the file system passed to the list of file systems the kernel

      * is aware of for mount and other syscalls. Returns 0 on success,

      * or a negative errno code on an error.

      *

      * The &struct file_system_type that is passed is linked into the kernel

      * structures and must not be freed until the file system has been

      * unregistered.

      */

      /*注冊一個新的文件系統(tǒng)*/

      int register_filesystem(struct file_system_type * fs)

      {

      int res = 0;

      struct file_system_type ** p;

      BUG_ON(strchr(fs->name, '.'));

      if (fs->next)

      return -EBUSY;

      INIT_LIST_HEAD(&fs->fs_supers);

      write_lock(&file_systems_lock);

      /*從system_type鏈表中查找指定名稱的file_system_type*/

      p = find_filesystem(fs->name, strlen(fs->name));

      if (*p)

      res = -EBUSY;

      else

      *p = fs;

      write_unlock(&file_systems_lock);

      return res;

      }

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

      [cpp] view plain copy print?

      static struct file_system_type rootfs_fs_type = {

      .name = "rootfs",

      .get_sb = rootfs_get_sb,

      .kill_sb = kill_litter_super,

      };

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

      [cpp] view plain copy print?

      /*獲得根目錄的sb*/

      static int rootfs_get_sb(struct file_system_type *fs_type,

      int flags, const char *dev_name, void *data, struct vfsmount *mnt)

      {

      return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,

      mnt);

      }

      [cpp] view plain copy print?

      int get_sb_nodev(struct file_system_type *fs_type,

      int flags, void *data,

      int (*fill_super)(struct super_block *, void *, int),

      struct vfsmount *mnt)

      {

      int error;

      /*獲得sb結(jié)構(gòu)*/

      struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);

      if (IS_ERR(s))

      return PTR_ERR(s);

      s->s_flags = flags;

      /*這里實際調(diào)用ramfs_fill_super,對sb結(jié)構(gòu)的屬性進行設(shè)置*/

      error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);

      if (error) {

      deactivate_locked_super(s);

      return error;

      }

      s->s_flags |= MS_ACTIVE;

      simple_set_mnt(mnt, s);/*設(shè)置mnt和sb關(guān)聯(lián)*/

      return 0;

      }

      [cpp] view plain copy print?

      /**

      * sget - find or create a superblock

      * @type: filesystem type superblock should belong to

      * @test: comparison callback

      * @set: setup callback

      * @data: argument to each of them

      */

      /*查找或創(chuàng)建一個sb結(jié)構(gòu)*/

      struct super_block *sget(struct file_system_type *type,

      int (*test)(struct super_block *,void *),

      int (*set)(struct super_block *,void *),

      void *data)

      {

      struct super_block *s = NULL;

      struct super_block *old;

      int err;

      retry:

      spin_lock(&sb_lock);

      if (test) {

      list_for_each_entry(old, &type->fs_supers, s_instances) {

      if (!test(old, data))

      continue;

      if (!grab_super(old))

      goto retry;

      if (s) {

      up_write(&s->s_umount);

      destroy_super(s);

      }

      return old;

      }

      }

      if (!s) {/*如果找不到sb,從內(nèi)存中申請一個*/

      spin_unlock(&sb_lock);

      s = alloc_super(type);

      if (!s)

      return ERR_PTR(-ENOMEM);

      goto retry;

      }

      err = set(s, data);

      if (err) {

      spin_unlock(&sb_lock);

      up_write(&s->s_umount);

      destroy_super(s);

      return ERR_PTR(err);

      }

      /*初始化得到的sb結(jié)構(gòu)*/

      s->s_type = type;

      strlcpy(s->s_id, type->name, sizeof(s->s_id));

      /*加入鏈表尾*/

      list_add_tail(&s->s_list, &super_blocks);

      list_add(&s->s_instances, &type->fs_supers);

      spin_unlock(&sb_lock);

      get_filesystem(type);

      return s;

      }

      [cpp] view plain copy print?

      /*所有超級塊對象都以雙向循環(huán)鏈表的形式鏈接在一起,量表中第一個

      元素用super_blocks變量表示,而超級塊對象的s_list字段存放指向鏈表

      相鄰元素的指針*/

      LIST_HEAD(super_blocks);

      [cpp] view plain copy print?

      /**

      * alloc_super - create new superblock

      * @type: filesystem type superblock should belong to

      *

      * Allocates and initializes a new &struct super_block. alloc_super()

      * returns a pointer new superblock or %NULL if allocation had failed.

      */

      static struct super_block *alloc_super(struct file_system_type *type)

      {

      /*從內(nèi)存中申請sb*/

      struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER);

      static const struct super_operations default_op;

      if (s) {

      if (security_sb_alloc(s)) {

      kfree(s);

      s = NULL;

      goto out;

      }

      /*初始化*/

      INIT_LIST_HEAD(&s->s_files);

      INIT_LIST_HEAD(&s->s_instances);

      INIT_HLIST_HEAD(&s->s_anon);

      INIT_LIST_HEAD(&s->s_inodes);

      INIT_LIST_HEAD(&s->s_dentry_lru);

      init_rwsem(&s->s_umount);

      mutex_init(&s->s_lock);

      lockdep_set_class(&s->s_umount, &type->s_umount_key);

      /*

      * The locking rules for s_lock are up to the

      * filesystem. For example ext3fs has different

      * lock ordering than usbfs:

      */

      lockdep_set_class(&s->s_lock, &type->s_lock_key);

      /*

      * sget() can have s_umount recursion.

      *

      * When it cannot find a suitable sb, it allocates a new

      * one (this one), and tries again to find a suitable old

      * one.

      *

      * In case that succeeds, it will acquire the s_umount

      * lock of the old one. Since these are clearly distrinct

      * locks, and this object isn't exposed yet, there's no

      * risk of deadlocks.

      *

      * Annotate this by putting this lock in a different

      * subclass.

      */

      down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);

      s->s_count = S_BIAS;

      atomic_set(&s->s_active, 1);

      mutex_init(&s->s_vfs_rename_mutex);

      mutex_init(&s->s_dquot.dqio_mutex);

      mutex_init(&s->s_dquot.dqonoff_mutex);

      init_rwsem(&s->s_dquot.dqptr_sem);

      init_waitqueue_head(&s->s_wait_unfrozen);

      s->s_maxbytes = MAX_NON_LFS;

      s->dq_op = sb_dquot_ops;

      s->s_qcop = sb_quotactl_ops;

      s->s_op = &default_op;

      s->s_time_gran = 1000000000;

      }

      out:

      return s;

      }

      kill_litter_super的過程相反,這里不再寫了。

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

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

      關(guān)于__setup宏

      __setup宏來注冊關(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)核在啟動時輸入串中含有string時,內(nèi)核要去

      執(zhí)行_handler。String必須以“=”符結(jié)束以使parse_args更方便解析。緊隨“=”后的任何文本都會作為輸入傳給

      _handler。下面的例子來自于init/do_mounts.c,其中root_dev_setup作為處理程序被注冊給“root=”關(guān)鍵字:

      __setup("root=", root_dev_setup);

      比如我們在啟動向參數(shù)終有

      noinitrd root=/dev/mtdblock2 console=/linuxrc

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

      [cpp] view plain copy print?

      static int __init root_dev_setup(char *line)

      {

      strlcpy(saved_root_name, line, sizeof(saved_root_name));

      return 1;

      }

      __setup("root=", root_dev_setup);

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

      [cpp] view plain copy print?

      /*

      * Prepare the namespace - decide what/where to mount, load ramdisks, etc.

      */

      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

      *

      * Note: this is a potential source of long boot delays.

      * For example, it is not atypical to wait 5 seconds here

      * for the touchpad of a laptop to initialize.

      */

      wait_for_device_probe();

      /*創(chuàng)建/dev/ram0,必須得,因為initrd要放到/dev/ram0里*/

      md_run_setup();

      if (saved_root_name[0]) {/*saved_root_name為從啟動參數(shù)"root"中獲取的設(shè)備文件名*/

      root_device_name = saved_root_name;

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

      !strncmp(root_device_name, "ubi", 3)) {/*如果設(shè)備名開頭為這兩個*/

      mount_block_root(root_device_name, root_mountflags);

      goto out;

      }

      /*主設(shè)備號和次設(shè)備號*/

      ROOT_DEV = name_to_dev_t(root_device_name);

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

      root_device_name += 5;/*濾掉'/dev/'字符*/

      }

      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);

      async_synchronize_full();

      }

      is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;

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

      ROOT_DEV = Root_RAM0;

      /*實際操作*/

      mount_root();

      out:

      devtmpfs_mount("dev");/*devfs從虛擬的根文件系統(tǒng)的/dev umount*/

      sys_mount(".", "/", NULL, MS_MOVE, NULL);/*將掛載點從當(dāng)前目錄【/root】(在mount_root函數(shù)中設(shè)置的)移到根目錄*/

      /*當(dāng)前目錄即【/root】(真正文件系統(tǒng)掛載的目錄)做為系統(tǒng)根目錄*/

      sys_chroot(".");

      }

      mount_root操作

      [cpp] view plain copy print?

      void __init mount_root(void)

      {

      #ifdef CONFIG_ROOT_NFS

      if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {

      if (mount_nfs_root())

      return;

      printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");

      ROOT_DEV = Root_FD0;

      }

      #endif

      #ifdef CONFIG_BLK_DEV_FD

      if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {

      /* rd_doload is 2 for a dual initrd/ramload setup */

      if (rd_doload==2) {

      if (rd_load_disk(1)) {

      ROOT_DEV = Root_RAM1;

      root_device_name = NULL;

      }

      } else

      change_floppy("root floppy");

      }

      #endif

      #ifdef CONFIG_BLOCK/*這里是一般流程*/

      create_dev("/dev/root", ROOT_DEV);/*用系統(tǒng)調(diào)用創(chuàng)建"/dev/root"*/

      mount_block_root("/dev/root", root_mountflags);

      #endif

      }

      [cpp] view plain copy print?

      void __init mount_block_root(char *name, int flags)

      {

      /*從cache中分配空間*/

      char *fs_names = __getname_gfp(GFP_KERNEL

      | __GFP_NOTRACK_FALSE_POSITIVE);

      char *p;

      #ifdef CONFIG_BLOCK

      char b[BDEVNAME_SIZE];

      #else

      const char *b = name;

      #endif

      /*獲得文件系統(tǒng)類型,如果在bootoption里有,

      則就為這個文件系統(tǒng)類型,如果沒有指定,

      則返回ilesytem鏈上所有類型,下面再對每個進行嘗試.*/

      get_fs_names(fs_names);

      retry:

      for (p = fs_names; *p; p += strlen(p)+1) {

      /*實際的安裝工作,這里調(diào)用了mount系統(tǒng)調(diào)用

      將文件系統(tǒng)掛到/root目錄,p為文件系統(tǒng)類型,由get_fs_names得到

      */

      int err = do_mount_root(name, p, flags, root_mount_data);

      switch (err) {

      case 0:

      goto out;

      case -EACCES:

      flags |= MS_RDONLY;

      goto retry;

      case -EINVAL:

      continue;

      }

      /*

      * Allow the user to distinguish between failed sys_open

      * and bad superblock on root device.

      * and give them a list of the available devices

      */

      #ifdef CONFIG_BLOCK

      __bdevname(ROOT_DEV, b);

      #endif

      printk("VFS: Cannot open root device \"%s\" or %s\n",

      root_device_name, b);

      printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");

      printk_all_partitions();

      #ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT

      printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "

      "explicit textual name for \"root=\" boot option.\n");

      #endif

      panic("VFS: Unable to mount root fs on %s", b);

      }

      printk("List of all partitions:\n");

      printk_all_partitions();

      printk("No filesystem could mount root, tried: ");

      for (p = fs_names; *p; p += strlen(p)+1)

      printk(" %s", p);

      printk("\n");

      #ifdef CONFIG_BLOCK

      __bdevname(ROOT_DEV, b);

      #endif

      panic("VFS: Unable to mount root fs on %s", b);

      out:

      putname(fs_names);

      }

      [cpp] view plain copy print?

      static int __init do_mount_root(char *name, char *fs, int flags, void *data)

      {

      /*mount系統(tǒng)調(diào)用來做實際的安裝文件系統(tǒng)工作*/

      int err = sys_mount(name, "/root", fs, flags, data);

      if (err)

      return err;

      /*改變當(dāng)前路徑到根目錄*/

      sys_chdir("/root");

      ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;

      printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",

      current->fs->pwd.mnt->mnt_sb->s_type->name,

      current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ?

      " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));

      return 0;

      }

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

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

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

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

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

      5,移動rootfs文件系統(tǒng)根目錄上得已經(jīng)安裝文件系統(tǒng)的安裝點;

      rootfs特殊文件系統(tǒng)沒有被卸載,他只是隱藏在基于磁盤的根文件系統(tǒng)下了。

    655506