6.S081学习记录-lab1

1、sleep

实现sleep函数,读取参数并调用sleep系统调用。

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

int main(int argc, char* argv[])
{
  int time;
  
  if(argc < 2){
    fprintf(2, "Usage: <sleep time>");
    exit(1);
  }
  
  time = atoi(argv[1]);
  if(time <= 0){
    fprintf(2, "Sleep: invalid sleep time");
    exit(1);
  }
  sleep(time);
  exit(0);
}

2、pingpong

管道的应用,使用管道在父子进程之间通信,像打乒乓球一样。注意关闭用不到的文件描述符。

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

int main(int argc, char* argv[])
{
  int child_to_parent[2], parent_to_child[2];
  char* child_buf = 0, *parent_buf = 0;
  char byte = 'a';
  pipe(child_to_parent);
  pipe(parent_to_child);
  
  int pid = fork();
  if(pid == -1){
    fprintf(2, "fork() failed");
    exit(1);
  }
  if(pid == 0){
    close(child_to_parent[0]);
    close(parent_to_child[1]);
    read(parent_to_child[0], child_buf, 1);
    fprintf(1, "<%d>: received ping\n", getpid());
    write(child_to_parent[1], child_buf, 1);
    close(child_to_parent[1]);
    close(parent_to_child[0]);
  }
  else{
    close(child_to_parent[1]);
    close(parent_to_child[0]);
    write(parent_to_child[1], &byte, 1);
    read(child_to_parent[0], parent_buf, 1);
    fprintf(1, "<%d>: received pong\n", getpid());
    close(child_to_parent[0]);
    close(parent_to_child[1]);
    wait(0);
  }
  exit(0);
}

3、primes

使用管道实现一个质数筛子,筛选出1-35中所有的质数。

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

// 子进程调用函数
void process(int left_to_right[])
{
  int prime, curNum;
  int new_left_to_right[2];
  
  pipe(new_left_to_right);
  
  // 留在left_to_right中的都是质数,此质数作为本进程的被除数
  if(read(left_to_right[0], &prime, sizeof(int)) <= 0)
    return;
  fprintf(1, "prime %d\n", prime);
  
  // 子进程作为右邻居,关闭写管道文件描述符
  if(fork() == 0){
    close(new_left_to_right[1]);
    process(new_left_to_right);
    close(new_left_to_right[0]);
  }
  else{
    close(new_left_to_right[0]);
    // 筛选,能被prime整除的淘汰,否则输入到右邻居进行处理
    while(read(left_to_right[0], &curNum, sizeof(int)) > 0){
      if(curNum % prime != 0){
        write(new_left_to_right[1], &curNum, sizeof(int));
      }
    }
    close(new_left_to_right[1]);
    wait(0);
  }
  close(left_to_right[0]);
  close(left_to_right[1]);
}

int main(int argc, char* argv[])
{
  int left_to_right[2], i;
  pipe(left_to_right);
  
  if(fork() == 0){
    close(left_to_right[1]);
    process(left_to_right);
    close(left_to_right[0]);
  }
  else{
    close(left_to_right[0]);
    // 读入数据,2就是质数,因此不需要处理
    for(i = 2; i <= 35; ++i){
      write(left_to_right[1], &i, sizeof(int));   
    }
    close(left_to_right[1]);
    wait(0);
  }
  exit(0);
}

4、find

参考ls,命令行参数分别为查找路径和待查找关键字。

#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 *filename)
{
  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(fmtname(path), filename) == 0){
      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;
      if(strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
        continue;
      memmove(p, de.name, DIRSIZ);
      p[DIRSIZ] = 0;
      if(stat(buf, &st) < 0){
        printf("ls: cannot stat %s\n", buf);
        continue;
      }
      find(buf, filename);
    }
    break;
  }
  close(fd);
}

int
main(int argc, char *argv[])
{
  if(argc < 3){
    fprintf(2, "Usage: find <path> <filename>\n");
    exit(0);
  }
  find(argv[1], argv[2]);
  exit(0);
}

5、xargs

编写一个简单版本的 UNIX xargs 程序:从标准输入读取行并为每一行运行一个命令,将该行作为参数提供给命令。

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

int main(int argc, char* argv[])
{
  int len = 0, idx = 0;
  char* exec_argv[MAXARG], buf[512];
  
  for(int i = 1; i < argc; ++i)
    exec_argv[i - 1] = argv[i];
  
  while(1){
    idx = 0;
    // 读取单行输入,一次读取一个字符,直到出现换行符 ('\n')。
    while((len = read(0, buf + idx, sizeof(char))) > 0){
      // 替换'\n'为'\0'
      if(buf[idx] == '\n'){
        buf[idx] = '\0';
        break;
      }
      ++idx;
    }
  
    // 没有命令需要读取了,退出循环
    if(len == 0 && idx == 0)
      break;
    exec_argv[argc - 1] = buf;
    // 使用fork和exec对每一行输入调用命令
    if(fork() == 0){
      exec(exec_argv[0], exec_argv);
      exit(0);
    }
    // 在父级中使用wait等待子级完成命令
    else{
      wait(0);
    }
  }
  exit(0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值