硬链接要求两个不同的目录项指向同一个文件,在我们的文件系统中也就是两个不同名称目录项指向同一个磁盘块。
本节要求实现三个系统调用 linkat、unlinkat、fstat。
linkat:
- syscall ID: 37
- 功能:创建一个文件的一个硬链接,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:
- syscall ID: 35
- 功能:取消一个文件路径到文件的链接,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;
}
}linkat和unlinkat的文件路径 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- 你的内核必须前向兼容,需要能通过前一章的所有测例