lab1 Xv6 and Unix utilities

127 阅读3分钟

相关规范注意

编译规则

进入Makefile文件修改其中的某项内容

sleep

代码

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

int main(int argc,char * argv[]){
      if(argc < 2){
         fprintf(2,"Usage: sleep time\n");
         exit(1);
      }
      int seconds = atoi(argv[1]);
     int ret = sleep(seconds);
     if(ret == -1){
        fprintf(2,"Error");
        exit(1);
     }
     exit(0);
}

pingpong

代码

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "stddef.h"
int main(int argc, char *argv[]){
    int fd1[2]; // fd1[0] 是父进程读端  fd1[1]是子进程写端
    int fd2[2];//  fd2[0] 子进程读端    fd2[1]是父进程写端

    int ret1 = pipe(fd1);
    int ret2 = pipe(fd2);

    if(ret1 == -1 || ret2 == -1){
        fprintf(2,"pipe error\n");
        exit(1);
    }
    
    int pid = fork();

    if(pid > 0) {// 父进程
         close(fd1[1]); // 关闭子进程写端
         close(fd2[0]); // 关闭子进程读端

         char * buf1 = "ping"; // 用于写入
         char  buf2[10] = {0}; // 用于读

         write(fd2[1],buf1,4); // 向写端写入一个字节

        //  wait(NULL);
         
         read(fd1[0],buf2,4);

        printf("%d: received %s\n",getpid(),buf2);
    }
    else if(pid == 0){
        close(fd1[0]); // 关闭父进程读端
        close(fd2[1]); // 关闭父进程写端

        char * buf1 = "pong"; // 用于写入
        char  buf2[10] = {0}; // 用于读

        read(fd2[0],buf2,4);
        printf("%d: received %s\n",getpid(),buf2);

        write(fd1[1],buf1,4);
    }
    else {
        fprintf(2,"Error\n");
        exit(1);
    }
    exit(0);
}

primes

这题不是很好想,坑点比较多

  • 如何解决有限的文件描述符文件 当一个进程中对一个文件描述符用完了后就一定要关掉避免文件描述符不够用的情况,内存有限哦
  • 还有一个很重要的就是wait()和exit的连用很重要,一定要注意这种想法]

代码

// Lab Xv6 and Unix utilities
// primes.c
//进程从文件描述符0读取(标准输入),将输出写入文件描述符1(标准输出) 和fd的读端和写端一样
#include "kernel/types.h"
#include "user/user.h"
#include "stddef.h"
// void map(int n,int fd[]){ // 关闭fd中的文件描述符 定位一下就行 这个重定位真的起作用了吗 我持怀疑态度 一会测试一下就知道了
//     close(n); 
//     dup(fd[n]);
//     close(fd[0]);
//     close(fd[1]);
// }

void primes(int fd[]){
    int num,num1;
     close(fd[1]);
    if(read(fd[0],&num,sizeof(int)) > 0){
        printf("prime %d\n",num); //打印一下从父进程传来的数据一定是素数
        
        int fd1[2];
        pipe(fd1);

        int pid = fork();

        if(pid > 0){ // 如果是父进程 继续从上次的子进程中读取数据判断是否写入子进程
          close (fd1[0]);
          while (read(fd[0],&num1,sizeof(int)))
          {
            if(num1 % num != 0) write(fd1[1],&num1,sizeof(int));
          }
          close(fd1[1]);
          wait(NULL);
          exit(0);
        }
        else primes(fd1); //子进程继续进行 
    }
    else exit(0);

}
int main(){
   int fd[2];
   pipe(fd);

    if(fork() > 0){ // 父进程向子进程写数据 
    close(fd[0]);
     for (int i = 2; i < 36; i++)
     {
        write(fd[1],&i,sizeof(int));// 父进程向子进程写数据 用fd[1]写入数据
     }
     close(fd[1]);
     wait(NULL);//等子进程结束
   }     
    else{
    //    直接进行判断
    primes(fd);
    }
   
   exit(0);
}

find

收获

  • 对目录遍历函数和文件系统函数理解的更加深刻
  • 看源码学了了stat和fstat区别
  • 学习了mmove函数

memove

void*
memmove(void *vdst, const void *vsrc, int n)
{
  char *dst;
  const char *src;

  dst = vdst;
  src = vsrc;
  if (src > dst) { // 如果vsrc的内存地址高于 vdst没有覆盖类似于memcpy
    while(n-- > 0)
      *dst++ = *src++;
  } else { // 如果有覆盖
    dst += n; // 指针后移n位进行复制
    src += n;
    while(n-- > 0)
      *--dst = *--src;
  }
  return vdst;
}

代码

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

void find(char *dir, char *file);

int main(int argc, char *argv[]) {
    //  题意是在指定目录下查询指定文件
    if (argc != 3) {
        printf("find:cannot execute\n");
        exit(1);
    }

    find(argv[1], argv[2]);
    exit(0);
}

void find(char *dir, char *file) {
    char buf[512], *p;
    int fd = 0;
    struct dirent de; // 和目录相关读取目录中文件信息
    struct stat st; // 对文件操作

    //判断是不是文件
    if ((fd = open(dir, 0)) < 0) {
        fprintf(2, "find: cannot open %s\n", dir);
        return;
    }
    if (strlen(dir) + 1 + DIRSIZ + 1 > sizeof buf) //太长了结束
    {
        fprintf(2, "find: directory too long\n");
        close(fd);
        return;
    }
    if (fstat(fd, &st) < 0) {
        fprintf(2, "find: cannot stat %s\n", dir);
        close(fd);
        return;
    }

    strcpy(buf, dir);
    p = strlen(buf) + 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("find: cannot stat %s\n", buf);
            continue;
        }
        if (!strcmp(de.name, ".") || !strcmp(de.name, "..")) continue;

        if (st.type == T_DIR) find(buf, file);

        if (st.type == T_FILE && !strcmp(de.name, file)) {
            printf("%s\n", buf);
        }
    }

}

xargs

代码

version1(一次性读取一整个字符串)

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#include "stddef.h"
#define MAXN 1024;
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(2, "xrags: arguments are not enough\n");
    }

    char * arguments [1024]; // 子进程参数
    char buf[1024];

    int pos = -1;
    for (int i = 1; i < argc; i++) arguments[++pos] = argv[i];
 
        while (read(0, buf, sizeof(buf)) > 0)   // 从爷爷进程中读取数据
        {
            char temp[1024] = {0};
            for (int i = 0; i < strlen(buf); i++)
            {
                /* code */
                if(buf[i] != '\n') {
                    temp[i] = buf[i];
                    continue;
                }
                if(fork() == 0){
                arguments[++pos] = temp;
                exec(argv[1],arguments);
                exit(1);
                }
                else wait(NULL);
            }
            
        }
    exit(0);
}

version2(一次读一个字节)

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

#define MAXN 1024;

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(2, "xrags: arguments are not enough\n");
    }

    char *arguments[1024]; // 子进程参数
    char buf[1];
    
    int pos = -1;
    for (int i = 1; i < argc; i++) arguments[++pos] = argv[i];
    
    int fd[2];
    pipe(fd);
    while (read(0, buf, sizeof(buf)) > 0)   // 从爷爷进程中读取数据
    {
       if(buf[0] != '\n'){
        write(fd[1],buf,1);
       }
       
       else{
        if(fork() > 0){
            wait(NULL);
            continue;
        }

        else{
            char argument[1024] = {0};
            read(fd[0],argument,sizeof(argument));
            arguments[++pos] = argument;

            exec(argv[1],arguments);
            exit(1);
        }
       }
    }
    exit(0);
}