MIT6.S081 Lab1 Xv6 and Unix utilities(更新ing)

国内的OS课程可能只是在表面上教你操作系统的概念,像是在玩一场模拟器游戏,只是看看别人玩的样子,终究还是在OS的世界里迷失了方向。

本文原载自我的个人博客MIT6.S081 lab1

Q1.sleep (easy)

Implement the UNIX program sleep for xv6; your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your solution should be in the file user/sleep.c.

Some hints:

  • Before you start coding, read Chapter 1 of the xv6 book.

    (1.先看书捏)

  • Look at some of the other programs in user/ (e.g., user/echo.c, user/grep.c, and user/rm.c) to see how you can obtain the command-line arguments passed to a program.

    (2.看上面几个文件来你如何获取命令行参数)

  • If the user forgets to pass an argument, sleep should print an error message.

    (3.没传参需要特殊处理)

  • The command-line argument is passed as a string; you can convert it to an integer using atoi (see user/ulib.c).

    (4.命令行输入的参数都是字符串,sleep需要的数字需要用atoi转化成整数)

  • Use the system call sleep.

    (5.使用写好的sleep系统调用)

  • See kernel/sysproc.c for the xv6 kernel code that implements the sleep system call (look for sys_sleep), user/user.h for the C definition of sleep callable from a user program, and user/usys.S for the assembler code that jumps from user code into the kernel for sleep.

    ()

  • Make sure main calls exit() in order to exit your program.

    (确保程序最后用系统调用exit()退出)

  • Add your sleep program to UPROGS in Makefile; once you've done that, make qemu will compile your program and you'll be able to run it from the xv6 shell.

    (MakeFile文件里要把sleep加上,这部分我参考的别人的MakeFile)

  • Look at Kernighan and Ritchie's book The C programming language (second edition) (K&R) to learn about C.

    (C基础薄弱的可以看这本书)

///user/echo.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
  int i;

  for(i = 1; i < argc; i++){
    write(1, argv[i], strlen(argv[i]));
    if(i + 1 < argc){
      write(1, " ", 1);
    } else {
      write(1, "\n", 1);
    }
  }
  exit(0);
}
//user/grep.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
  int fd, i;
  char *pattern;

  if(argc <= 1){
    fprintf(2, "usage: grep pattern [file ...]\n");
    exit(1);
  }
  pattern = argv[1];

  if(argc <= 2){
    grep(pattern, 0);
    exit(0);
  }

  for(i = 2; i < argc; i++){
    if((fd = open(argv[i], 0)) < 0){
      printf("grep: cannot open %s\n", argv[i]);
      exit(1);
    }
    grep(pattern, fd);
    close(fd);
  }
  exit(0);
}
//user/rm.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

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

  if(argc < 2){
    fprintf(2, "Usage: rm files...\n");
    exit(1);
  }

  for(i = 1; i < argc; i++){
    if(unlink(argv[i]) < 0){
      fprintf(2, "rm: %s failed to delete\n", argv[i]);
      break;
    }
  }

  exit(0);
}

参考一下上面的三个.c文件,很明显看出:

1.argc是参数个数,agrv是个二维字符数组,argv[0]是第一个参数,argv[1]是第二个参数, 那么对于我们要实现的sleep,输入sleep xxx,则sleep是作为argv[0],xxx作为argv[1]。

2.没传sleep需要的参数,需要特判。

3.若有参数,则用atoi把字符串转化成整数,最后调用系统调用sleep

以下是我实现的sleep.c,已通测试

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

int main(int argc,char *argv[]){
    int time;
    if(argc < 2){
        printf("You forget to pass an argument, so I print an error message.");
        exit(1);
    }
    time = atoi(argv[1]);
    sleep(time);
    exit(0);
}

Q2.pingpong (easy)

Write a program that uses UNIX system calls to ''ping-pong'' a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print ": received ping", where is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print ": received pong", and exit. Your solution should be in the file user/pingpong.c.

Some hints:

  • Use pipe to create a pipe.

    (使用pipe系统调用来创建管道,这个博主讲的很好,易于理解linux管道pipe详解_linux pipe-CSDN博客)

  • Use fork to create a child.

    (使用fork创建子进程,父子通信嘛)

  • Use read to read from the pipe, and write to write to the pipe.

    (使用read系统调用来从管道读写)

  • Use getpid to find the process ID of the calling process.

    (使用getpid调用获得当前进程id,answer要输出)

  • Add the program to UPROGS in Makefile.

  • User programs on xv6 have a limited set of library functions available to them. You can see the list in user/user.h; the source (other than for system calls) is in user/ulib.c, user/printf.c, and user/umalloc.c.

    (用user.h下提供的调用)

Run the program from the xv6 shell and it should produce the following output:

    $ make qemu
    ...
    init: starting sh
    $ pingpong
    4: received ping
    3: received pong
    $
  

我的代码如下,已满分:

(想了大半天,知道用两个管道那就很容易了,一锤定easy)

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
 
int main(int argc,char * argv[]){
    int p[2];
    int p2[2];
    char buf[1024];
    pipe(p);
    pipe(p2);
    char *a = "hello mychild";
    char *b = "hello myparent";
    if(fork() == 0){
        close(p[1]);
        int len = read(p[0],buf,sizeof(buf));
        if(len > 0)
            printf("%d: received ping\n",getpid());
        close(p[0]);
        close(p2[0]);
        write(p2[1],b,strlen(b));
        
        close(p2[1]);
    }else{
        close(p[0]);
        write(p[1],a,strlen(a));
        wait((int*)0);
        int len = read(p2[0],buf,sizeof(buf));
        if(len > 0)
            printf("%d: received pong\n",getpid());
        close(p[0]);
        close(p[1]);
        close(p2[0]);
        close(p2[1]);

    }

    exit(0);
}

最近主要在忙别的,后面的题也会好好做,慢慢更~

你可能感兴趣的:(操作系统,unix,服务器,c语言,ubuntu,gnu,linux)