Browse Source

Filesystem Lab (#24)

Co-authored-by: Jomo <[email protected]>
Jomo 1 year ago
parent
commit
978b452c00
32 changed files with 374 additions and 98 deletions
  1. 0 0
      docs/.vuepress/public/DragonOS/DragonOS.png
  2. BIN
      docs/.vuepress/public/DragonOS/IndexNode_open_and_close.png
  3. BIN
      docs/.vuepress/public/DragonOS/SYS_CLOSE.png
  4. BIN
      docs/.vuepress/public/DragonOS/SYS_OPEN.png
  5. BIN
      docs/.vuepress/public/DragonOS/SYS_OPEN_truncate.png
  6. BIN
      docs/.vuepress/public/DragonOS/binding.png
  7. BIN
      docs/.vuepress/public/DragonOS/crate_my_ramfs.png
  8. BIN
      docs/.vuepress/public/DragonOS/do_migrate.png
  9. BIN
      docs/.vuepress/public/DragonOS/my_test_Makefile.png
  10. BIN
      docs/.vuepress/public/DragonOS/my_test_dadk.png
  11. BIN
      docs/.vuepress/public/DragonOS/test_fstat_Makefile.png
  12. BIN
      docs/.vuepress/public/DragonOS/test_fstat_dadk.png
  13. BIN
      docs/.vuepress/public/DragonOS/truncate.png
  14. 0 0
      docs/.vuepress/public/DragonOS/vfs_archi_design.png
  15. BIN
      docs/.vuepress/public/DragonOS/vfs_init_mkdir.png
  16. BIN
      docs/.vuepress/public/DragonOS/vfs_init_mount.png
  17. 0 0
      docs/.vuepress/public/Linux/FIFO_result.png
  18. 0 0
      docs/.vuepress/public/Linux/MLFQ_principle.png
  19. 0 0
      docs/.vuepress/public/Linux/MLFQ_result.png
  20. 0 0
      docs/.vuepress/public/Linux/RR-result.png
  21. 0 0
      docs/.vuepress/public/Linux/cfs-equity.png
  22. 0 0
      docs/.vuepress/public/Linux/cfs-result.png
  23. 0 0
      docs/.vuepress/public/Linux/process.png
  24. 0 0
      docs/.vuepress/public/Linux/tree.png
  25. 349 0
      docs/DragonOS/Assignment/Lab1.md
  26. 17 90
      docs/DragonOS/Lab/Lab1.md
  27. 1 1
      docs/Linux/Assignment/Lab2.md
  28. 1 1
      docs/Linux/Lab/Lab2.md
  29. 2 2
      docs/Linux/Lab/Lab3/CFS.md
  30. 2 2
      docs/Linux/Lab/Lab3/MLFQ.md
  31. 1 1
      docs/Linux/Lab/Lab3/RR.md
  32. 1 1
      docs/Linux/Lab/Lab4/FIFO.md

+ 0 - 0
docs/.vuepress/public/DragonOS.png → docs/.vuepress/public/DragonOS/DragonOS.png


BIN
docs/.vuepress/public/DragonOS/IndexNode_open_and_close.png


BIN
docs/.vuepress/public/DragonOS/SYS_CLOSE.png


BIN
docs/.vuepress/public/DragonOS/SYS_OPEN.png


BIN
docs/.vuepress/public/DragonOS/SYS_OPEN_truncate.png


BIN
docs/.vuepress/public/DragonOS/binding.png


BIN
docs/.vuepress/public/DragonOS/crate_my_ramfs.png


BIN
docs/.vuepress/public/DragonOS/do_migrate.png


BIN
docs/.vuepress/public/DragonOS/my_test_Makefile.png


BIN
docs/.vuepress/public/DragonOS/my_test_dadk.png


BIN
docs/.vuepress/public/DragonOS/test_fstat_Makefile.png


BIN
docs/.vuepress/public/DragonOS/test_fstat_dadk.png


BIN
docs/.vuepress/public/DragonOS/truncate.png


+ 0 - 0
docs/.vuepress/public/vfs_archi_design.png → docs/.vuepress/public/DragonOS/vfs_archi_design.png


BIN
docs/.vuepress/public/DragonOS/vfs_init_mkdir.png


BIN
docs/.vuepress/public/DragonOS/vfs_init_mount.png


+ 0 - 0
docs/.vuepress/public/FIFO_result.png → docs/.vuepress/public/Linux/FIFO_result.png


+ 0 - 0
docs/.vuepress/public/MLFQ_principle.png → docs/.vuepress/public/Linux/MLFQ_principle.png


+ 0 - 0
docs/.vuepress/public/MLFQ_result.png → docs/.vuepress/public/Linux/MLFQ_result.png


+ 0 - 0
docs/.vuepress/public/RR-result.png → docs/.vuepress/public/Linux/RR-result.png


+ 0 - 0
docs/.vuepress/public/cfs-equity.png → docs/.vuepress/public/Linux/cfs-equity.png


+ 0 - 0
docs/.vuepress/public/cfs-result.png → docs/.vuepress/public/Linux/cfs-result.png


+ 0 - 0
docs/.vuepress/public/process.png → docs/.vuepress/public/Linux/process.png


+ 0 - 0
docs/.vuepress/public/tree.png → docs/.vuepress/public/Linux/tree.png


+ 349 - 0
docs/DragonOS/Assignment/Lab1.md

@@ -0,0 +1,349 @@
+## 实验内容
+
+ramfs的基本功能在/kernel/src/filesystem/ramfs/mod.rs中,实现过程中请参考文件../vfs/mod.rs以及已实现函数的相关代码和注释。在实现基本的文件操作之前,需要先实现创建文件结构的辅助函数:create_with_data。其用于创建文件时,在父目录下创建带初始化数据的inode。
+
+>**练习1:**实现位于/kernel/src/filesystem/ramfs/mod.rs中的 create_with_data。
+
+```rust
+    // 该函数用于在当前目录下创建一个新的inode,并传入一个简单的data字段,方便进行初始化。
+    // 需要判断当前inode是否是文件且是否重名,接着创建inode进行初始化。
+    fn create_with_data(
+        &self,
+        name: &str,
+        file_type: FileType,
+        mode: u32,
+        data: usize,
+    ) -> Result<Arc<dyn IndexNode>, SystemError> {
+        // 获取当前inode
+        let mut inode = self.0.lock();
+        
+        // LAB TODO BEGIN
+
+        // LAB TODO END
+
+        // 初始化inode的自引用的weak指针
+        result.0.lock().self_ref = Arc::downgrade(&result);
+
+        // 将子inode插入父inode的B树中
+        inode.children.insert(String::from(name), result.clone());
+
+        return Ok(result);
+    }
+```
+
+文件读写是文件系统的基本功能,ramfs的读写操作会将文件数据块中内容读入内存缓冲区,或将缓冲区内容写入对应文件数据块。read_at和 write_at两个函数分别用于以一定偏移量读取和写入一段长度的数据,并且返回实际的读写字节长度 (读取不能超过文件大小)
+
+
+
+>**练习2:**实现位于/kernel/src/filesystem/ramfs/mod.rs中的 read_at和 write_at。
+
+```rust
+    // 该函数用于实现对文件以一定偏移量读取一段长度的数据,并且返回实际的读字节长度。
+    // 首先检查当前inode是否为一个文件,然后计算读文件的偏移量,最后拷贝数据(copy_from_slice)。
+    fn read_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &mut [u8],
+        _data: &mut FilePrivateData,
+    ) -> Result<usize, SystemError> {
+        if buf.len() < len {
+            return Err(SystemError::EINVAL);
+        }
+        // 加锁
+        let inode: SpinLockGuard<RamFSInode> = self.0.lock();
+
+        // LAB TODO BEGIN
+
+        // LAB TODO END
+
+        return Ok(src.len());
+    }
+
+    // 该函数用于实现对文件以一定偏移量写一段长度的数据,并且返回实际的写字节长度。
+    // 首先检查当前inode是否为一个文件,如果文件大小比原来的大,那就resize这个数组,最后将数据写入(copy_from_slice)。
+    fn write_at(
+        &self,
+        offset: usize,
+        len: usize,
+        buf: &[u8],
+        _data: &mut FilePrivateData,
+    ) -> Result<usize, SystemError> {
+        if buf.len() < len {
+            return Err(SystemError::EINVAL);
+        }
+
+        // 加锁
+        let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
+
+        // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
+        if inode.metadata.file_type == FileType::Dir {
+            return Err(SystemError::EISDIR);
+        }
+
+        // LAB TODO BEGIN
+
+        // LAB TODO END
+
+        return Ok(len);
+    }
+```
+
+
+
+> **练习3:**模仿ramfs实现my_ramfs,并更正ramfs
+
+原ramfs其实是有点小问题的,需要在my_ramfs更正后再测试,具体如下:
+
+
+
+**open和close**
+
+测试代码中打开文件调用的open函数,最终会进行系统调用,在**kernel/src/syscall**中,标志是**SYS_OPEN**
+
+![图片1](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/SYS_OPEN.png)
+
+检查文件路径正确后会调用同级目录下的**syscall.rs**中的open函数
+
+
+
+测试代码中的关闭文件调用close函数也和open类似,标志为**SYS_CLOSE**,然后调用**syscall.rs**中的close函数
+
+![图片2](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/SYS_CLOSE.png)
+
+
+
+再看**kernel/vfs/mod.rs**的IndexNode接口中
+
+![图片3](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/IndexNode_open_and_close.png)
+
+如果文件系统没有具体实现open和close函数,就返回不支持,所以这就是出错的原因
+
+
+
+**解决方式:**
+
+在我们模仿的ramfs文件系统里,添加open和close函数的具体实现,如下:
+
+```rust
+fn open(&self, _data: &mut FilePrivateData, _mode: &super::vfs::file::FileMode) -> Result<(), SystemError> {
+    return Ok(());
+}
+
+fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
+    return Ok(());
+}
+```
+
+
+
+**fopen**
+
+测试代码中我们用到了fopen来打开文件,第二个参数的"w+"的含义可以在**user/libs/libc/src/stdio.c**文件中查看,表示读写文件,并且如果文件不存在的话就创建这个文件
+
+
+
+fopen的系统调用也是SYS_OPEN,但是和open的区别在于:
+
+![图片4](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/SYS_OPEN_truncate.png)
+
+fopen在满足条件的情况下会调用truncate函数,这个函数和open、close一样,也是定义在**vfs/mod.rs**中的IndexNode接口中,但是没有具体实现,需要文件系统自己实现,如下:
+![图片5](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/truncate.png)
+
+
+
+**解决方式:**
+
+所以需要在我们模仿的ramfs中,添加truncate的具体实现,如下:
+
+```rust
+fn truncate(&self, _len: usize) -> Result<(), SystemError> {
+    let mut inode = self.0.lock();
+    if inode.metadata.file_type == FileType::Dir {
+        return Err(SystemError::EISDIR);
+    }
+    inode.data.resize(_len,0);
+    return Ok(());
+}
+```
+
+## 测试文件系统
+
+测试我们模仿实现的my_ramfs
+
+### 创建测试文件夹
+
+在**DragonOS/user/apps**目录下新建一个文件夹**my_test**
+
+### 配置文件
+
+#### 拷贝文件
+
+找到**DragonOS/user/apps**目录下其他测试文件夹(例如:test_fstat)的两个文件:**link.lds** + **Makefile**,将这两个文件拷贝到我们新建的测试文件夹**my_test**中
+
+#### 更改Makefile内容
+
+将**Makefile**中的测试目录名改回来,假设拷贝的是test_fstat目录的,则按如下修改:
+
+**test_fstat/Makefile**
+
+![图片6](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/test_fstat_Makefile.png)
+
+
+
+**my_test/Makefile**
+
+![图片7](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/my_test_Makefile.png)
+
+将代码里的**test_fstat**改为**my_test**(**PS:**注意区分大小写)
+
+### 配置dadk
+
+#### 拷贝文件
+
+在**DragonOS/user/dadk/config**目录下模仿其它文件新建一个文件**my_test-0.1.0.dadk**(**PS:**这里的my_test和我们在第一步创建的测试目录名相同),然后拷贝其他文件的内容到里面,比如拷贝**test_fstat-0.1.0.dadk**
+
+#### 更改dadk内容
+
+还是和 2.2 类似,按如下修改:
+
+**test_fstat-0.1.0.dadk**
+
+![图片8](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/test_fstat_dadk.png)
+
+
+
+**my_test-0.1.0.dadk**
+
+![图片9](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/my_test_dadk.png)
+
+将代码里的**test_fstat**都改成**my_test**
+
+### 挂载文件系统
+
+将你要测试的文件系统挂载到我们的操作系统上面
+
+打开**DragonOS/kernel/src/filesystem/vfs/core.rs**文件
+
+#### 导入
+
+导入你自己实现的文件系统,比如我这里是模仿ramfs写了一个my_ramfs,就按如下添加:
+![图片10](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/crate_my_ramfs.png)
+
+#### 创建文件夹、实例并挂载
+
+在**vfs_init**函数中:
+
+
+
+模仿其它文件系统创建当前准备测试的文件系统的文件夹,如下:
+
+![图片11](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/vfs_init_mkdir.png)
+
+
+
+紧接着在下面创建ramfs实例,并挂载,照样是模仿其它文件系统挂载,如下:
+
+![图片12](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/vfs_init_mount.png)
+
+#### 迁移伪文件系统的inode
+
+在**migrate_virtual_filesystem**函数中:
+
+##### 获取inode,
+
+模仿其它文件系统获取ramfs的inode,如下:
+
+![图片13](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/binding.png)
+
+##### 迁移到新的文件系统下
+
+![图片14](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/do_migrate.png)
+
+### 开始测试
+
+至此,我们就可以开始测试文件系统了。
+
+在之前我们新建的测试文件夹**DragonOS/user/apps/my_test**目录下添加**main.c**文件,用来测试文件系统的开、关、读、写
+
+
+
+测试的过程中会出现一些问题,具体原因在接下来的**ramfs的更正**中
+
+```c
+#include<sys/types.h>
+#include<sys/stat.h>
+#include<fcntl.h>
+#include<unistd.h>
+#include<stdio.h>
+
+int main(){
+    //需要先创建文件夹
+    int check=-1;
+    check = mkdir("/ram/test_0",0777);
+    if(check!=0){
+        printf("Cannot create dir: /ram/test_0\n");
+        return;
+    }
+    check=-1;
+    check = mkdir("/ram/test_1",0777);
+    if(check!=0){
+        printf("Cannot create dir: /ram/test_1\n");
+        return;
+    }
+
+    //测试open+close+write+read
+    printf("Test open/close/write/read\n");
+    int fd=-1;
+    fd=open("/ram/test_0/file_0.txt",O_WRONLY | O_CREAT);
+    if(fd<0){
+        printf("Open file failed!\n");
+        return;
+    }
+    printf("File opened successfully!\n");
+    const char* write_ptr = "Write str here";
+    write(fd,write_ptr,strlen(write_ptr));
+    printf("Having written:%s\n",write_ptr);
+    close(fd);
+    printf("File closed successfully!\n");
+
+    //测试open+close+read
+    fd=open("/ram/test_0/file_0.txt",O_WRONLY | O_CREAT);
+    if(fd<0){
+        printf("Open file failed!\n");
+        return;
+    }
+    printf("File opened successfully!\n");
+    char* buf[64];
+    read(fd,buf,64);
+    printf("Having read:%s\n",buf);
+    close(fd);
+    printf("File closed successfully!\n");
+
+    //测试fopen+fclose+fputs
+    printf("\nTest fopen/fclose/fputs/fgets\n");
+    FILE* file = fopen("/ram/test_1/file_0.txt","w+");
+    if(file == NULL){
+        printf("Fopen file failed!\n");
+        return;
+    }
+    printf("File opened successfully!\n");
+    const char* fputs_ptr = "Fputs str here";
+    fputs(fputs_ptr,file);
+    printf("Having fput: %s\n",fputs_ptr);
+    fclose(file);
+    printf("File closed successfully!\n");
+
+    //测试fopen+fclose+fgets
+    file = fopen("/ram/test_1/file_0.txt","r+");
+    if(file==NULL){
+        printf("Fopen file failed!\n");
+        return;
+    }
+    char* buf1[64];
+    fgets(buf1,64,file);
+    printf("Having got: %s\n",buf1);
+    fclose(file);
+    printf("File closed successfully!\n");
+}
+```

+ 17 - 90
docs/DragonOS/Lab/Lab1.md

@@ -24,7 +24,7 @@ sidebar: auto
 
 如图所示:
 
-![图片1](../.vuepress/public/../../../.vuepress/public/DragonOS.png '文件系统架构设计')
+![图片1](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/DragonOS.png '文件系统架构设计')
 
 其中我们可以看到,中间部分作为接口对多个并行的物理文件系统实例(每一个都叫做文件系统的实现)提供支持。这就是虚拟文件系统。
 
@@ -50,7 +50,7 @@ VFS是DragonOS文件系统的核心,它提供了一套统一的文件系统接
 
 ## VFS的架构设计
 
-![图片2](../.vuepress/public/../../../.vuepress/public/vfs_archi_design.png 'vfs架构设计')
+![图片2](/OS_lab_tutorial/docs/.vuepress/public/DragonOS/vfs_archi_design.png 'vfs架构设计')
 
 ### File
 
@@ -202,91 +202,18 @@ pub struct MountFSInode {
 
 对于大部分的操作,MountFS都是直接转发给具体的文件系统,而不做任何处理。同时,为了支持跨文件系统的操作,比如在目录树上查找,每次`lookup`操作或者是`find`操作,都会通过`MountFSInode`的对应方法,判断当前inode是否为挂载点,并对挂载点进行特殊处理。如果发现操作跨越了具体文件系统的边界,MountFS就会将操作转发给下一个文件系统,并执行Inode替换。这个功能的实现,也是通过在普通的Inode结构体外面,套一层MountFSInode结构体来实现的。
 
-## 实验内容
-
-ramfs的基本功能在/kernel/src/filesystem/ramfs/mod.rs中,实现过程中请参考文件../vfs/mod.rs以及已实现函数的相关代码和注释。在实现基本的文件操作之前,需要先实现创建文件结构的辅助函数:create_with_data。其用于创建文件时,在父目录下创建带初始化数据的inode。
-
->练习1:实现位于/kernel/src/filesystem/ramfs/mod.rs中的 create_with_data。
-
-```rust
-    // 该函数用于在当前目录下创建一个新的inode,并传入一个简单的data字段,方便进行初始化。
-    // 需要判断当前inode是否是文件且是否重名,接着创建inode进行初始化。
-    fn create_with_data(
-        &self,
-        name: &str,
-        file_type: FileType,
-        mode: u32,
-        data: usize,
-    ) -> Result<Arc<dyn IndexNode>, SystemError> {
-        // 获取当前inode
-        let mut inode = self.0.lock();
-        
-        // LAB TODO BEGIN
-
-        // LAB TODO END
-
-        // 初始化inode的自引用的weak指针
-        result.0.lock().self_ref = Arc::downgrade(&result);
-
-        // 将子inode插入父inode的B树中
-        inode.children.insert(String::from(name), result.clone());
-
-        return Ok(result);
-    }
-```
-
-文件读写是文件系统的基本功能,ramfs的读写操作会将文件数据块中内容读入内存缓冲区,或将缓冲区内容写入对应文件数据块。read_at和 write_at两个函数分别用于以一定偏移量读取和写入一段长度的数据,并且返回实际的读写字节长度 (读取不能超过文件大小)。
-
->练习2:实现位于/kernel/src/filesystem/ramfs/mod.rs中的 read_at和 write_at。
-
-```rust
-    // 该函数用于实现对文件以一定偏移量读取一段长度的数据,并且返回实际的读字节长度。
-    // 首先检查当前inode是否为一个文件,然后计算读文件的偏移量,最后拷贝数据(copy_from_slice)。
-    fn read_at(
-        &self,
-        offset: usize,
-        len: usize,
-        buf: &mut [u8],
-        _data: &mut FilePrivateData,
-    ) -> Result<usize, SystemError> {
-        if buf.len() < len {
-            return Err(SystemError::EINVAL);
-        }
-        // 加锁
-        let inode: SpinLockGuard<RamFSInode> = self.0.lock();
-
-        // LAB TODO BEGIN
-
-        // LAB TODO END
-
-        return Ok(src.len());
-    }
-
-    // 该函数用于实现对文件以一定偏移量写一段长度的数据,并且返回实际的写字节长度。
-    // 首先检查当前inode是否为一个文件,如果文件大小比原来的大,那就resize这个数组,最后将数据写入(copy_from_slice)。
-    fn write_at(
-        &self,
-        offset: usize,
-        len: usize,
-        buf: &[u8],
-        _data: &mut FilePrivateData,
-    ) -> Result<usize, SystemError> {
-        if buf.len() < len {
-            return Err(SystemError::EINVAL);
-        }
-
-        // 加锁
-        let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
-
-        // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
-        if inode.metadata.file_type == FileType::Dir {
-            return Err(SystemError::EISDIR);
-        }
-
-        // LAB TODO BEGIN
-
-        // LAB TODO END
-
-        return Ok(len);
-    }
-```
+## RamFS
+
+ramfs是vfs下具体实现的一种基于RAM做存储的文件系统,主要实现了以下功能:
+
+- **read_at**:读
+- **write_at**:写
+- **poll**:获取文件状态
+- **resize**:重置用于存放数据的data的大小
+- **create_with_data**:创建自带数据的文件
+- **link**:链接
+- **unlink**:解链接
+- **rmdir:**删除文件夹
+- **move_**:移动文件
+- **find**:查找文件
+- **list**:显示当前文件夹下的内容

+ 1 - 1
docs/Linux/Assignment/Lab2.md

@@ -34,7 +34,7 @@ int main()
 
 编写程序创建进程树如图所示,在每个进程中显示当前进程标识getpid()和父进程标识getppid()。
 
-![图片1](/OS_lab_tutorial/docs/.vuepress/public/tree.png '进程树')
+![图片1](/OS_lab_tutorial/docs/.vuepress/public/Linux/tree.png '进程树')
 
 ### 信号通信
 

+ 1 - 1
docs/Linux/Lab/Lab2.md

@@ -24,7 +24,7 @@ sidebar: auto
 
 进程创建的过程示意图如下所示:
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/process.png" alt="图片1" title="进程的创建" style="zoom: 67%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/process.png" alt="图片1" title="进程的创建" style="zoom: 67%;" />
 
 ### 系统调用fork()
 

+ 2 - 2
docs/Linux/Lab/Lab3/CFS.md

@@ -98,7 +98,7 @@
 
 以图说话:左图则为Round Robin算法的结果,右图则为CFS的结果,体现了equality和equity的区别。
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/cfs-equity.png" alt="image-20230710104508212" style="zoom:50%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/cfs-equity.png" alt="image-20230710104508212" style="zoom:50%;" />
 
 
 
@@ -275,7 +275,7 @@ int main() {
 
 ## 实验结果
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/cfs-result.png" alt="image-20230710173552858" style="zoom:80%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/cfs-result.png" alt="image-20230710173552858" style="zoom:80%;" />
 
 
 

+ 2 - 2
docs/Linux/Lab/Lab3/MLFQ.md

@@ -8,7 +8,7 @@
 
 ​	该算法有多个队列,同一 个队列中的进程优先级相同,不同队列中的进程优 先级不同; 最高优先级上的进程运行一个时间片,次 高级上的进程运行两个时间片,再下一级运行四个 时间片,以此类推; 每当一个进程在一个优先级队列 中用完它的时间片后,就下移一级,进入另一个队 列; 在低优先级队列中等待时间过长的进程,将被移 入高优先级队列; 调度程序将该进程从等待队列中 释放后提高其优先级。
 
-​	<img src="/OS_lab_tutorial/docs/.vuepress/public/MLFQ_principle.png" alt="image-20230713191830436" style="zoom:80%;" />
+​	<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/MLFQ_principle.png" alt="image-20230713191830436" style="zoom:80%;" />
 
 ​	MLFQ的设计可以根据具体需求进行调整和改进,例如,可以调整队列数量、时间片长度、优先级提升规则等来适应不同的系统环境和应用场景。该调度策略在实践中常用于操作系统中,以平衡系统的吞吐量和响应时间,同时为不同类型的进程提供适当的执行机会。
 
@@ -165,7 +165,7 @@ int main() {
 
 ## 实验结果
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/MLFQ_result.png" alt="image-20230713194336736" style="zoom:80%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/MLFQ_result.png" alt="image-20230713194336736" style="zoom:80%;" />
 
 
 

+ 1 - 1
docs/Linux/Lab/Lab3/RR.md

@@ -117,7 +117,7 @@ int main() {
 
 ## 实验结果
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/RR-result.png" alt="image-20230710171839016" style="zoom:80%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/RR-result.png" alt="image-20230710171839016" style="zoom:80%;" />
 
 
 

+ 1 - 1
docs/Linux/Lab/Lab4/FIFO.md

@@ -104,7 +104,7 @@ int main() {
 
 ## 实验样例
 
-<img src="/OS_lab_tutorial/docs/.vuepress/public/FIFO_result.png" alt="image-20230713200134638" style="zoom:80%;" />
+<img src="/OS_lab_tutorial/docs/.vuepress/public/Linux/FIFO_result.png" alt="image-20230713200134638" style="zoom:80%;" />