1. 程式人生 > 其它 >mit6.s081-21-Lab1/ Xv6 and Unix utilities

mit6.s081-21-Lab1/ Xv6 and Unix utilities

sleep

Implement the UNIX program sleep for xv6; your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your solution should be in the file user/sleep.c.

描述:實現一個提供sleep功能的unix程式。

解決思路:系統已經實現了sleep函式,直接呼叫即可。

程式碼:

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

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

  if(argc != 2){
    fprintf(2, "Usage: sleep times\n");
    exit(1);
  }
  
  ticks_num = atoi(argv[1]);
  sleep(ticks_num);

  exit(0);
}

pingpong

Write a program that uses UNIX system calls to ''ping-pong'' a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print ": received ping", where is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print ": received pong", and exit. Your solution should be in the file user/pingpong.c

.

描述:使用管道(pipe)實現ping-pong(即使用pipe實現父程序子程序之間的通訊)

解決思路:fork + pipe + write/read即可,比較簡單,要注意pipe會建立兩個fd(讀/寫),fork後子程序會繼承檔案描述符。

程式碼:

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

int
main(int argc, char *argv[])
{
  int p[2]; // read, write
  char buf[2];
  if(argc != 1){
    fprintf(2, "Usage: pingpong\n");
    exit(1);
  }

  pipe(p);
  if (fork() == 0) { // child
    read(p[0], buf, 1);
    fprintf(1, "%d: received ping\n", getpid());
    write(p[1], "c", 1);
    exit(0);
  } else { // father
    write(p[1], "c", 1);
    read(p[0], buf, 1);
    fprintf(1, "%d: received pong\n", getpid());
  }

  exit(0);
}

primes

Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, inventor of Unix pipes. The picture halfway down this page and the surrounding text explain how to do it. Your solution should be in the file user/primes.c.

描述:使用pipe實現素數篩。

解決思路:父程序產生2-35的數,然後子程序按以下演算法進行篩選即可。

p = get a number from left neighbor
print p
loop:
    n = get a number from left neighbor
    if (p does not divide n)
        send n to right neighbor

程式碼:(若BUFSIZE過大會panic,排查後發現是stack只有一頁。。。)

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

#define MAX_SEQ 35
#define BUFSIZE 100

int getline(int fd, char *buf, int max)
{
    int i, cc;
    char c;

    for (i = 0; i + 1 < max;)
    {
        cc = read(fd, &c, 1);
        if (cc < 1)
        {
            return 0;
        }
        if (c == '\n' || c == '\r')
            break;
        buf[i++] = c;
    }
    buf[i] = '\0';
    return i;
}

int getnum(char *buf, int *pos)
{
    int num = 0, i = *pos;
    while(buf[i] >= '0' && buf[i] <= '9') {
        num = num * 10 + buf[i] - '0';
        i++;
    }
    *pos = i - 1;
    return num;
}

int primer(int read_fd)
{
    char buf[BUFSIZE];
    int len = getline(read_fd, buf, BUFSIZE);
    // printf("%s\n", buf);
    close(read_fd);

    int pipe_fd[2];
    pipe(pipe_fd);

    int i = 0, first_print_flag = 1;
    int is_have = 0;
    int first_num = getnum(buf, &i), num_tmp;
    printf("prime %d\n", first_num);
    for (i = 0; i < len; ++i) {
        if (buf[i] >= '0' && buf[i] <= '9') {
            num_tmp = getnum(buf, &i);
            if (num_tmp % first_num == 0) {
                continue;
            }
            is_have = 1;
            break;
        }
    }
    if (is_have) {
        if (fork() == 0) { // child
            close(pipe_fd[1]);
            primer(pipe_fd[0]);
            exit(0);
        } else {
            close(pipe_fd[0]);
            for (i = 0; i < len; ++i) {
                if (buf[i] >= '0' && buf[i] <= '9') {
                    num_tmp = getnum(buf, &i);
                    if (num_tmp % first_num == 0) {
                        continue;
                    }
                    if (first_print_flag) {
                        fprintf(pipe_fd[1], "%d", num_tmp);
                        first_print_flag = 0;
                    } else {
                        fprintf(pipe_fd[1], " %d", num_tmp);
                    }
                }
            }
            fprintf(pipe_fd[1], "\n", num_tmp);
            close(pipe_fd[1]);
            wait(0);
        }
    } else {
        close(pipe_fd[0]);
        close(pipe_fd[1]);
    }
    return 0;
}

