0 00:00:00,000 --> 00:00:06,920 1 00:00:06,960 --> 00:00:07,760 那最后一部分呢 2 00:00:07,800 --> 00:00:09,320 我们来给大家介绍一下 3 00:00:09,360 --> 00:00:11,880 这个文件系统的执行流程 4 00:00:11,920 --> 00:00:13,160 这里面举了两个例子 5 00:00:13,200 --> 00:00:15,720 第一个例子是关于文件系统怎么启动 6 00:00:15,760 --> 00:00:17,200 第二个呢 是看一下 7 00:00:17,240 --> 00:00:20,280 当用户程序发出open操作的时候 8 00:00:20,320 --> 00:00:22,440 我们整个这个执行过程是怎么回事 9 00:00:22,480 --> 00:00:26,240 首先看一下这个文件系统初始化过程 10 00:00:26,280 --> 00:00:29,240 从总控函数kern_init开始 11 00:00:29,280 --> 00:00:31,880 专门增加一个fs_init 12 00:00:31,920 --> 00:00:33,920 这是lab8增加内容 13 00:00:33,960 --> 00:00:36,160 在这里面呢fs_init呢 14 00:00:36,200 --> 00:00:38,200 进一步展开会分成三部分 15 00:00:38,240 --> 00:00:41,160 第一个是虚拟文件系统的初始化 16 00:00:41,200 --> 00:00:43,160 第二个是关于设备初始化 17 00:00:43,200 --> 00:00:44,720 第三个是SFS 18 00:00:44,760 --> 00:00:49,320 就是simple file system的初始化过程 19 00:00:49,360 --> 00:00:51,920 我们再把这个vfs_init呢看一下 20 00:00:51,960 --> 00:00:54,160 它干什么事情 第一建一个链表 21 00:00:54,200 --> 00:00:56,280 就是专门针对device的list 22 00:00:56,320 --> 00:00:58,560 使得它可以在后续过程中 23 00:00:58,600 --> 00:01:01,720 管理这些device的fs 24 00:01:01,760 --> 00:01:04,000 第二个呢是设置一个信号量 25 00:01:04,040 --> 00:01:07,240 这是由于很多对共享资源的操作呢 26 00:01:07,280 --> 00:01:11,920 需要信号量来进行保护 27 00:01:11,960 --> 00:01:14,560 那么对于dev_init呢 就是device_init呢 28 00:01:14,600 --> 00:01:15,960 它包含了三部分工作 29 00:01:16,000 --> 00:01:18,720 第一个初始化device 30 00:01:18,760 --> 00:01:21,440 disk stdin和stdout 31 00:01:21,480 --> 00:01:27,480 这分别代表了三类不同的设备 32 00:01:27,520 --> 00:01:29,280 再接下来是关于这个 33 00:01:29,320 --> 00:01:31,360 simple file system的一个初始化过程 34 00:01:31,400 --> 00:01:33,000 这最主要完成一个mount 35 00:01:33,040 --> 00:01:34,920 就是加载这个文件系统 36 00:01:34,960 --> 00:01:38,800 那么这三部分进一步细化可以看出来 37 00:01:38,840 --> 00:01:40,040 第一部分 是关于这个 38 00:01:40,080 --> 00:01:41,400 dev_list的一个初始化 39 00:01:41,440 --> 00:01:43,040 它主要是初始化一个双向链表 40 00:01:43,080 --> 00:01:44,640 这个双向链表是在我们整个 41 00:01:44,680 --> 00:01:47,600 uCore操作系统里面经常使用的 42 00:01:47,640 --> 00:01:49,800 然后也同样存在一个信号量 43 00:01:49,840 --> 00:01:54,440 来保证对这个list操作一个互斥的保护 44 00:01:54,480 --> 00:01:56,960 第二部分关于device的init 45 00:01:57,000 --> 00:02:01,440 它会分别去调用disk0的device_init 46 00:02:01,480 --> 00:02:04,360 stdin和stdout的device_init 47 00:02:04,400 --> 00:02:05,840 那么这后两部分呢 48 00:02:05,880 --> 00:02:07,240 我们在前面也给大家做了介绍 49 00:02:07,280 --> 00:02:09,360 它怎么完成它的初始化过程 50 00:02:09,400 --> 00:02:11,400 这个disk0的初始化过程 51 00:02:11,440 --> 00:02:16,880 希望大家能够自己去看一下 52 00:02:16,920 --> 00:02:18,800 对于simple file system而言 53 00:02:18,840 --> 00:02:20,600 它的这个mount过程包含两部分 54 00:02:20,640 --> 00:02:22,120 第一部分是vfs_mount 55 00:02:22,160 --> 00:02:25,920 以及具体的一个SFS一个do_mount 56 00:02:25,960 --> 00:02:27,400 那么在这个do_mount里面呢 57 00:02:27,440 --> 00:02:30,080 它会完成把自身SFS 58 00:02:30,120 --> 00:02:31,840 和VFS建立一个连接 59 00:02:31,880 --> 00:02:33,720 然后呢把它的根目录 60 00:02:33,760 --> 00:02:35,840 能够让我们的uCore 61 00:02:35,880 --> 00:02:37,040 操作系统能感知得到 62 00:02:37,080 --> 00:02:39,800 使得接下来的 针对这个文件系统的 63 00:02:39,840 --> 00:02:42,800 一个读写操作能够正常执行 64 00:02:42,840 --> 00:02:44,960 那这就是我们文件系统 65 00:02:45,000 --> 00:02:47,960 一个大致初始化过程 66 00:02:48,000 --> 00:02:53,560 这是整个一个初始化一个流程图 67 00:02:53,600 --> 00:02:54,840 接下来我们再看一下 68 00:02:54,880 --> 00:02:57,560 对于一个文件 我们要打开它 69 00:02:57,600 --> 00:02:59,360 便于后续的读 或者写操作 70 00:02:59,400 --> 00:03:01,760 大致执行什么事情 71 00:03:01,800 --> 00:03:03,640 这是应用程序通常的写法 72 00:03:03,680 --> 00:03:05,360 Open一个file 73 00:03:05,400 --> 00:03:06,440 那么这是一个字符串 74 00:03:06,480 --> 00:03:07,640 代表文件的名字 75 00:03:07,680 --> 00:03:09,400 它可能带一些目录 76 00:03:09,440 --> 00:03:11,720 它位于某一个目录下一个文件 77 00:03:11,760 --> 00:03:13,120 这是一个字符串 78 00:03:13,160 --> 00:03:14,640 那么如果这个open操作 79 00:03:14,680 --> 00:03:16,640 正常地执行结束的话 80 00:03:16,680 --> 00:03:18,400 它会返回一个fd 81 00:03:18,440 --> 00:03:20,840 那么这个fd代表了文件 82 00:03:20,880 --> 00:03:22,200 在这个进程控制块中的 83 00:03:22,240 --> 00:03:24,040 一个文件链表中一个位置 84 00:03:24,080 --> 00:03:25,240 从而可以根据这个位置 85 00:03:25,280 --> 00:03:28,720 能访问更具体的file信息 86 00:03:28,760 --> 00:03:29,840 那么当我们应用程序 87 00:03:29,880 --> 00:03:31,440 执行open操作之后呢 88 00:03:31,480 --> 00:03:34,440 它会进一步调系统调用 sys_open 89 00:03:34,480 --> 00:03:37,120 然后呢发出sys_call 这个系统调用 90 00:03:37,160 --> 00:03:40,360 sys_open这么一个信息 91 00:03:40,400 --> 00:03:42,640 然后让我们操作系统做进一步处理 92 00:03:42,680 --> 00:03:45,040 这是第一部分工作 93 00:03:45,080 --> 00:03:45,880 我们操作系统 94 00:03:45,920 --> 00:03:47,360 在接受到这个操作之后呢 95 00:03:47,400 --> 00:03:51,640 它会通过进一步sys_open呢来往下处理 96 00:03:51,680 --> 00:03:52,720 那么可以看出来 97 00:03:52,760 --> 00:03:56,320 它会把文件名的字符串一步步往下传 98 00:03:56,360 --> 00:03:59,680 然后到这儿 那么它会分配一个 99 00:03:59,720 --> 00:04:02,120 Fd_array中的一个项给它 100 00:04:02,160 --> 00:04:03,440 那么这个index 101 00:04:03,480 --> 00:04:05,160 就是我们最终要访问那个fd 102 00:04:05,200 --> 00:04:07,080 但是 需要注意是 103 00:04:07,120 --> 00:04:09,600 这里面fd所对应那个file 104 00:04:09,640 --> 00:04:11,720 它里面inode信息还没有 105 00:04:11,760 --> 00:04:14,600 所以我们进一步要把文件名 106 00:04:14,640 --> 00:04:17,640 所实际对应的inode信息给建立起来 107 00:04:17,680 --> 00:04:19,240 这就需要我们进一步去处理 108 00:04:19,280 --> 00:04:22,120 做vfs_open操作 109 00:04:22,160 --> 00:04:24,320 但是我们知道 vfs_open呢 110 00:04:24,360 --> 00:04:25,480 它只是一个壳 111 00:04:25,520 --> 00:04:28,080 它需要去找到具体文件系统 112 00:04:28,120 --> 00:04:30,480 做进一步打开操作 113 00:04:30,520 --> 00:04:32,920 有两方面 第一方面是要有一个 114 00:04:32,960 --> 00:04:36,480 查找文件名和inode对应信息 115 00:04:36,520 --> 00:04:39,320 一旦找到之后 会把inode信息 116 00:04:39,360 --> 00:04:41,000 给加载到内存中来 117 00:04:41,040 --> 00:04:43,440 成为我们操作系统能够进一步去访问的 118 00:04:43,480 --> 00:04:46,960 一个很重要一个关键数据结构 119 00:04:47,000 --> 00:04:49,440 那么lookup干什么 120 00:04:49,480 --> 00:04:51,480 vfs_lookup会进一步调什么呢 121 00:04:51,520 --> 00:04:53,240 大家想一想 122 00:04:53,280 --> 00:04:56,600 我们说这个lookup就要查找一个文件名 123 00:04:56,640 --> 00:04:58,840 包含了目录也包含文件名本身 124 00:04:58,880 --> 00:04:59,920 这么一个字符串 125 00:04:59,960 --> 00:05:03,120 把所对应的inode是什么 126 00:05:03,160 --> 00:05:08,240 我们需要进一步去看一下 127 00:05:08,280 --> 00:05:11,760 前面的vfs_lookup最终会调到SFS 128 00:05:11,800 --> 00:05:13,680 就simple file system的lookup 129 00:05:13,720 --> 00:05:15,200 这里面它会根据path 130 00:05:15,240 --> 00:05:16,880 就我们刚才说的文件名信息 131 00:05:16,920 --> 00:05:19,600 来一步步的 递归地查找 132 00:05:19,640 --> 00:05:22,160 一个文件它所对应的inode是多少 133 00:05:22,200 --> 00:05:23,920 因为它首先要查找到 134 00:05:23,960 --> 00:05:25,560 这个文件所在的目录 135 00:05:25,600 --> 00:05:27,120 假设我们这里面只有一级目录 136 00:05:27,160 --> 00:05:29,480 那会把这个目录所对应的inode找着 137 00:05:29,520 --> 00:05:31,280 然后查找这个inode里面 138 00:05:31,320 --> 00:05:33,160 所对应的目录项 139 00:05:33,200 --> 00:05:34,960 看目录项里面的文件名 140 00:05:35,000 --> 00:05:38,680 是否和path里面的最终文件名是一致的 141 00:05:38,720 --> 00:05:39,840 如果是一致的 142 00:05:39,880 --> 00:05:41,400 也意味着找着了这个文件 143 00:05:41,440 --> 00:05:44,440 它会把inode对应文件名给取出来 144 00:05:44,480 --> 00:05:47,200 然后进一步去load inode 145 00:05:47,240 --> 00:05:49,960 从而可以把inode的信息 146 00:05:50,000 --> 00:05:52,760 从硬盘加载到我们内存中来 147 00:05:52,800 --> 00:05:54,840 你看这里面 sfs_load_inode 148 00:05:54,880 --> 00:05:58,280 会进一步调sfs_rbuf 就是read buffer 149 00:05:58,320 --> 00:06:00,920 而这一个会进一步device的I/O 150 00:06:00,960 --> 00:06:04,520 最终会访问到IDE的read sector 151 00:06:04,560 --> 00:06:08,360 这个操作是我们硬盘驱动的一个函数 152 00:06:08,400 --> 00:06:10,040 从而把所需要的信息 153 00:06:10,080 --> 00:06:12,800 一层一层再返回到我们应用态 154 00:06:12,840 --> 00:06:18,800 那这就是整个open操作的执行过程 155 00:06:18,840 --> 00:06:21,560 好 那我们把lab8的文件系统呢 156 00:06:21,600 --> 00:06:23,280 给大家做了一个讲解 157 00:06:23,320 --> 00:06:25,720 可以看着这里面涉及的层次很多 158 00:06:25,760 --> 00:06:28,120 数据结构很多 调用关系很复杂 159 00:06:28,160 --> 00:06:30,360 但是相对而言 它整个调用关系 160 00:06:30,400 --> 00:06:32,760 是一个串行的一个调用关系 161 00:06:32,800 --> 00:06:35,640 而包含数据结构的依赖关系呢 162 00:06:35,680 --> 00:06:38,040 也是相对来说比较直观 163 00:06:38,080 --> 00:06:39,680 从上层到底层 164 00:06:39,720 --> 00:06:42,040 底层又返回来引用上层 165 00:06:42,080 --> 00:06:45,200 那这个过程呢 虽然数据量比较大 166 00:06:45,240 --> 00:06:48,040 但是大家通过阅读代码 调试 167 00:06:48,080 --> 00:06:51,320 和具体执行 我相信能够很好地掌握 168 00:06:51,360 --> 00:06:53,600 关于文件系统这一块的内容 169 00:06:53,640 --> 00:06:55,400 一旦完成了文件系统这一块内容呢 170 00:06:55,440 --> 00:06:59,000 我们可以让我们的uCore OS 171 00:06:59,040 --> 00:07:01,080 可以很好访问文件系统中 172 00:07:01,120 --> 00:07:02,600 存在那些文件 173 00:07:02,640 --> 00:07:05,320 去执行 或者读写操作 174 00:07:05,360 --> 00:07:06,480 完成了lab8之后呢 175 00:07:06,520 --> 00:07:08,760 我想大家应该有一定的收获 176 00:07:08,800 --> 00:07:10,960 可以对操作系统有更深入的理解 177 00:07:11,000 --> 00:07:13,600 同时我们也提供了进一步labx 178 00:07:13,640 --> 00:07:17,000 这个labx是希望大家在常规练习之后 179 00:07:17,040 --> 00:07:19,640 去做一些更有挑战一些练习 180 00:07:19,680 --> 00:07:21,160 我们称之为challenge练习 181 00:07:21,200 --> 00:07:22,840 我们在uCoreLab中也给大家列出了 182 00:07:22,880 --> 00:07:24,320 一系列的challenge练习 183 00:07:24,360 --> 00:07:26,960 如果大家对操作系统有兴趣 184 00:07:27,000 --> 00:07:29,600 那我们欢迎大家去迎接新的挑战 185 00:07:29,640 --> 00:07:30,880 好 谢谢大家 186 00:07:30,920 --> 00:07:30,960