ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

lab5学习

2022-06-15 22:02:02  阅读:139  来源: 互联网

标签:文件 struct int File lab5 学习 file 磁盘


文件系统所涉及的代码文件众多, 此处介绍部分代码文件的主要功能来为大家建立初步的印象。我们将通过 fs/fsformat.c 来创建磁盘镜像,在 fs/fs.c 中实现文件系统的基本功能函数,文件系统进程通过 fs/ide.c 与磁盘镜像进行交互,其进程主要运行在 fs/serv.c 上,并在 fs/serv.c 中通过 IPC 通信与用户进程 user/fsipc.c 内的通信函数进行交互;用户进程在 user/file.c 中实现用户接口,并在 user/fd.c 中引入文件描述符,抽象地操作文件、管道等内容。(注:fs.h 头文件存在于 fs/fs.h 和 include/fs.h 中,其内容并不相同)

一个磁盘块4096字节,一个扇区512字节

文件控制块(File 结构体)

文件服务流程

用户进程调用fd.c的函数read,wirte,seek等函数,fd.c的函数根据fd调用对应的ide的函数,比如ide为file,则file.c的函数调用fsipc.c的函数,fsipc.c中的fsipc_xxx通过设置请求,调用fsipc函数将请求发送到文件进程的REQVA的页面上,文件进程根据请求类型调用不同处理函数

Offset Effect
0x0000 Write: Set the offset (in bytes) from the beginning of the disk image.
This offset will be used for the next read/write operation.
即设置与磁盘镜像开头的偏移
0x0008 Write: Set the high 32 bits of the offset (in bytes). (*)
设置偏移量的高32位(以字节为单位)
0x0010 Write: Select the IDE ID to be used in the next read/write operation
选择要在下一次读/写操作中使用的IDE的ID
0x0020 Write: Start a read or write operation. (Writing 0 means a Read operat
ion, a 1 means a Write operation.)
写入:启动读取或写操作。(写入0表示读取操作,写入1表示写入操作。)
写入一个字节即可
0x0030 Read: Get status of the last operation. (Status 0 means failure, non-zero
means success.)
读取:获取上一次操作的状态。(状态0表示失败,非零表示成功。)
0x4000-0x41f Read/Write: 512 bytes data buffer.
读/写:512字节的数据缓冲区。

make clean && make &&/OSLAB/gxemul -E testmips -C R3000 -M 64 -d gxemul/fs.img gxemul/vmlinux

磁盘块

struct Block {
    uint8_t data[BY2BLK];
    uint32_t type;
} disk[NBLOCK]; //block of disk

超级块

struct Super {
	u_int s_magic; // Magic number: FS_MAGIC
	u_int s_nblocks; // Total number of blocks on disk 1024
	struct File s_root; // Root directory node
};

• s_magic:魔数,用于识别该文件系统,为一个常量。

• s_nblocks:记录本文件系统有多少个磁盘块,本文件系统为 1024。

• s_root为根目录,其f_type为FTYPE_DIR,f_name为”/”。

超级块初始化

disk[1].type = BLOCK_SUPER;
super.s_magic = FS_MAGIC;
super.s_nblocks = NBLOCK;
super.s_root.f_type = FTYPE_DIR;
strcpy(super.s_root.f_name, "/");

文件控制块

struct File {
    u_char f_name[MAXNAMELEN];  // filename
    u_int f_size;           // file size in bytes
    u_int f_type;           // file type
    u_int f_direct[NDIRECT];
    u_int f_indirect;

    struct File *f_dir;     // the pointer to the dir where this file is in, valid only in memory.
    u_char f_pad[BY2FILE - MAXNAMELEN - 4 - 4 - NDIRECT * 4 - 4 - 4];
};

f_name为文件名称,文件名的最大长度 MAXNAMELEN 值为 128。

f_size为文件的大小,单位为字节。

f_type为文件类型,有普通文件 (FTYPE_REG) 和文件夹 (FTYPE_DIR) 两种。

f_direct[NDIRECT]为文件的直接指针,每个文件控制块设有 10 个直接指针,用来记录文件的数据块在磁盘上的位置。每个磁盘块的大小为 4KB,也就是说,这十个直接指针能够表示最大 40KB的文件,而当文件的大小大于 40KB 时,就需要用到间接指针。

f_indirect指向一个间接磁盘块,用来存储指向文件内容的磁盘块的指针。为了简化计算,我们不使用间接磁
盘块的前十个指针。

f_dir指向文件所属的文件目录。

f_pad则是为了让整数个文件结构体占用一个磁盘块,填充结构体中剩下的字节。