int main(int argc, char *argv[])
{
    int pipe_fd[2]; // read, write
    if (argc != 1)
    {
        fprintf(2, "Usage: primes\n");
        exit(1);
    }

    pipe(pipe_fd);
    if (fork() == 0)
    { // child
        close(pipe_fd[1]);
        primer(pipe_fd[0]);
        exit(0);
    }
    else
    { // father
        close(pipe_fd[0]);
        for (int i = 2; i <= MAX_SEQ; ++i)
        {
            fprintf(pipe_fd[1], "%d", i);
            if (i != MAX_SEQ)
            {
                fprintf(pipe_fd[1], " ", i);
            }
            else
            {
                fprintf(pipe_fd[1], "\n", i);
            }
        }
        close(pipe_fd[1]);
        wait(0);
    }

    exit(0);
}

find

Write a simple version of the UNIX find program: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c.

描述:實現find。

解決思路:魔改ls即可,改成dfs實現。

程式碼:

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

char*
fmtname(char *path)
{
  char *p;

  // Find first character after last slash.
  for(p=path+strlen(path); p >= path && *p != '/'; p--)
    ;
  p++;
  return p;
}

void
find(char *path, char *target)
{
  struct stat st;
  char buf[512], *p;
  int fd;
  struct dirent de;

  if (stat(path, &st) < 0) {
    fprintf(2, "find: cannot stat %s\n", path);
    return;
  }

  switch(st.type){
  case T_FILE:
    if (strcmp(fmtname(path), target) == 0) {
      printf("%s\n", path);
    }
    break;

  case T_DIR:
    if((fd = open(path, 0)) < 0){
      fprintf(2, "find: cannot open %s\n", path);
      return;
    }

    strcpy(buf, path);
    p = buf+strlen(buf);
    *p++ = '/';

    // many records
    while(read(fd, &de, sizeof(de)) == sizeof(de)){
      if(de.inum == 0)
        continue;
      
      if (!strcmp(".", de.name) || !strcmp("..",  de.name)) {
        continue;
      }

      memmove(p, de.name, strlen(de.name));
      p[strlen(de.name)] = 0;
      find(buf, target);
    }
    close(fd);
    break;
  }
}

int
main(int argc, char *argv[])
{
  if(argc != 3){
    fprintf(2, "Usage: find path keyword\n");
    exit(1);
  }

  find(argv[1], argv[2]);

  exit(0);
}

xargs

Write a simple version of the UNIX xargs program: read lines from the standard input and run a command for each line, supplying the line as arguments to the command. Your solution should be in the file user/xargs.c.

描述:實現xargs。

解決思路:對每行進行處理,因此加上上面的getline函式然後搭配上fork和exec就行(和shell類似)。

程式碼:

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

#define MAX_LEN 512

int getline(char *buf, int max)
{
  int i, cc;
  char c;

  for(i=0; i+1 < max; ){
    cc = read(0, &c, 1);
    if(cc < 1) {
      return 0;
    }
    if(c == '\n' || c == '\r')
      break;
    buf[i++] = c;
  }
  buf[i] = '\0';
  printf("str: %s\n", buf);
  return 1;
}

int
main(int argc, char *argv[])
{
  // echo hello too | xargs echo bye
  char buffer[MAX_LEN];
  char* argv_tmp[MAXARG];
  // minus "xargs"
  memcpy(argv_tmp, argv + 1, (argc - 1) * sizeof(char*));
  while (getline(buffer, MAX_LEN))
  {
    if (fork() == 0) {
      argv_tmp[argc - 1] = buffer;
      exec(argv_tmp[0], argv_tmp);
      exit(0);
    } else {
      wait(0);
    }
  }
  exit(0);
}