第一个lab是熟悉xv6的system calls
sleep:
easy难度
在makefile的UPROGS添加$U/_sleep
在user/sleep.c中写以下代码:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc != 2){
fprintf(2, "sleep needs an int as param.\n");
exit(1);
}
int i = atoi(argv[1]);
sleep(i);
exit(0);
}
pingpong:利用pipe在父子进程间通信(利用子进程会继承父进程的打开文件符)
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc > 1){
fprintf(2, "ping-pong doesn't need params\n");
exit(1);
}
char v = 0;
int parent[2];
int child[2];
pipe(parent);
pipe(child);
if(fork() == 0){
//child
close(child[1]);
close(parent[0]);
read(child[0], &v, 1);
if(v==0){
printf("%d: received ping\n", getpid());
}else{
exit(1);
}
v = 1;
write(parent[1], &v, 1);
close(child[0]);
close(parent[1]);
}else{
//parent
close(child[0]);
close(parent[1]);
write(child[1], &v, 1);
read(parent[0], &v, 1);
if(v==1){
printf("%d: received pong\n", getpid());
}else{
exit(1);
}
close(parent[0]);
close(child[1]);
}
exit(0);
}
primes:利用fork出来的进程树,对数据进行过滤
及时关闭用不到的fd
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/param.h"
#include "user/user.h"
/*
解题思路:
buffer的作用是保存这轮不能被筛除的数
*/
int
main(int argc, char *argv[])
{
int fd[2];
int buffer[36];
int cnt = 0;
for (int i = 2; i < 36; i++)
{
buffer[cnt++] = i;
}
while (cnt > 0)
{
pipe(fd);
if(fork() == 0)
{
close(fd[1]);
int base = 0;
cnt = -1;
int v;
while (read(fd[0], &v, sizeof(v)))
{
if(cnt == -1){
base = v;
cnt = 0;
}else if(v % base != 0){
buffer[cnt++] = v;
}
}
close(fd[0]);
printf("prime %d\n", base);
}
else
{
close(fd[0]);
for (int i = 0; i < cnt; i++)
{
write(fd[1], &buffer[i], sizeof(buffer[i]));
}
close(fd[1]);
wait(0);
break; //父进程跳出while循环
}
}
exit(0);
}
find:利用fstat查看fd的元信息,如果是file,则拿到文件名,如果是directory,则读取其中的struct dirent
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
// extract b from ./a/b
void
extractname(char *path, char *buf)
{
char *p = path + strlen(path);
while(*--p != '/'){
}
strcpy(buf, p+1);
}
void
find(char *path, char *name)
{
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
fprintf(2, "find: cannot open %s\n", path);
return;
}
//fstat是查看该fd的元信息
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type){
case T_FILE:
extractname(path, buf);
if(strcmp(buf, name) == 0){
printf("%s\n", path);
}
break;
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++ = '/';
//文件夹也是一个file,从里面会逐个读取文件夹下的内容,每次读一个struct dirent大小
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
}
// printf("debug %s\n", buf);
/* 出现递归
debug ./.
debug ././.
debug ./././.
debug ././././.
*/
char *check = buf + strlen(buf);
while(*check != '/') check--;
check++;
if(strcmp(check, ".") == 0) continue;
if(strcmp(check, "..") == 0) continue;
find(buf, name);
// printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
}
break;
}
close(fd);
}
int
main(int argc, char *argv[])
{
if(argc < 3){
fprintf(2, "find need at least 3 params\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
xargs:把上一个命令的输出作为下一个命令的输入参数
$ echo hello too | xargs echo bye
bye hello too
solution:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/param.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
char *args[MAXARG];
int ini_arg_num = 0;
char buf[256] = {0};
// printf("argc %d\n", argc);
for(int i=1; i<argc; ++i){
if(strcmp(argv[i], "-n") == 0 && i==1){
++i;
}else{
args[ini_arg_num++] = argv[i];
// printf("%d %s\n", ini_arg_num-1, argv[i]);
}
}
/*
这里有问题 无法解析\n
$ echo "1\n2" | xargs -n 1 echo line
"1\n2"
line "1\n2"
*/
while(gets( buf, sizeof(buf))){
if(strlen(buf) < 1) break;
// printf("%d\n%s", strlen(buf), buf);
buf[strlen(buf)-1] = 0; //清除gets读入的\n
// printf("%s\n", buf);
int arg_num = ini_arg_num;
char *p = buf;
while (*p)
{
while ((*p == ' ') && *p) *p++ = 0;
if(*p) args[arg_num++] = p;
while ((*p != ' ') && *p) p++;
}
if(arg_num >= MAXARG) fprintf(2, "too many args\n");
if(arg_num < 1) fprintf(2, "too few args for xargs\n");
args[arg_num] = 0;
if(fork() == 0){
// printf("%s\n", args[0]);
// printf("%s %s %s\n", args[1], args[2], args[3]);
exec(args[0], args);
exit(0);
}else{
wait(0);
}
}
exit(0);
}