MIT6.S081

MIT6.S081 util

Posted on 2021-03-16,7 min read

第一个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);
}


下一篇: C++ unique_lock future condition_variable→