引言
最近在学习mit的操作系统课程,本系列博客主要记录课程项目实现的过程及一些思考过程。对应课程网址如下6.1810 / Fall 2024
sleep(easy)
第一个任务实现用户下的sleep程序,只需调用sleep系统调用即可。sleep.c文件实现如下
|
|
pingpong(easy)
前置知识
- 实验前准备:理解pipe的使用,会linux下pipe系统调用即可。
实现过程
本任务主要实现了一个父子进程通过管道来进行通信,pingpong.c文件实现如下
|
|
primes(moderate)/(hard)
前置知识
- 前置知识:理解fork系统调用的使用,会linux下fork系统调用即可。
实现过程
虽然本实验标注了hard,但是主要还是理清筛选素数的过程,理清了过程很快也就能写出来了。首先要理解埃氏筛的过程。埃氏筛是通过每次过滤已经确定的最后一个素数的所有倍数,来完成素数的筛选。
- 程序一开始的父进程只需要通过管道向子进程传递所有范围数字即可。
- 其他进程用于接受父进程的数据来进行过滤,并将过滤后的数据再传给子进程
- 子进程的过滤及传递过程都是通过primes函数实现,需要接受父进程创建的管道的读端fd作为参数,来接受父进程发送的数据。
- 同时需要再primes创建一个新的管道并进行fork系统调用,用于该进程过滤后将数据发送给创建的子进程。
- 下面的任务就是确定每一个进程需要过滤哪些数据
- 子进程首先会接受父进程发送的第一个数cur,这个第一个cur就是当前确认的素数,进行打印,然后根据这个数cur进行过滤,如果后面接受的父进程的数字不是这个cur的倍数,就可以发送给其子进程;是cur的倍数不发送,完成过滤。
- 到最后一定是某个子进程只接受了其父进程一个数cur,接受完第一个数后直接关闭文件描述符,其子进程调用read返回0,说明已经将全部素数都打印了,可以结束程序了。
|
|
find(moderate)
- 本实验主要实现查找指定目录树中特定名称的所有文件
前置知识
- 前置知识,学习user/ls.c中目录读取的内容
- fstate根据指定fd获取文件对应信息存放在struct stat数组中
- while(read(fd,&de,sizeof(de))) // 循环读取文件夹中的每一项,放到de中,主要存储文件名
|
|
实现过程
- 学会了ls中的相关操作,就可以来完成find操作了
- find操作主要是在文件树中进行一个深度优先遍历(dfs)来查找,找到对应文件信息符合要求就可以进行打印
- 前面模仿ls中的操作来打开对应的目录,注意find命令接受的第一个参数必须是文件夹路径
- while循环根据每一个子文件名(完整路径的文件名,需路径拼接)调用sate来获取文件信息,路径拼接和ls中一样
- 注意判断子文件名(非完整路径,无需拼接)要排除".“和”.."
- 子文件还是目录,进行递归调用即可;是文件比较是否是要查找的,是就输出即可。
find.c文件如下
|
|
xargs(moderate)
前置知识
-
理解文件重定向,以及fork 和 exec中间进行文件重定向的操作。这一块xv6 book中应该有很好的解释。
-
你需要实现xargs.c文件,因此你需要知道操作系统是如何调用你写的这个程序
-
理解匿名管道的调用过程,在echo hello too | xargs echo bye 中操作系统是如何执行xargs程序的
在user/sh.c中找到下面这些代码
|
|
- 在这个实验里,我们只需要知道sh根据用户输入的命令,将命令解析为struct cmd结构体
- 当cmd是一个pipecmd的时候,里面有左右两个cmd分别代表了 管道|左右两个命令
- 如echo hello too | xargs echo bye 中, cmd->left 对应echo hello too解析出来的命名 ,cmd->right 对应 xargs echo bye 解析出来的命令。
- 随后会调用fork函数来进行重定向
- 当cmd是一个pipecmd的时候,里面有左右两个cmd分别代表了 管道|左右两个命令
|
|
- 理解了过程,就可以知道xargs程序的执行会将左命令生成的标准输出追加到其指定要执行程序的参数后面
实现过程
|
|
- 以上面的命令为例,对于find . b 找到的每一个文件, 都要指定一次 grep hello b,因此xargs是实现可以如下所示
- 首先循环标准输入,解析标准输入,当标准输入已经读完一行就可以开始执行grep命令了
- 调用fork创建子进程,子进程将获得的那一行标准输入添加到grep的参数后面,中调用exec系统调用执行grep命令
- 父进程用于恢复之前读取的buf缓存
xargs.c 文件夹如下
|
|