Lab 1: Unix utilities汇总

这个实验主要学习了常用的一些系统调用。

Lab 1: Unix utilities

Boot xv6 (easy)

git克隆,切换分支,qemu。根据要求进行操作即可。

$ git clone git://g.csail.mit.edu/xv6-labs-2020
$ cd xv6-labs-2020
$ git checkout util
$ make qemu

sleep (easy)

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

int main(int argc ,char *argv[])
{
    if(argc < 2 )
    {
        fprintf(2,"please enter a number!");
        exit(1);
    }else{

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

}

在 Makefile 中将 sleep 加入构建目标里。

UPROGS=\
	$U/_cat\
	$U/_echo\
	$U/_forktest\
	$U/_grep\
	$U/_init\
	$U/_kill\
	$U/_ln\
	$U/_ls\
	$U/_mkdir\
	$U/_rm\
	$U/_sh\
	$U/_stressfs\
	$U/_usertests\
	$U/_grind\
	$U/_wc\
	$U/_zombie\
	$U/_sleep\ .   # here !!!

pingpong (easy)

管道题,使用 fork() 复制本进程创建子进程,然后使用管道进行相互通信。

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

int main(int argc ,char *argv[])
{
    int pp2c[2],pp2p[2];
    pipe(pp2c);
    pipe(pp2p);
    int n = fork();
    if(n != 0 ){
        write(pp2c[1],"a",1);
        char buff;
        read(pp2p[0],&buff,1);
        printf("%d: received pong\n",n);
    }else{
        char buff;
        read(pp2c[0],&buff,1);
        printf("%d: received ping\n",n);
        write(pp2p[1],&buff,1);
        
    }
    exit(0);

}

primes (moderate) / (hard)

观察下图进行进行理解,使用fork实现素数筛的功能。
Lab 1: Unix utilities汇总_第1张图片

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



void sieve(int pleft[2]){

    int p ;
    read(pleft[0] ,&p,sizeof(p));
    if(p == -1){

        exit(0);
    }
    printf("prime %d\n", p);
    int pright[2];
    pipe(pright);
    if(fork() == 0){
        // 子进程
        close(pright[1]);
        close(pleft[0]);
        sieve(pright);
    }else{
        close(pright[0]);
        int buff ;
        while(read(pleft[0] ,&buff,sizeof(buff)) && buff != -1){
            if(buff %p != 0 ){
                write(pright[1] ,&buff,sizeof(buff));
            }
        }
        buff = -1;
        write(pright[1] ,&buff,sizeof(buff));
        wait(0);
        exit(0);
    }
}

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

    int inputpipe[2];
    pipe(inputpipe);

    if(fork() == 0){
        // 子进程
        close(inputpipe[1]);
        sieve(inputpipe);
        exit(0);

    }else{
        close(inputpipe[0]);
   
        int i ;
        for( i = 2 ; i <=35;i++){
            write(inputpipe[1] ,&i,sizeof(i) );
            
        }
        i =-1;
        write(inputpipe[1] ,&i,sizeof(i) );
        
    }
    wait(0);
    exit(0);
}

find (moderate)

根据ls.c 改造得到

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


void find(char *path,char *target)
{
  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(path+strlen(path) - strlen(target) ,target) == 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++ = '/';
    while(read(fd, &de, sizeof(de)) == sizeof(de)){
      if(de.inum == 0|| strcmp(de.name, ".")==0 || strcmp(de.name, ".." )==0 )
        continue;
      memmove(p, de.name, DIRSIZ);//每次循环都会被覆盖
      p[DIRSIZ] = 0;
      if(stat(buf, &st) < 0){
        printf("find: cannot stat %s\n", buf);
        continue;
      }
      // printf(buf);
      // printf("\n");
    		find(buf, target); // 递归查找
		
    }
    break;
  }
  close(fd);
}

int main(int argc, char *argv[])
{
  
	if(argc < 3){
		exit(0);
	}
	char target[512];
	target[0] = '/'; // 为查找的文件名添加 / 在开头
	strcpy(target+1, argv[2]);
	find(argv[1], target);
	exit(0);
}

xargs (moderate)

xargs介绍

整体思路:

  • 将xargs命令传入的参数保存至指针数组,每个指针指向一个参数;
  • 解析输入参数,如果遇到’ ’ 或者\n 就将参数保存至指针数组,每次读取完成一行就使用exec进行运行
  • 最后一行进行单独判断运行,万一最后一行没有换行符
// xargs.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"


void run(char *program , char ** args)
{
    if(fork() == 0 ){
        exec(program,args);
        exit(0);
    }
    return ;
}
int main(int argc,char* argv[]){

    char buf[2048]; // 读入时使用的内存池
	char *p = buf, *last_p = buf; // 当前参数的结束、开始指针
	char *argsbuf[128]; // 全部参数列表,字符串指针数组,包含 argv 传进来的参数和 stdin 读入的参数
	char **args = argsbuf; // 指向 argsbuf 中第一个从 stdin 读入的参数
    for(int i=1;i<argc;i++) {
		// 将 argv 提供的参数加入到最终的参数列表中
		*args = argv[i];
		args++;
	}

    char **pa = args;

    while(read(0,p,1) != 0 ){
        if(*p == ' ' || *p == '\n'){
            *p = '\0';
            *(pa++) = last_p;
            last_p = p+1;
            
            if(*p == '\n'){
    
                
                *pa = 0;
                run(argv[1],argsbuf);
                pa = args;
            }
        }
        p++;

    }

    if(pa != args) { // 如果最后一行不是空行
		// 收尾最后一个参数

      
		*p = '\0';
		*(pa++) = last_p;
		// 收尾最后一行
		*pa = 0; // 参数列表末尾用 null 标识列表结束
		// 执行最后一行指令
		run(argv[1], argsbuf);
	}
    while(wait(0) != -1) {}; 

    exit(0);
}

你可能感兴趣的:(项目实战,unix,服务器)