Lab Utilities(2020年度课程)

Boot xv6 (easy)

根据官网指引,在 make qemu 步骤发生问题(runcmd函数内检测到无限递归):

user/sh.c: In function 'runcmd':
user/sh.c:58:1: error: infinite recursion detected [-Werror=infinite-recursion]
   58 | runcmd(struct cmd *cmd)
      | ^~~~~~

 看到csdn上也有类似的提问,https://ask.csdn.net/questions/7829950

 根据这个帖子里的回答,在 runcmd 函数前添加 __attribute__((noreturn)) 即 Make qemu 成功。

steps:

在xv6-labs-2020路径下执行 make qemu

Grade

在xv6-labs-2020路径下执行 make grade 可以评分。

sleep (easy)

参考 user/echo.c 实现 sleep.c;

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"


int main(int argc,char *argv[])
{
	if(2!=argc){
		fprintf(2, "usage: sleep seconds\n");
    		exit(1);
	}
	
	sleep(atoi(argv[1]));

	exit(0);
}

修改 makefile

UPROGS=\

        $U/_sleep\

...

ifeq ($(LAB),sleep)

UPROGS += \

        $U/_sleep

endif

在 xv6-labs-2020路径下执行

./grade-lab-util sleep

查看是否通过。

pingpong (easy)

参考 riscv第一章内容实现,注意:

1. 子进程先read再write;

2. 父子进程完成工作后close管道的读写端

3. 为了避免打印乱序,父进程中在打印之前调用 wait 系统调用,等待子进程完成工作。

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int main(int argc,char* argv[])
{
	int pipes[2];
	pipe(pipes);
	char buf[2];
	int pid=0;
	if(0==fork()){
		//child
		memset(buf,0,2);
		read(pipes[0],buf,1);
		pid=getpid();
		
		printf("%d: received ping\n",pid);
		write(pipes[1],"a",2);
		
		close(pipes[0]);
		close(pipes[1]);
		
		exit(0);
	}
	else{
		memset(buf,0,2);
		write(pipes[1],"a",2);
		read(pipes[0],buf,1);
		pid=getpid();

		wait((int*)0);
		printf("%d: received pong\n",pid);

		close(pipes[0]);
		close(pipes[1]);
		exit(0);
	}
	exit(0);
}

find (moderate)

char *fmtname ( char *path); 返回 path 路径字符串中最右斜杆 / 后子串,如 /hello/world 返回 world

#include <iostream>
#include <stdlib.h>
#include <string.h>

int main()
{
	char buf[100] = "hello world";
	if (*(buf + strlen(buf)) == '\0') {
		printf("buf + strlen(buf) points to a \\0\n");
	}

	char* p = buf + 2;
	printf("strlen(p): <%d>\n", strlen(p));
	printf("p: <%s>\n", p);
	return 0;
}

/*
buf + strlen(buf) points to a \0
strlen(p): <9>
p: <llo world>

注意,若 make qemu 报错:error: unknown type name 'uint'

修改头文件的include顺序,最简单就直接从 ls.c 里复制一下就行,不要随便修改 #include 的顺序

注意点:

1. fstat 得到的文件类型应考虑 T_FILE 与 T_DIR以外的类型

2. 获取路径中最右斜杆后的文件名,可以用个全局的字符数组

3. 注意及时close被open的描述符

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#include "stdbool.h"

char buf[DIRSIZ + 1] = {0};
char *fmtname(char *path)
{
  memset(buf, 0, sizeof(buf));
  char *p;

  for (p = path + strlen(path); p >= path && *p != '/'; p--)
    ;
  p++;

  if (strlen(p) >= DIRSIZ)
    return p;
  memcpy(buf, p, strlen(p));
  return buf;
}

void find(char *path, char *file)
{
  if (strlen(path) <= 0)
    return;

  char buf[512] = {0};
  strcpy(buf, path);

  struct stat st;
  struct dirent de;
  int fd = 0;

  if ((fd = open(buf, 0)) < 0)
  {
    return;
  }

  if (fstat(fd, &st) < 0)
  {
    close(fd);
    return;
  }

  if (st.type == T_FILE)
  {
    char *filename = fmtname(buf);
    if (strcmp(filename, file) == 0)
    {
      printf("%s\n", buf);
    }
    close(fd);
    return;
  }
  else if (st.type == T_DIR)
  {

    if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf)
    {
      close(fd);
      return;
    }
    char *p = buf + strlen(buf);
    *p++ = '/';

    while (read(fd, &de, sizeof(de)) == sizeof(de))
    {
      if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
        continue;
      if (de.inum == 0)
        continue;
      memmove(p, de.name, DIRSIZ);
      p[DIRSIZ] = 0;

      find(buf, file);
    }
  }
  else
  {
    close(fd);
    return;
  }
}

int main(int argc, char *argv[])
{

  if (argc < 3)
  {
    fprintf(2, "usage: find . filename");
    exit(1);
  }
  char dir[512] = {0};
  char file[512] = {0};

  memcpy(dir, argv[1], strlen(argv[1]));
  memcpy(file, argv[2], strlen(argv[2]));

  find(dir, file);

  printf("bye\n");

  return 0;
}

xargs

简化版的 UNIX xargs程序:从标准输入读取多行,对每一行执行命令。,该行作为命令的参数。

比如 

echo hello too | xargs echo bye

这里,echo bye 为命令,hello too 为参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值