dev

struct Dev {
    int dev_id;
    char *dev_name;
    int (*dev_read)(struct Fd *, void *, u_int, u_int);
    int (*dev_write)(struct Fd *, const void *, u_int, u_int);
    int (*dev_close)(struct Fd *);
    int (*dev_stat)(struct Fd *, struct Stat *);
    int (*dev_seek)(struct Fd *, u_int);
};

fd

struct Fd {
    u_int fd_dev_id;
    u_int fd_offset;
    u_int fd_omode;
};

State

struct Stat {
    char st_name[MAXNAMELEN];
    u_int st_size;
    u_int st_isdir;
    struct Dev *st_dev;
};

Filefd

struct Filefd {
    struct Fd f_fd;
    u_int f_fileid;
    struct File f_file;
};

Open

struct Open {
    struct File *o_file;    // mapped descriptor for open file
    u_int o_fileid;     // file id
    int o_mode;     // open mode
    struct Filefd *o_ff;    // va of filefd page
};

磁盘块类型

enum {
    BLOCK_FREE  = 0,
    BLOCK_BOOT  = 1,
    BLOCK_BMAP  = 2,
    BLOCK_SUPER = 3,
    BLOCK_DATA  = 4,
    BLOCK_FILE  = 5,
    BLOCK_INDEX = 6,
};

文件打开类型

/* File open modes */
#define O_RDONLY    0x0000      /* open for reading only */
#define O_WRONLY    0x0001      /* open for writing only */
#define O_RDWR      0x0002      /* open for reading and writing */
#define O_ACCMODE   0x0003      /* mask for above modes */

#define O_CREAT     0x0100      /* create if nonexistent */
#define O_TRUNC     0x0200      /* truncate to zero length */
#define O_EXCL      0x0400      /* error if already exists */
#define O_MKDIR     0x0800      /* create directory, not regular file */

宏定义

内容 作用
BY2FILE 256 一个文件控制块256字节
NINDIRECT (BY2BLK/4) 文件拥有磁盘块的最大数目
FILE2BLK (BY2BLK/sizeof(struct File)) 一个磁盘块中文件控制块的个数
BY2BLK 4096 一个磁盘块4096字节
MAXNAMELEN 128 文件名最大长度,其值为128,即,文件名不可以超过128个字符。事实上,由于最后一个字符必须是\0,因此,“有效”字符串最大长度为127.
MAXPATHLEN 1024
NDIRECT 10 文件控制块中直接块指针的数量
NINDIRECT 1024 文件控制块中间接块指针可以管理的块数量上限
FTYPE_REG 0 regular file, 常规文件
DISKMAP 0x10000000 磁盘块在内存中的va开始
DISKMAX 0x40000000 磁盘块在内存中最多1GB
INDEX2FD(i) (FDTABLE+(i)*BY2PG) 第i个fd在内存中的va

代码中局部变量名字含义

名字 含义
bno 系统当前使用的磁盘块号
nblk 文件的所占有磁盘总块数

fs.c函数

