操作系统实验
Lab5
目录
1.思考题解答
2.难点分析
3.思考体会
思考题解答
Thinking 5.1
当外设需要从内存中获取数据时,若数据先保存在 cache 中,则只有该数据在 cache 中的空间被后来的数据申请才会把该数据移到内存中(缓存更新),外设才可以获取这部分数据;会导致不同步或无响应的错误行为。
对于不同的外设:
- 串口设备:每次读写以字节为单位,传输频繁,如果采用这种方式,极易出错。
- IDE 磁盘:每次读写以磁盘块为单位,传输频率较低,采用这种方式出错概率小于串口设备。
Thinking 5.2
#define FILE2BLK (BY2BLK / sizeof(struct File))
可知一个磁盘中最多有 16 个文件控制块。
#define NDIRECT 10
#define NINDIRECT (BY2BLK / 4)
因为不使用 INDRECT 部分的前十个指针,则一个目录文件最多可以使用1024个磁盘块存储数据,因此一个目录下最多1024*16 = 16384个文件。
#define MAXFILESIZE (NINDIRECT * BY2BLK)
可知单个文件最大为 4KB * 1K = 4MB
Thinking 5.3
#define DISKMAX 0x40000000
可知为 1GB
Thinking 5.4
fs/serv.h
#define PTE_DIRTY 0x0002 // file system block cache is dirty
/* IDE disk number to look on for our file system */
#define DISKNO 1
#define BY2SECT 512 /* Bytes per disk sector */
#define SECT2BLK (BY2BLK / BY2SECT) /* sectors to a block */
/* Disk block n, when in memory, is mapped into the file system
* server's address space at DISKMAP+(n*BY2BLK). */
#define DISKMAP 0x10000000
/* Maximum disk size we can handle (1GB) */
#define DISKMAX 0x40000000
定义了磁盘空间的各个基本单位的参数。
user/include/fs.h
// Bytes per file system block - same as page size
#define BY2BLK BY2PG
#define BIT2BLK (BY2BLK * 8)
// Maximum size of a filename (a single path component), including null
#define MAXNAMELEN 128
// Maximum size of a complete pathname, including null
#define MAXPATHLEN 1024
// Number of (direct) block pointers in a File descriptor
// Number of (indirect) block pointers in a File descriptor
#define NDIRECT 10
#define NINDIRECT (BY2BLK / 4)
//Maximum size ofa file
#define MAXFILESIZE (NINDIRECT * BY2BLK)
//Size of a file control block
#define BY2FILE 256
定义了文件控制块和文件本身的限制和参数。
Thinking 5.5
#include <stdio.h>
#include <unistd.h>
int main (void)
{
long pid;
pid = fork();
if(pid == 0){
sleep(3);
FILE* f0 = fopen("/newmotd", "r");
printf("child open file's code is %d\n", f0->_flags);
} else {
sleep(2);
FILE* f1 = fopen("/newmotd", "r");
printf("parent open file's code is %d\n", f1->_flags);
}
return 0;
}
仅平台测试发现,父子进程共享文件描述符和定位指针。
Thinking 5.6
struct File {
char f_name[MAXNAMELEN]; // filename
uint32_t f_size; // file size in bytes
uint32_t f_type; // file type
uint32_t f_direct[NDIRECT];
uint32_t f_indirect;
struct File *f_dir; // the pointer to the dir where this file is in, valid only in memory.
char f_pad[BY2FILE - MAXNAMELEN - (3 + NDIRECT) * 4 - sizeof(void *)];
} __attribute__((aligned(4), packed));
// file descriptor
struct Fd {
u_int fd_dev_id; //文件对应的设备id
u_int fd_offset; //文件指针所指向的位置
u_int fd_omode; //文件打开模式
};
// file descriptor + file
struct Filefd {
struct Fd f_fd; //文件描述符结构体
u_int f_fileid; //文件id
struct File f_file; //文件控制块
};
结构体名称 | 使用域 |
---|---|
Fd | 记录已打开文件的状态,用户可以直接使用文件描述符对文件进行操作,该结构体对应磁盘上的物理实体 |
File | 记录文件中的详细信息,包括文件名、文件类型、磁盘位置等 |
Filefd | 是以上两种结构体的组合包,将 Fd* 强制转换为 Filefd* 从而获取到文件控制块中更详细的信息 |
Thinking 5.7
- 实线箭头为同步消息
- 虚线箭头为返回消息
- 通信时,消息接收方进入可接收状态并通知发送方发送数据,进行进程切换;发送方发送完毕后等待接收方接收完毕的信号;收到信号后通知接收方继续运行。
- ipc 机制保证了用户、内核、文件进程间的正常通信。
难点分析
在完成作业时,主要的难点如下:
- 内核态读写驱动读写缓冲区和设置操作值的顺序易出错;
- 文件体系结构的管理数据结构较为多样
- 文件系统服务的通信机制较为复杂
思考体会
本次实验系统介绍了文件系统,按照 外设–接口–驱动–文件系统管理–用户接口构造 的顺序逐步构建文件系统。
安照指导书和代码注释补全代码难度不大,但要完整的把握整个文件系统的运行流程还需对fs文件夹以及user文件夹下的相关代码做仔细的阅读。