DAY2

89 阅读4分钟

Day2

继续lab1~

primes

依旧是看看题目:

  1. pipe和fork设置管道,第一个进程输入数字2-35,每个素数创建一个进程,左读右写(0读1写),第一个进程可以停在第三十五个?
  2. 关闭进程不需要的文件描述符,一旦第一个进程达到35,则应该等待整个管道终止。
  3. 当写入端关闭时,read返回0(写入0)
  4. 管道里创建流程?

思路:

  1. 构造一个筛子函数,和一个main函数
  2. 首先main函数构造一个管道left,第一个进程负责向管道写入2-35的进程,写入后关闭写入窗口。
  3. fork1:根据fork()的返回值判断是父进程还是子进程还是错误
    1. 父进程:不做任何事情,等待,关闭
    2. 子进程:执行sift(left),执行结束后关闭
  4. sift即筛子函数,用递归的形式输出筛出后的内容。
    1. 首先传入left管道,关闭left管道的写入端
    2. 创建n,j,right管道
    3. Hint: read returns zero when the write-side of a pipe is closed.,根据这句话,读取一个数n,加一个判定:若返回0.直接退出
    4. 输出n,n既是过筛的素数,
    5. 再根据pid = fork(),判断fork的返回值,去决定是父进程还是子进程
      1. pid < 0,错误,关闭left,right的读写,退出~
      2. pid > 0,父进程,即当前进程,进行过筛,写入right
      3. pid =0,子进程,继续递归sift(right),这次把right 作为left传入
    6. make qemu,make grade,成功~

这题卡了好久,总共得有个四五个小时吧emmm,看别人的才知道得用两个管道,且需要关闭管道的读写,不然顺序会变化。不过最终还是过了~~~

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
//需要使用开关,且使用两个进程,一个左读右写,一个右写等待子进程读取

void  sift(int left[2]){
    close(left[1]);

    int n,j,right[2];
    int pid;
    pipe(right);
    if(read(left[0],&n,4) == 0 ){
        exit(0);
    }
    
    printf("prime ");
    printf("%d\n",n);

    if((pid = fork()) < 0){
         fprintf(2, "Error:sift error..\n");
         close(left[0]);
         close(right[0]);
         close(right[1]);
    }else if(pid > 0){
        //接受left,传递right
        close(right[0]);
        while(read(left[0],&j,4) > 0){
            if(j % n != 0){
                // printf("%d",j);
                write(right[1],&j,4);
            }
        }
        close(right[1]);
        wait(0);
        exit(0);
    }else{
        sift(right);
        exit(0);
    }

}



int main(){
    int left[2];
    int i;
    int pid;
    pipe(left);
    for(i = 2; i <= 35; i++){
        write(left[1],&i,4);
    }
    close(left[1]);
    pid = fork();
    if(pid < 0){
        fprintf(2, "Error:main error...\n");
        exit(1);
    }else if(pid > 0){
        wait(0);
        exit(0);
    }else{
        sift(left);
        exit(0);
    }

    return 0;

}

find(moderate)

首先还是来看下题目:

  1. 写一个unix查找程序,查找目录树中具有特定名称的所有文件
  2. 这一看就是递归查找,然后比较文件名啊

先创建文件和加入Makefile

思路:

  1. 创建一个函数,参数:目录名,依次输出目录下的文件名,判断是否和函数对应
  2. 输出文件名的时候,如果是子文件夹,递归,参数为子文件夹的目录名
  3. 退出

这题就是把ls改了一下,没什么奇技淫巧,边玩边写,看别人撕逼去了emmm

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.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), ' ', DIRSIZ-strlen(p));
  return buf;
}
void find(char *name,char *path)
{
  char buf[512], *p;
  int fd;
  struct dirent de;
  struct stat st;

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

  if(fstat(fd, &st) < 0){
    fprintf(2, "ls: cannot stat %s\n", path);
    close(fd);
    return;
  }
  switch(st.type){
  case T_FILE:
    if(strcmp(name,fmtname(path)) == -32)
        printf("%s\n", path);
    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)) != -32&&strcmp(".",fmtname(buf)) != -32){
            find(name,buf);
      }
    }
    break;
  }
  close(fd);
}

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

    int i; 
    if(argc < 2){
        exit(0);
    }
    for(i = 1; i < argc;i++){
        find(argv[i+1],argv[i]);
        i++;
    }
    exit(0);
}

xargs(moderate)

首先来看看题目

编写一个简单的xargs,从标准输入中读取行并为每行运行一个命令,改行作为参数提供给命令

  1. example1:

    1. $ echo hello too | xargs echo bye
    2. bye hello too
  2. example2:

    echo "1\n2" | xargs -n 1 echo line
        line 1
        line 2
    
  3. 这里的xargs好像执行的是一个附加的操作,在之前指令上附加一些指令

  4. fork,exec去执行指令,wait去让父亲进程等待子进程完成

  5. 行与行之间使用\n分割

还是先列一下思路:

  1. 首先还是argv < 2,发送错误指令
  2. 然后argv[1]是需要执行的指令

好吧卡了两小时写不出来,不想写了,去看下一章课去了。