6.s081 lab1
Posted 豹豹龙神
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.s081 lab1相关的知识,希望对你有一定的参考价值。
文档:
课程介绍 · 6.S081 All-In-One (dgs.zone)
网课:6.S081 / Fall 2020 [麻省理工操作系统 - 2020 年秋季][中英文字幕]_哔哩哔哩_bilibili
1.sleep
main的第一个参数一般是函数名,第二个才是参数
而输入的参数是Ascii码,系统调用sleep需要的是数值,因此需要转换
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
if (argc != 2)
fprintf(2, "Usage: sleep <number>\\n");
exit(1);
int i = *argv[1] - '1';
sleep(i);
exit(0);
2.pingpong
考验对管道的理解
错误:第一次写的时候,不知道pipe(p1)后,p1[0]为读入端,p1[1]为写入端。也就是说p1[0]、p1[1]的分工是被定死了的
这里close是一种习惯,当一个进程有太多管道的时候,可能会爆掉。比如xv6的每个进程最多只能打开16个文件描述符
read(p1[0], buf, n) 是从管道p1[0]中读取n个字节到buf,并返回实际读取的字节数。
因此可以使用 read(p1[0], buf, n) == n 来判断是否顺利读入
write(p1[1], buf, n) 同理
#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" int main(int argc, char *argv[]) if(argc > 1) fprintf(2, "Usage: pingpong\\n"); exit(1); int p1[2], p2[2]; pipe(p1); pipe(p2); char buf[1]; if(fork() == 0) //son should read buf[0] = '0'; close(p1[0]); close(p2[1]); if(read(p2[0], buf, 1) == 1) close(p2[0]); printf("%d: received pong\\n", getpid()); write(p1[1], buf, 1); close(p1[1]); else buf[0] = '1'; close(p1[1]); close(p2[0]); write(p2[1], buf, 1); close(p2[1]); if(read(p1[0], buf, 1) == 1) close(p1[0]); printf("%d: received ping\\n",getpid()); exit(0);
3. primes
错误:把函数定义在main()之后,导致编译出错
main()函数进行第一次fork,父进程通过管道向子进程传递2~35。子进程调用递归。
递归的第一件事是检查其父进程是否通过管道传递数字,如果没有,说明递归结束。
如果有,那么传递的第一个数字i一定是质数(这些数都是不能被比它小的数字整除的),将其打印。
然后进行fork(),本进程进行筛选,将不能被i整除的数字传递给子进程,子进程调用递归
进程1->进程2: 传递 2~35
进程2:打印2,进程2->进程3 传递: 3~35 筛掉能被2整除的数,传递给进程3
进程3:打印3,进程3->进程4 传递: 5~35(不能被2、3整除) 筛掉能被3整除的数,传递给4
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void ff(int p[])
close(p[1]);
int i;
// finish 2~35
if(read(p[0], &i, sizeof(i)) == 0)
close(p[0]);
exit(0);
printf("prime %d\\n",i);
int num, newp[2];
pipe(newp);
//son recursion
if(fork() == 0)
close(p[0]);
close(newp[1]);
ff(newp);
//parent output for son
else
close(newp[0]);
// get digit from its parent
while(read(p[0], &num, sizeof(num)) != 0)
//sift digit, and send to son
if(num % i != 0)
write(newp[1], &num, sizeof(num));
close(p[0]);
close(newp[1]);
wait(0);
exit(0);
int main(int argc, char *argv[])
//need not input
if(argc > 1)
fprintf(2, "Usage: primes\\n");
exit(1);
int p[2];
pipe(p);
//son
if(fork() == 0)
close(p[1]);
ff(p);
//parent
else
close(p[0]);
for(int i = 2; i <= 35; i++)
write(p[1], &i, sizeof(i));
close(p[1]);
wait(0);
exit(0);
4. find
错误:
在把目录名加入到buf后面的时候,一开始没想到用p,写成
buf[strlen(buf)] = '/';
memmove(buf + strlen(buf), de.name, DIRSIZ);
buf[ strlen(buf) ] = 0;
这是因为没有想清楚,这是个dfs,while中的每个文件名相当于多叉树的一个分叉,走出去一步后应该撤销,再走另一分叉。buf[ strlen(buf) ] = 0;显然只是在结尾加个0,buf会成为当前目录下所有文件名的拼接。path name1 name2 name3
应该使用p记录当前结点的path,一次循环结束后,memove把name2复制到当前path之后,而不是name1之后。然后再加0,这样即使name1很长,也因为加了0不影响
p指向'/'后一位 path/aaaaaaaa
memove(p, de.name, strlen(de.name)) path/bbbaaaaa
p[strlen(de.name)]=0 path/bbb0aaaa
主要的问题是对很多全局变量不清楚
struct stat st; fstat(fd, &st) 是将fd的信息存到结构体st中
struct dirent de;
while(read(fd, &de, sizeof(de)) == sizeof(de)) 是遍历fd下的每个文件, 将fd中的某个文件读入到结构体de。de.name是文件名
stat的type属性:T_FILE为文件,T_DIR为目录
疑问:open(path, 0)的path是整个读进去,还是读到0为止
思路:dfs
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
void find(char *path, char *target)
char buf[256], *p;
int fd;
struct dirent de;
struct stat st;
//打开path
if((fd = open(path, 0)) < 0)
fprintf(2, "find: cannot open %s\\n", path);
return;
// 调用 fstat 将 fd 对应的文件信息记录在 st 中
if(fstat(fd, &st) < 0)
fprintf(2, "find: cannot stat %s\\n", path);
return;
switch(st.type)
// st.type 为文件时直接返回即可
case T_FILE:
if(strcmp(path + strlen(path) - strlen(target), target) == 0)
printf("%s\\n", path);
break;
//若为目录,则使用DFS,遍历当前目录下的每一个文件或目录,调用find不断递归,直到找到target
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf)
printf("find: path too long\\n");
break;
strcpy(buf, path);
p = buf + strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de))
if(de.inum == 0)
continue;
if(strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;
// 将 de.name 拷贝到 p 中
memmove(p, de.name, strlen(de.name));
//设置路径的结束符,因为buf要递归传给下一步作为path
p[strlen(de.name)] = 0;
find(buf, target);
break;
close(fd);
int main(int argc, char *argv[])
if(argc < 3)
exit(0);
char target[256];
//自动在输入的目标前加一个‘/’
target[0] = '/';
strcpy(target + 1, argv[2]);
find(argv[1], target);
exit(0);
以上是关于6.s081 lab1的主要内容,如果未能解决你的问题,请参考以下文章