Lab1:Xv6 and Unix utilities,主要内容是利用系统调用完成一些小程序。
Problem 1:环境配置
第一个难题是boot xv6,配置环境使xv6在qemu上运行。一开始我是在Vmware上的Ubuntu18.04上配置,交叉编译工具需要自己手动安装,但是从github的clone一直失败,最后索性在wsl的Ubuntu20.04上配置环境,顺利的完成了配置环境。
Problem 2:用户代码使用系统调用发生了什么?
从用户代码user/usys.S中可以看到系统调用是一段汇编代码
sleep:
li a7, SYS_sleep
ecall
ret
SYS_sleep只是/kernel/syscall.h中定义的宏定义system call number,system call function被存储为一个函数指针数组,system call number就是对应system call在数组中的位置。将system call number存放在a7后使用ecall进行系统调用。
Problem 3: 利用pipe使用并行计算
primes计算100以内的质数程序基于this page的思想,利用pipe将计算结果不断的向后面的进程传递以达到并行计算的效果。该程序的难点在于为了形成下图的结构,需要进行递归创建子进程,并且在创建子进程及时关闭父进程的file descriptor。
Problem 4: 读取目录文件
open打开文件后返回一个file descriptor,在Linux中万物皆为文件,但是对于不同类型文件的读写操作是不同的,那么系统是如何区分设备文件或者普通文件或者目录呢?xv6-book中给出答案,通过fstat返回file descriptor引用的inode的检索信息,这些信息存储为一个stat类型,在kernel/stat.h中可以看到其类型相关声明。
#define T_DIR 1 // Directory
#define T_FILE 2 // File
#define T_DEVICE 3 // Device
struct stat {
int dev; // File system's disk device
uint ino; // Inode number
short type; // Type of file
short nlink; // Number of links to file
uint64 size; // Size of file in bytes
};
通过stat判断一个类型并对其进行相应读写操作,如在find中读取目录文件代码如下,其中de为dirent类型,存储目录中的文件名称,在kernel/fs.h中dirent的定义如下
read(fd,&de,sizeof(de))
//fs.h
struct dirent {
ushort inum;
char name[DIRSIZ];
};