Skip to content

1. Lab Utilities

sleep

参照echo.c,直接调用system的函数即可

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

int main(int argc, char *argv[]) 
{
  int n;
  if (argc < 2) {
    fprintf(2, "Please enter a number.\n");
    exit(1);
  }

  n = atoi(argv[1]);
  sleep(n);
  exit(0);
}

然后在 makefileUPROGS下面加上相应内容。

pingpoing

使用到了 forkpipe

参考pipe() System call - GeeksforGeeks

p[0] 读数据 p[1] 写数据

不用的需要关闭

#include <kernel/types.h>
#include <kernel/stat.h>
#include <user/user.h>

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

  int p[2];
  if (pipe(p) < 0)
    exit(1);

  int pid = fork();
  if (pid > 0) {
    char buf;
    write(p[1], argv[1], 1);
    close(p[1]);
    read(p[0],&buf,1);
    close(p[0]);
    printf("%d: received pong\n", getpid());


  } else {
    char buf;
    read(p[0],&buf, 1);// 当p[0]没有数据时,这个进程会被挂起,进行等待。
    close(p[0]);
    printf("%d: received ping\n",getpid());
    write(p[1], &buf, 1);
    close(p[1]);

  }

  exit(0);
}

int pipe(int fds[2]);

Parameters : fd[0] will be the fd(file descriptor) for the read end of pipe. fd[1] will be the fd for the write end of pipe. Returns : 0 on Success. -1 on error.

primes

参考Bell Labs and CSP Threads

要求编写并发版本的质数筛

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

void process(int left[]) {
  char p;
  read(left[0], &p, 1);

  printf("prime %d\n", p);

  int num = 0;
  if (read(left[0], &num, 1) == 0) { // 到达结尾 管道关闭
    return;
  }


  int right[2];
  pipe(right);

  int pid = fork();
  if (pid == 0) {
    close(left[0]);
    close(right[1]);

    process(right);

    close(right[0]);
  } else if (pid > 0) {

    close(right[0]);

    do {
      if (num % p != 0) {
        write(right[1], &num, 1);
      }
    } while(read(left[0],&num,1) != 0);

    close(left[0]);
    close(right[1]);
    wait(0);

  } else {
    printf("Error.\n");
    exit(1);
  }


}

int main() {
  int right[2];
  pipe(right);

  int pid = fork();
  if (pid == 0) {

    close(right[1]);
    process(right);
    close(right[0]);
  } else if (pid > 0) {

    close(right[0]);

    for (int i = 2; i <= 35; i++) { // 传数
      char buf = i;
      write(right[1], &buf, 1);
    }

    close(right[1]);
    wait(0);

  } else {
    printf("Error.\n");
    close(right[0]);
    close(right[1]);
    exit(1);
  }

  exit(0);
}

read() 函数返回成功读取的字节数。如果返回值为0,则表示已到达文件末尾(end-of-file)。

当使用read()函数从管道中读取数据时,如果没有数据可供读取且管道中不再有任何写入端(也就是所有写入端都已关闭),read()函数将会返回0,表示已到达文件末尾(end-of-file)。

find

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

char *fmtname(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++;

  // Return blank-padded name.
  if (strlen(p) >= DIRSIZ)
    return p;
  memmove(buf, p, strlen(p));
  memset(buf + strlen(p), 0, DIRSIZ - strlen(p)); // 把’ ’改成0
  return buf;
}

int norecurse(char *path) { // 判断能否递归
  char* buf = fmtname(path);
  if(buf[0] == '.' && buf[1] == 0) {
    return 1;
  }
  if(buf[0] == '.' && buf[1] == '.' && buf[2] == 0) {
    return 1;
  }
  return 0;
}

void find(char *path,char *target) {
  //printf("%s\n",path);
  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;
  }

  if (fstat(fd, &st) < 0) { // 文件的状态信息
    fprintf(2, "find: cannot stat %s\n", path);
    close(fd);
    return;
  }

  //printf("path: %s; traget: %s;\n",path,target);

  if (strcmp(fmtname(path),target) == 0) {
    printf("%s\n",path);
  }

  switch(st.type){
  case T_FILE:
    // printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size);
    break;

  case T_DIR:
    if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
      printf("ls: 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;
      memmove(p, de.name, DIRSIZ);
      p[DIRSIZ] = 0;

      if(stat(buf, &st) < 0){
        printf("ls: cannot stat %s\n", buf);
        continue;
      }

      // if (strcmp(fmtname(buf), target) == 0) {
      //   printf("%s\n",buf);
      // }

      //printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);

      if(norecurse(buf) == 0) {
          find(buf,target);
      }

    }
    break;
  }
  close(fd);
}

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

  if(argc < 2) {
    printf("usage: find [path] [target]\n");
    exit(1);
  }

  if (argc < 3) {
    find(".", argv[1]);
    exit(0);
  }
  if(argc <4) {
    find(argv[1], argv[2]);
    exit(0);
  }


  printf("usage: find [path] [target\n]");
  exit(1);
}

xargs

$ echo hello too | xargs echo bye
bye hello too
$
$ find . b | xargs grep hello
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"


# define MAXSIZE 2048

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

    char buf[MAXSIZE];

    // 获取标准化输入
    int buf_idx = 0;

    int n = read(0,buf,MAXSIZE); // 防止输入时间过长,需要一直读取
    while (n>0) {
        buf_idx += n;
        n = read(0,&buf[buf_idx],MAXSIZE);
    }

    // for(int i=0;i<MAXSIZE;i++) {
    //     printf("%c",buf[i]);
    // }
    // printf("\n");

    // 处理参数
    char *xargv[MAXARG];
    int xargc = 0;
    for (int i=1; i<argc;i++) {
        xargv[xargc] = argv[i];
        xargc++;
    }

    char *p = buf;
    for (int i = 0; i < MAXSIZE; i++) {
        if(buf[i] == '\n') { //对每一行输入分别处理
            int pid = fork();
            if (pid == 0) {
                buf[i] = 0;
                xargv[xargc] = p; // 把参数加到最后
                xargc ++ ;
                xargv[xargc] = 0;
                xargc++;
                exec(xargv[0],xargv); // 执行程序
                exit(0);
            } else if (pid > 0) {
                wait(0);
                p = &buf[i+1];

            } else {
                printf("fork error.\n");
                exit(1);
            }
        }
    }

    exit(0);
}