<em id="0a85b"><option id="0a85b"></option></em>

<abbr id="0a85b"></abbr>

      <nobr id="0a85b"></nobr>
        <tr id="0a85b"></tr>
        9久久伊人精品综合,亚洲一区精品视频在线,成 人免费va视频,国产一区二区三区黄网,99国产精品永久免费视频,亚洲毛片多多影院,精品久久久无码人妻中文字幕,无码国产欧美一区二区三区不卡
        學習啦 > 學習電腦 > 操作系統 > Linux教程 > linux安裝文件系統

        linux安裝文件系統

        時間: 春健736 分享

        linux安裝文件系統

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

          安裝linux文件系統

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

          安裝根文件系統分為兩個階段:

          1,內核安裝特殊rootfs文件系統,該文件系統僅提供一個作為初始安裝點的空目錄

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

          [cpp] view plain copy print?

          /*初始化根文件系統*/

          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.

          */

          /*注冊一個新的文件系統*/

          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;

          }

          根文件系統定義如下

          [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,

          };

          下面看看他的兩個函數

          [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結構*/

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

          if (IS_ERR(s))

          return PTR_ERR(s);

          s->s_flags = flags;

          /*這里實際調用ramfs_fill_super,對sb結構的屬性進行設置*/

          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);/*設置mnt和sb關聯*/

          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

          */

          /*查找或創建一個sb結構*/

          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,從內存中申請一個*/

          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結構*/

          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?

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

          元素用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)

          {

          /*從內存中申請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的過程相反,這里不再寫了。

          構造根目錄是由init_mount_tree()函數實現的,該函數在前面已經介紹過了。

          2,安裝實際根文件系統

          關于__setup宏

          __setup宏來注冊關鍵字及相關聯的處理函數,__setup宏在include/linux/init.h中定義,其原型如下:

          __setup(string, _handler);

          其中:string是關鍵字,_handler是關聯處理函數。__setup只是告訴內核在啟動時輸入串中含有string時,內核要去

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

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

          __setup("root=", root_dev_setup);

          比如我們在啟動向參數終有

          noinitrd root=/dev/mtdblock2 console=/linuxrc

          setup_arch解釋時會發現root=/dev/mtdblock2,然后它就會調用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();

          /*創建/dev/ram0,必須得,因為initrd要放到/dev/ram0里*/

          md_run_setup();

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

          root_device_name = saved_root_name;

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

          !strncmp(root_device_name, "ubi", 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;/*濾掉'/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從虛擬的根文件系統的/dev umount*/

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

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

          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);/*用系統調用創建"/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

          /*獲得文件系統類型,如果在bootoption里有,

          則就為這個文件系統類型,如果沒有指定,

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

          get_fs_names(fs_names);

          retry:

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

          /*實際的安裝工作,這里調用了mount系統調用

          將文件系統掛到/root目錄,p為文件系統類型,由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系統調用來做實際的安裝文件系統工作*/

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

          if (err)

          return err;

          /*改變當前路徑到根目錄*/

          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;

          }

          到此,根文件系統的安裝過程算是完成了,中間關于mount等系統調用將在后面分析。可以看出總的步驟主要有:

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

          2,從系統啟動參數中獲取設備文件名以及設備號;

          3,調用系統調用創建符號鏈接,并調用mount系統調用進程實際的安裝操作;

          4,改變進程當前目錄;

          5,移動rootfs文件系統根目錄上得已經安裝文件系統的安裝點;

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

        655506 主站蜘蛛池模板: 九九热在线精品免费视频| 国产极品美女高潮抽搐免费网站| 亚洲中文字幕系列第1页| 精品国产亚洲区久久露脸| 狠狠色婷婷久久综合频道日韩| 日韩人妻无码一区二区三区综合部| 亚洲毛片无码专区亚洲乱| 亚洲人成网站18禁止无码| 日韩人妻一区中文字幕| 亚洲欧美日韩综合一区在线 | 成人午夜在线观看刺激| 亚洲av精选一区二区| 国产日韩AV免费无码一区二区三区| 永久免费av无码网站直播| 狠狠色狠狠综合久久| 久久久久综合中文字幕| 区一区二区三区中文字幕| 高潮迭起av乳颜射后入| 国产主播一区二区三区| 无码丰满少妇2在线观看| 2021av在线天堂网| 亚洲一区sm无码| 亚洲av无码一区二区乱子仑| 国产老妇伦国产熟女老妇高清| 六十熟妇乱子伦视频| 亚洲第一无码AV无码专区| 日韩精品亚洲精品第一页| 免费观看又色又爽又黄的韩国| 麻豆精品一区综合av在线| 好男人2019在线视频播放观看| 日本理伦片午夜理伦片| 日韩一区二区三区三级| 永久免费无码av在线网站| 久久99精品国产99久久6尤物| 黑人异族巨大巨大巨粗| 大尺度国产一区二区视频| 日本美女性亚洲精品黄色| 日韩卡一卡2卡3卡4卡| 成人免费无码大片a毛片| 国产成人综合亚洲欧美日韩| 9lporm自拍视频区|