Skip to content

Latest commit

 

History

History
141 lines (113 loc) · 4.64 KB

File metadata and controls

141 lines (113 loc) · 4.64 KB

chapter6 练习

编程作业

硬链接

硬链接要求两个不同的目录项指向同一个文件,在我们的文件系统中也就是两个不同名称目录项指向同一个磁盘块。

本节要求实现三个系统调用 linkatunlinkatfstat

linkat

fn linkat(&self, _caller: Caller, _olddirfd: i32, oldpath: usize, _newdirfd: i32, newpath: usize, _flags: u32) -> isize
  • 参数:
    • olddirfd, newdirfd: 仅为了兼容性考虑,本次实验中始终为 AT_FDCWD (-100),可以忽略。
    • flags: 仅为了兼容性考虑,本次实验中始终为 0,可以忽略。
    • oldpath:原有文件路径
    • newpath: 新的链接文件路径。
  • 说明:
    • 为了方便,不考虑新文件路径已经存在的情况(属于未定义行为)。除非出现新旧名字一致的情况,此时需要返回 -1。
    • 返回值:如果出现了错误则返回 -1,否则返回 0。
  • 可能的错误:
    • 链接同名文件。

unlinkat:

fn unlinkat(&self, _caller: Caller, _dirfd: i32, path: usize, _flags: u32) -> isize
  • 参数:
    • dirfd: 仅为了兼容性考虑,本次实验中始终为 AT_FDCWD (-100),可以忽略。
    • flags: 仅为了兼容性考虑,本次实验中始终为 0,可以忽略。
    • path:文件路径。
  • 说明:
    • 注意考虑使用 unlink 彻底删除文件的情况,此时需要回收 inode 以及它对应的数据块。
  • 返回值:如果出现了错误则返回 -1,否则返回 0。
  • 可能的错误:
    • 文件不存在。

fstat:

  • syscall ID: 80
  • 功能:获取文件状态。
fn fstat(&self, _caller: Caller, fd: usize, st: usize) -> isize
  • 参数:
    • fd: 文件描述符
    • st: 文件状态结构体指针
// Stat 结构体和 StatMode 结构体已在 syscall/src/fs.rs 中定义
#[repr(C)]
#[derive(Debug)]
pub struct Stat {
    /// 文件所在磁盘驱动器号,该实验中写死为 0 即可
    pub dev: u64,
    /// inode 文件所在 inode 编号
    pub ino: u64,
    /// 文件类型
    pub mode: StatMode,
    /// 硬链接数量,初始为 1
    pub nlink: u32,
    /// 无需考虑,为了兼容性设计
    pad: [u64; 7],
}

bitflags! {
    pub struct StatMode: u32 {
        const NULL  = 0;
        /// directory
        const DIR   = 0o040000;
        /// ordinary regular file
        const FILE  = 0o100000;
    }
}

HINT

  • linkatunlinkat 的文件路径 path 的读取可参考 tg-rcore-tutorial-ch6/src/main.rs 中的 open 系统调用实现。
  • fstat 的文件状态结构体 Stat 指针 st 的写入可参考 tg-rcore-tutorial-ch6/src/main.rs 中的 clock_gettime 系统调用对 TimeSpec 的写入实现。

实验要求

  • 在 tg-rcore-tutorial-ch6 目录下完成实验。
  • 目录结构说明:
tg-rcore-tutorial-ch6/
├── Cargo.toml(内核配置文件,需要修改依赖配置)
├── src/(内核源代码,需要修改)
│   ├── main.rs(内核主函数,包括系统调用接口实现)
│   ├── fs.rs(文件系统相关)
│   ├── process.rs(进程结构)
│   ├── processor.rs(进程管理器)
│   └── virtio_block.rs(VirtIO 块设备实现)
├── tg-rcore-tutorial-easy-fs/(文件系统实现,需要拉取到本地并修改以支持硬链接)
│   └── src/
│       ├── lib.rs
│       └── ...
└── tg-rcore-tutorial-user/(用户程序,运行时自动拉取,无需修改)
    └── src/bin(测试用例)

说明

  • tg-rcore-tutorial-user 会在运行时自动拉取到 tg-rcore-tutorial-ch6/tg-rcore-tutorial-user 目录下
  • tg-rcore-tutorial-easy-fs 需要拉取到本地才能修改其代码以支持硬链接
    • 在 tg-rcore-tutorial-ch6 目录下执行 cargo clone tg-rcore-tutorial-easy-fs 拉取到本地
    • 在 tg-rcore-tutorial-ch6/Cargo.toml 中修改 tg-rcore-tutorial-easy-fs 为本地路径:
      [dependencies]
      tg-rcore-tutorial-easy-fs = { path = "./tg-rcore-tutorial-easy-fs" }
  • 运行练习测例:
cargo run --features exercise

然后在终端中输入 tg-rcore-tutorial-ch6_usertest 运行,这个测例打包了所有你需要通过的测例。

  • 测试练习测例:
./test.sh exercise

说明

  • 你的内核必须前向兼容,需要能通过前一章的所有测例