名字 作用
u_int block_is_mapped(u_int blockno) 检查磁盘块是否映射到虚拟地址
u_int va_is_mapped(u_int va) 检查va是否被映射到磁盘块(二者一一对应)
int file_get_block(struct File *f, u_int filebno, void **blk) 读取文件的第filebo块到内存中,*blk被设置为对应的va
int block_is_free(u_int blockno) 通过位图中的特定位来判断指定的磁盘块是否被占用
u_int diskaddr(u_int blockno) 返回磁盘块对应的虚拟地址
u_int va_is_dirty(u_int va) 检查va的脏位
u_int block_is_dirty(u_int blockno) 检查磁盘块是否有脏位
int map_block(u_int blockno) 分配内存中的一个物理页给对应的磁盘块
void unmap_block(u_int blockno) 解除磁盘块在内存中的映射,如果磁盘块被写过则写回磁盘
int read_block(u_int blockno, void **blk, u_int *isnew) 将第blockno个磁盘块读入内存,*blk被设置为对应的va
void write_block(u_int blockno) 把在内存中的第blockno个磁盘块写回磁盘
int block_is_free(u_int blockno) 判断第blockno个磁盘块是否空闲
void free_block(u_int blockno) 在位图中设置第blockno个磁盘块为空闲
int alloc_block_num(void) 找到第一个空闲的磁盘块,返回块号,并把这个磁盘块写回磁盘(只能位图先设置为1,再执行这个函数)
int alloc_block(void) 分配一个磁盘块,返回块号
int file_block_walk(struct File *f, u_int filebno, u_int **ppdiskbno, u_int alloc) 将*ppdiskbno设置为文件f的第filebno块索引的地址
int file_map_block(struct File *f, u_int filebno, u_int *diskbno, u_int alloc) 将diskbno设置为文件f的第fiebno块对应磁盘块的块号
int file_clear_block(struct File *f, u_int filebno) 释放文件f的第filebno块
int file_get_block(struct File *f, u_int filebno, void **blk) 将文件f的第filebno块读入磁盘,*blk设置为文件f的第filebno块在内存中对应磁盘块的va
int file_dirty(struct File *f, u_int offset) 对文件f的第offset / BY2BLK块设置脏位
int dir_lookup(struct File *dir, char *name, struct File **file) 找到dir下对应的名为name的文件,*file设置为对应的文件控制块指针
int dir_alloc_file(struct File *dir, struct File **file) 找到dir下的一个空闲fcb,*file指向这个fcb
char * skip_slash(char *p) 跳过'/'
int walk_path(char *path, struct File **pdir, struct File **pfile, char *lastelem) 找到path下的文件,*pfile指向这个文件的fcb,*pdir若不为0则指向最后一个目录
int file_open(char *path, struct File **file) *file指向path下最后文件的fcb
int file_create(char *path, struct File **file) *file指向创建的文件控制块
void file_truncate(struct File *f, u_int newsize) 调整文件大小,如果比原来小则释放文件块
int file_set_size(struct File *f, u_int newsize) 调整文件大小,把f的目录flush一遍(写回磁盘)
void file_flush(struct File *f) 把文件f写回磁盘(f的文件块对应的磁盘块修改过才写回)
void fs_sync(void) 所有磁盘块若有脏位则写回磁盘
void file_close(struct File *f) 文件f刷新到磁盘,f的目录也刷新到磁盘
int file_remove(char *path) 把path对应的文件移除(找到文件,文件大小设置为0,刷新文件到磁盘,刷新文件的目录到磁盘)

fsformat.c

名字 作用
void reverse_block(struct Block *b) 翻转磁盘块大小端
void init_disk() 初始化磁盘0块,为BLOCK_BOOT;初始化块2开始为位图块,块1位super块
disk[1].type = BLOCK_SUPER;
super.s_magic = FS_MAGIC;
super.s_nblocks = NBLOCK;
super.s_root.f_type = FTYPE_DIR;
strcpy(super.s_root.f_name, "/");
int file_get_block(struct File *f, u_int filebno, void **blk) 读取文件的第filebo块到内存中,*blk被设置为对应的va
int block_is_free(u_int blockno) 通过位图中的特定位来判断指定的磁盘块是否被占用
int next_block(int type) 设置磁盘块的下一块为类型type,返回磁盘块id
void flush_bitmap() 刷新位图,当前磁盘块使用情况全部在位图标记
void finish_fs(char *name) 将内存中的磁盘块写回磁盘
void save_block_link(struct File *f, int nblk, int bno) 设置文件的第nblk块的对应的磁盘块为bno
int make_link_block(struct File *dirf, int nblk) 调用save_block_link设置索引,并把文件大小加上4096B
struct File *create_file(struct File *dirf) 创建目录下的一个文件,返回这个文件的文件控制块的指针
void write_file(struct File *dirf, const char *path) 写文件到

fd.c

名字 作用
int dev_lookup(int dev_id, struct Dev **dev) 根据devid找到dev,*dev指向对应的dev
int fd_alloc(struct Fd **fd) 分配一个文件描述符,*fd指向这个描述符
void fd_close(struct Fd *fd) 解除fd对内存页的映射
int fd_lookup(int fdnum, struct Fd **fd) 找第fdnum个文件描述符,*fd指向它
u_int fd2data(struct Fd *fd) 返回fd对应的文件的va地址
int fd2num(struct Fd *fd) 返回对应的fd是第几个fd
int num2fd(int fd) 返回第fd个文件描述符的地址
int close(int fdnum) 关闭第fdnum个文件描述符及其对应的文件
void close_all(void) 关闭所有文件
int read(int fdnum, void *buf, u_int n) 第fdnum个fd对应的文件读n个字节到buf
int write(int fdnum, const void *buf, u_int n) 第fdnum个fd对应的文件写n个字节从buf
int seek(int fdnum, u_int offset) 设置第fdnum个fd对应的文件的偏移量为offset

标签:文件,struct,int,File,lab5,学习,file,磁盘
来源: https://www.cnblogs.com/sdjasj/p/16379944.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有