磁盘的结构
[ boot block | sb block | log | inode blocks | free bit map | data blocks ] |
- 超级块里有一个魔数用来验证文件系统
- 超级块里保存了日志区,inode区,位图区的起始位置
- 超级块里保存了日志区,inode区,数据区和整个镜像的大小
函数的功能
/*
* 作用: 依据块的使用情况写位图区
* int : 已经使用的块的数量
* 原理:
*/
void balloc(int);
/*
* 作用:向指定扇区写入数据。
* sec : sect No.
* *buf : 要写入扇区的数据。
* 原理:首先用lseek系统调用定位到扇区所在的位置,然后用write系统调用把arg2写入到对应扇区。
*/
void wsect(uint, void*);
/*
* 作用: 依据inode的编号把它对应的数据结构写入到硬盘的inode区
* uint: inode的编号。
* struct dinode*: 用来指向inode对应的数据结构
* 原理:
*/
void winode(uint, struct dinode*);
/*
* 作用:依据inode的编号获取它的数据结构
* inum : inode的编号
* *ip : 用来指向inode对应的数据结构
* 原理:
*/
void rinode(uint inum, struct dinode *ip);
/*
* 作用:从指定扇区读出数据
* sec : sect No.
* *buf : 缓冲区地址。
* 原理 : 首先用lseek系统调用定位到扇区所在的位置,然后用read系统调用从对应扇区把数据读到缓冲区里。
*/
void rsect(uint sec, void *buf);
/*
* 作用 : 分配一个inode
* type : inode类型,有目录、文件、设备三种类型
* 返回值 : inode号
* 原理 : 分配一个inode号并初始化一个dinode数据结构,然后调用winode把这个数据结构写入到inode区里inode号对应的位置。
*/
uint ialloc(ushort type);
/*
* 作用 : 向inode里添加内容
* inum : inode号
* *xp : 要添加的信息的指针
* n : 要添加的信息的大小
* 原理 : 首先得到这个文件的大小,把它赋值给off变量。 进而得到当前文件末尾的块编号fbn,进而得到分配的块号x。然后以buf为缓冲区,把不大于1个块的内容写入x号块。调整n,off,p的值,并持续循环,直到把所有的内容都写到块里。最后,修改inode的属性,并调用winode把inode的信息再写回磁盘。
*/
void iappend(uint inum, void *p, int n);
格式化的过程
本程序的功能是创建一个格式化的镜像。至少要有两个参数,第一个参数是镜像名称,第二个及以后的参数是要放到镜像里的文件的名称。镜像有1000个块,每个块1KB,故镜像大小为1M。
数据结构de代表了目录文件里的每一项。
字符数组buf的大小是一个块的大小,这样可以方便地把buf里的数据写入到扇区里。
整数freeinode代表了空闲inode的编号。每分配出一个inode它就执行加1操作。
首先,使用系统调用open,以第一个参数为文件名创建一个文件,其文件描述符赋值给fsfd。
然后,计算各个数据区的大小。
- 启动块和超级块点两个块。
- 日志块nlog占30个块,inode块ninodeblocks占的块数(即inode的总数200除以每个块可以保存的inode数据结构的数量,其值为13),位图占用的块数nbitmap,其值为1。
- 如上的块组成元数据区nmeta,共占46个块。
- 除了元数据区,镜像空间剩下的即为数据区nblocks,共占954个块。
然后,填充超级块的数据结构。xint的作用是让数字满足内存里的表示形式,即低位放在低字节,高位放在高字节。
然后,在for循环里调用wsect函数把整个镜像填充为0。
然后,把超级块的内容写入到1号扇区。
然后,为根目录分配一个inode号rootino。
然后,为根目录添加条目.
和..
。
然后,在一个for循环里,把要传入的文件依次复制到镜像的根目录下。
然后,修改根目录所对应的inode的数据结构的size属性。
最后,执行balloc函数,把数据块的使用情况写入到位图区。