[自制操作系统] JOS文件系统详解&支持工作路径&MSH

本文详述了JOS操作系统中文件系统的实现,包括IDE、block cache、文件系统服务器等,并介绍了如何支持工作路径,实现list目录、创建文件等功能。此外,文章还涵盖了管道通信和屏幕输入输出的实现,以及对MSH的增强。
摘要由CSDN通过智能技术生成

这里写图片描述
本文分为两部分:
第一部分将详细分析JOS的文件系统及文件描述符的实现方法。
第二部分将实现工作路径,提供新的系统调用,完善用户空间工具。
本文中支持的新特性:

  • 支持进程工作目录 提供getcwdchdir

  • 新的syscall

    • SYS_env_set_workpath 修改工作路径
  • 新的用户程序
    • ls 功能完善
    • pwd 输出当前工作目录
    • cat 接入工作目录
    • touch 由于文件属性没啥可改的,用于创建文件
    • mkdir 创建目录文件
    • msh 更高级的shell 还未完全完工 支持cd 支持默认二进制路径为 bin
  • 调整目标磁盘生成工具

Github:https://github.com/He11oLiu/MOS

JOS文件系统详解

文件系统总结

      Regular env           FS env
   +---------------+   +---------------+
   |      read     |   |   file_read   |
   |   (lib/fd.c)  |   |   (fs/fs.c)   |
...|.......|.......|...|.......^.......|...............
   |       v       |   |       |       | RPC mechanism
   |  devfile_read |   |  serve_read   |
   |  (lib/file.c) |   |  (fs/serv.c)  |
   |       |       |   |       ^       |
   |       v       |   |       |       |
   |     fsipc     |   |     serve     |
   |  (lib/file.c) |   |  (fs/serv.c)  |
   |       |       |   |       ^       |
   |       v       |   |       |       |
   |   ipc_send    |   |   ipc_recv    |
   |       |       |   |       ^       |
   +-------|-------+   +-------|-------+
           |                   |
           +-------------------+
  • 底层与磁盘有关的丢给ide_xx来实现,因为要用到IO中断,要给对应的权限
  • 通过bc_pgfault来实现缺页自己映射,利用flush_block来回写磁盘
  • 然后通过分block利用block cache实现对于磁盘的数据读入内存或者写回磁盘
  • 再上面一层的file_readfile_write,均是对于blk的操作。
  • 再上面就是文件系统服务器,通过调用file_read实现功能了。
  • 客户端通过对需求打包,发送IPC给文件系统服务器,即可实现读/写文件的功能。

文件系统&文件描述符 Overview

JOS文件系统是直接映射到内存空间DISKMAPDISKMAP + DISKSIZE这块空间。故其支持的文件系统最大为3GB.

IDE ide.c

文件系统底层PIO驱动放在ide.c中。注意在IDE中,是以硬件的角度来看待硬盘,其基本单位是sector,不是block

  • bool ide_probe_disk1(void) 用于检测disk1是否存在。
  • voidide_set_disk(int diskno) 用于设置目标磁盘。
  • ide_read ide_write 用于磁盘读写。

block cache bc.c

文件系统在内存中的映射是基于block cache的。以一个block为单位在内存中为其分配单元。注意在bc中,是以操作系统的角度来看待硬盘,其基本单位是block,不是sector

  • void *diskaddr(uint32_t blockno) 用于查找blockno在地址空间中的地址。

  • blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE 用于查找addr对应文件系统中的blockno

  • static void bc_pgfault(struct UTrapframe *utf) 用于处理读取不在内存中而出现page fault的情况。这时需要从file system通过PIO读取到block cache(也就是内存中新分配的一页)中,并做好映射。

  • void flush_block(void *addr) 用于写回硬盘,写回时清理PTE_D标记。

file system fs.c

文件系统是基于刚才的block cache和底层ide驱动的。

bitmap 相关

bitmap每一位代表着一个block的状态,用位操作检查/设置block状态即可。

  • bool block_is_free(uint32_t blockno) 用于check给定的blockno是否是空闲的。

  • void free_block(uint32_t blockno) 设置对应位为0

  • int alloc_block(void) 设置对应位为1

文件系统操作

  • void fs_init(void) 初始化文件系统。检测disk1是否存在,检测super blockbitmap block

  • static int file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc) 用于找到文件ffilenoblockblocknoalloc用于控制当f_indirect不存在的时候,是否需要新申请一个block

  • int file_get_block(struct File *f, uint32_t filebno, char **blk) 用于找到文件ffilenoblock的地址。

  • static int dir_lookup(struct File *dir, const char *name, struct File **file) 用于在dir下查找name这个文件。其遍历读取dir这个文件,并逐个判断其目录下每一个文件的名字是否相等。

  • static int dir_alloc_file(struct File *dir, struct File **file)dir下新申请一个file。同样也是遍历所有的dir下的文件。找到第一个名字为空的文件,并把新的文件存在这里。

  • static int walk_path(const char *path, struct File **pdir, struct File **pf, char *lastelem) 用于从根目录获取path的文件,文件放在pf中,路径放在pdir中。如果找到了路径没有找到文件。最后的路径名放在lastelem中,最后的路径放在pdir中。

文件操作

  • int file_create(const char *path, struct File **pf) 用于创建文件。

  • int file_open(const char *path, struct File **pf) 打开文件。

  • ssize_t file_read(struct File *f, void *buf, size_t count, off_t offset)foffset读取countbytes的数据放入buf中。

  • int file_write(struct File *f, const void *buf, size_t count, off_t offset) 与上面的类似。

  • static int file_free_block(struct File *f, uint32_t filebno) 删除文件中的filebno

  • static void file_truncate_blocks(struct File *f, off_t newsize) 缩短文件大小。

  • int file_set_size(struct File *f, off_t newsize) 修改文件大小。

  • void file_flush(struct File *f) 将文件写回硬盘

  • void fs_sync(void) 将所有的文件写回硬盘

文件系统服务器 serv.c

  • 服务器主要逻辑umain: 初始化文件系统,初始化服务器,开始接收请求。

  • 服务器具体函数见上面实现。

  • int openfile_alloc(struct OpenFile **o)用于服务器分配一个openfile结构体

文件描述符 fd.c

  • struct fd 结构体

    struct Fd {
    int fd_dev_id;
    off_t fd_offset;
    int fd_omode;
    union {
        // File server files
        struct FdFile fd_file;
    };
    };

    其中fd_file用于发送的时候传入服务器对应的fileid

    包括了fd_id 文件读取的offset,读取模式以及FdFile

  • int fd2num(struct Fd *fd)fd获取其编号

  • char* fd2data(struct Fd *fd)fd获取文件内容

  • int fd_alloc(struct Fd **fd_store) 查找到第一个空闲的fd,并分配出去。

  • int fd_lookup(int fdnum, struct Fd **fd_store) 为查找fdnum的fd,并放在fd_store中。

  • int fd_close(struct Fd *fd, bool must_exist) 用于关闭并free一个fd

  • int dev_lookup(int dev_id, struct Dev **dev) 获取不同的Device

  • int close(int fdnum) 关闭fd

  • void close_all(void) 关闭全部

  • int dup(int oldfdnum, int newfdnum) dup不是简单的复制,而是要将两个fd的内容完全同步,其是通过虚拟内存映射做到的。

  • read(int fdnum, void *buf, size_t n) 后面的与这个类似

    • 获取fdfd_dev_id并根据其获取dev
    • 调用dev对应的function
  • int seek(int fdnum, off_t offset) 用于设置fdoffset

  • int fstat(int fdnum, struct Stat *stat) 获取文件状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值