zoukankan      html  css  js  c++  java
  • MIT6.S081 Lab Utilities

    Lab Utilities

    本章实验学习xv6的一些softerware tools的实现,学习系统调用。
    学习进程、文件相关的系统调用使用。

    sleep

    使用sleep系统调用,暂停指定的ticks(一个tick代表两次时钟中断的时间间隔)。
    使用exit系统调用终止当前进程。

    #include "kernel/types.h"
    #include "user/user.h"
    
    int
    main(int argc, char *argv[])
    {
        if(argc <= 1){
            fprintf(2, "usage: sleep clock ticks\n");
            exit(1);
        }
    
        sleep(atoi(argv[1]));
    
        exit(0);
    }
    

    pingpong

    使用read和write系统调用利用管道进行进程间通信。
    使用close系统调用关闭不用的管道端。
    管道read是阻塞式的,除非对端有数据写入,或者所有指向对端的文件描述符被close掉然后read返回0。

    #include "kernel/types.h"
    #include "user/user.h"
    
    int
    main(int argc, char *argv[])
    {
        int pipe1[2], pipe2[2];
        char buf[1];
    
        if(pipe(pipe1) < 0 || pipe(pipe2) < 0){
            fprintf(2, "pingpong: pipe failed\n");
            exit(1);
        }
    
        if(fork() == 0){
            close(pipe1[1]);
            close(pipe2[0]);
    
            read(pipe1[0], buf, 1);
            printf("%d: received ping\n", getpid());
            write(pipe2[1], "1", 1);
        } else {
            close(pipe1[0]);
            close(pipe2[1]);
    
            write(pipe1[1], "1", 1);
            read(pipe2[0], buf, 1);
            printf("%d: received pong\n", getpid());
        }
    
        exit(0);
    }
    

    primes

    参考素数筛在论文中的实现。
    地址的理解:write时,将i的地址传入,长度设为4,则write写入的是从i所在地址的长度为4字节的字符串,本质是将i的值以字符串形式传出。
    在pipeline中,可以借鉴xv6的shell设计的思路(Chapter1 1.3),做I/O重定向,这样做的好处是将main和pipeline做了解耦,不需要将管道作为参数传递并且处理,直接使用fd=0的描述符进行读取。
    使用dup系统调用和wait系统调用。
    及时close不用的管道端口,否则程序会有问题(我这里是不停的打印0,很难调试出原因,应该是内存有限)。

    #include "kernel/types.h"
    #include "user/user.h"
    
    void
    pipeline()
    {
        int p[2];
        int prime;
    
        if (read(0, &prime, 4) == 0) {
            exit(0);
        }
        printf("prime %d\n", prime);
    
        pipe(p);
    
        if (fork() == 0) {
            close(0);
            dup(p[0]);
            close(p[0]);
            close(p[1]);
    
            pipeline();
        } else {
            close(p[0]);
    
            int number;
            while (read(0, &number, 4) == 4) {
                if (number % prime != 0) {
                    write(p[1], &number, 4);
                }
            }
    
            close(p[1]);
    
            wait((int*)0);
        }
        exit(0);
    }
    
    int
    main(int argc, char *argv[])
    {
        int p[2];
    
        pipe(p);
    
        if (fork() == 0) {
            close(0);
            dup(p[0]);
            close(p[0]);
            close(p[1]);
    
            pipeline();
        } else {
            close(p[0]);
    
            for (int i = 2; i <= 35; i++) {
                write(p[1], &i, 4);
            }
            close(p[1]);
    
            wait((int *)0);
        }
        exit(0);
    }
    

    find

    目录本质上是一个文件,type是T_DIR,该文件对应的数据是一系列目录项,每个目录项dirent由名称和inode索引组成。
    找该给定目录下的所有目录项,除了当前目录和上级目录,如果目录项是目录,递归查找(给定目录找文件);如果目录项是文件,对比文件名称,相同则输出。
    inode number为0的目录项不可用(Chapter 8.11)。
    使用fstat系统调用,熟悉dirent和stat结构体。

    #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 file[])
    {
        char buf[512], *p;
        int fd;
        struct dirent de;
        struct stat st;
    
        if((fd = open(path, 0)) < 0){
            fprintf(2, "find: cannot open %s\n", path);
            return;
        }
    
        if(fstat(fd, &st) < 0){
            fprintf(2, "find: cannot stat %s\n", path);
            close(fd);
            return;
        }
    
        switch(st.type)
        {
        case T_FILE:
            if (strcmp(fmtname(path), file) == 0)
                printf("%s\n", path);
            break;
    
        case T_DIR:
            if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
                fprintf(2, "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)
                    continue;
    
                if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
                    continue;
    
                memmove(p, de.name, DIRSIZ);
                p[DIRSIZ] = 0;
    
                find(buf, file);
            }
            break;
        }
        close(fd);
    }
    
    int
    main(int argc, char *argv[])
    {
        if(argc < 3){
            fprintf(2, "Usage: find path file\n");
            exit(1);
        }
    
        find(argv[1], argv[2]);
    
        exit(0);
    }
    
    

    xargs

    从标准输入读取行,并每行运行一次命令。
    之所以从标准输入读,是因为shell实现了pipelines,通过创建管道链接pipelines左端和右端。来自左端的结果,输出至fd=1,这里管道的写端重定向到fd=1。右端的读端重定向到fd=0。
    所以左端的结果需要成为右端的参数。
    使用exec系统调用,失败才回到xargs的main。

    #include "kernel/types.h"
    #include "user/user.h"
    #include "kernel/param.h"
    
    int
    main(int argc, char *argv[])
    {
        char *arguments[MAXARG], buf[512];
    
        if(argc < 2) {
            fprintf(2, "Usage: xargs command\n");
            exit(1);
        }
    
        if (argc + 1 > MAXARG) {
            fprintf(2, "xargs: argument too much\n");
            exit(1);
        }
    
        for (int i = 1; i < argc; i++)
            arguments[i-1] = argv[i];
    
        char *p = buf;
        while (read(0, p, 1) == 1) {
            if (*p == '\n') {
                *p = '\0';
                arguments[argc-1] = buf;
    
                if (fork() == 0) {
                    exec(argv[1], arguments);
    
                    fprintf(2, "exec %s failed\n", argv[1]);
                    exit(0);
                } else {
                    wait((int*)0);
                }
    
                p = buf;
            } else {
                p++;
            }
        }
    
        exit(0);
    }
    

    Code

    Code:Lab util

  • 相关阅读:
    Bom入门
    Dom入门
    JavaScript对象
    Ultra-QuickSort——[归并排序、分治求逆序对]
    UVA 11212 Editing a Book [迭代加深搜索IDA*]
    Anagram——[枚举全排列]
    Black Box--[优先队列 、最大堆最小堆的应用]
    Argus--[优先队列]
    UVa1601
    UVa 10603 Fill [暴力枚举、路径搜索]
  • 原文地址:https://www.cnblogs.com/seaupnice/p/15775089.html
Copyright © 2011-2022 走看看