Lab1 : Xv6 and Unix utilities
1.xv6 system call interface
2.task
i. primes
注意管道pipe的使用:
int pipe(int p[])
Create a pipe, put read/write file descriptors in p[0] and p[1], 成功:0;失败:-1,设置errno;
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void myprimes(int *p){
int p_id;
if((p_id = fork()) < 0){
fprintf(2, "primes: fork failed\n");
exit(1);
}
if(p_id == 0){
char buff[1];
int child_p[2];
int len;
int num = -1;
close(p[1]);
while((len = read(p[0], buff, 1)) > 0){
int n = (int)buff[0];
// printf("%d:recv %d\n", getpid(), n);
if(num == -1){
num = n;
printf("prime %d\n", num);
if(pipe(child_p) < 0){
fprintf(2, "primes: pipe failed\n");
exit(1);
}
myprimes(child_p); // 注意,先创建新的子进程,再关闭文件描述符
close(child_p[0]); // 否则会导致子进程对应的文件描述符也关闭(复制过去的)
}
else if(n % num){
write(child_p[1], buff, 1);
}
}
close(child_p[1]);
close(p[0]);
wait(0);
exit(0);
}
}
int
main(int argc, char const *argv[]){
int p[2];
if(pipe(p) < 0){
fprintf(2, "prime: pipe failed\n");
exit(1);
}
myprimes(p);
close(p[0]);
char buff[1];
for(int i=2;i<=35;++i){
buff[0] = (char)i;
// printf("%d: emit %d\n",getpid(), i);
write(p[1], buff, 1);
}
close(p[1]);
wait(0);
exit(0);
}
ii. find
实现思路:修改ls即可,ls只遍历当前目录,find修改为遍历当前目录及其所有子目录,通过递归实现即可,需要注意的是不要遍历"."和"..",会导致死循环。
此外,需要注意对于目录的读取:
read(fd, &de, sizeof(de)) == sizeof(de)
和文件的读取方式相同,每次读取目录中的一个元素,读取的结果存储在dirent结构体中。
struct dirent {
ushort inum;
char name[DIRSIZ];
};
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
char*
filename(char *path){
static char buf[DIRSIZ+1];
char *p;
// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;
memmove(buf, p, strlen(p));
buf[strlen(p)] = 0;
return buf;
}
void find(char *src, char *dst){
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
// printf("find in : %s\n", src);
if((fd = open(src, 0)) < 0){
fprintf(2, "find: cannot open %s\n", src);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", src);
close(fd);
return;
}
switch (st.type)
{
case T_FILE:
// printf("name:%s\n", filename(src));
if(strcmp(filename(src), dst) == 0){
printf("%s\n", src);
}
break;
case T_DIR:
if(strlen(src) + 1 + DIRSIZ + 1 > sizeof buf){
printf("find: path too long\n");
break;
}
strcpy(buf, src);
p = buf + strlen(buf);
*p++ = '/';
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(strcmp(".", p) == 0 || strcmp("..", p)==0)
continue;
if(stat(buf, &st) < 0){
printf("ls: cannot stat %s\n", buf);
continue;
}
find(buf, dst);
}
break;
}
close(fd);
}
int
main(int argc, char *argv[]){
if(argc != 3){
fprintf(2, "Usage: find src dst\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}