设为首页 加入收藏

TOP

操作系统复习 MITS6.1810 lab util 记录(一)
2023-08-06 07:49:43 】 浏览:337
Tags:MITS6.1810 lab util 记录

lab util

sleep

  1. 介绍:主要用来熟悉下环境以及代码结构。

    • 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.
  2. 代码:

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

pingpong

  1. 单个管道一般用于单向通信,父子进程可通过两个管道进行双向通信。(管道详细行为参考 primes 实验部分)

  2. 代码:

    #include "kernel/types.h"
    #include "user/user.h"
    
    #define BUFFSIZE 128
    
    void perror_exit(char* err_msg) {
      fprintf(2, "%s\n", err_msg);
      exit(-1);
    }
    
    int main(int argc, char *argv[])
    {
      int toson_fd[2];
      int toparent_fd[2];
    
      int ret1 = pipe(toson_fd);
      int ret2 = pipe(toparent_fd);
      if (ret1 == -1 || ret2 == -1) {
        perror_exit("pipe error");
      }
      
      int pid = fork();
      if (pid == -1) { // 
        perror_exit("fork error");
      } else if (pid == 0) { // child process
        close(toson_fd[1]);
        close(toparent_fd[0]);
    
        // read from the pipe1
        char buf[BUFFSIZE];
        int rbytes = read(toson_fd[0], buf, sizeof(buf));
        if (rbytes == -1) {
          perror_exit("read error");
        }
        buf[rbytes] = '\0';
        
        // print the msg from parent
        fprintf(1, "%d: received %s\n", getpid(), buf);
    
        // write response to parent (to pipe2)
        char resp[4] = "pong";
        int ret = write(toparent_fd[1], resp, sizeof(resp));
        if (ret == -1) {
          perror_exit("write error");
        }
      } else { // parent process
        close(toson_fd[0]);
        close(toparent_fd[1]);
    
        // write to son
        char msg[4] = "ping";
        int ret = write(toson_fd[1], msg, sizeof(msg));
        if (ret == -1) {
          perror_exit("write error");
        }
    
        // read from son
        char buf[BUFFSIZE];
        int rbytes = read(toparent_fd[0], buf, sizeof(buf));
        if (rbytes == -1) {
          perror_exit("read");
        }
        buf[rbytes] = '\0';
    
        // print the resp from son
        fprintf(1, "%d: received %s\n", getpid(), buf);
      }
    
      exit(0);
    }
    

primes

介绍

实验要求通过 fork 和 pipe 系统调用建立起如下素数筛的 pipeline.

p = get a number from left neighbor
print p
loop:
    n = get a number from left neighbor
    if (p does not divide n)
        send n to right neighbor

img

思路

CSP 的关键点在于:单个步骤内部操作是串行的,所有步骤之间是并发的。步骤之间的通信通过特定的 channel 完成,这里通过 pipe 完成。

如上图,除去第一个进程和最后一个进程,每个进程有两种身份(父/子)。

分析上述 pipeline, 每个进程需做如下事情:

  1. 从 left-side-pipe 中读取数据,尝试打印素数 prime。

    • 如果 left-side-pipe 的写端关闭且没读到数据,代表没有数据到达。本进程任务结束,正常 exit.
  2. 建立一个新的 right-side-pipe, fork 出一个子进程, 自身即作为“父身份”根据第一步得出的 prime 进行 filter, 将过滤后的数据传入 right-side-pipe. wait 子进程,等待子进程打印结束。

    • 进程 p0 由 shell fork 创建,如果 p0 不 wait 子进程,父进程 p0 可能在所有子进程打印完成前结束,此时 shell 会向终端输出提示符$,造成 $ 穿插在打印结果中的现象。
    • 不 wait:
      • 子进程还在运行,父进程结束 -> 孤儿进程 -> 由 init 收养。缺点:原父进程得不到子进程的状态。
      • 父进程还在运行,子进程结束 -> 僵尸进程。缺点:占用资源得不到释放 (task_struct)。

notes: fork 出来的子进程重复上述操作。

注意点

  • 注意 close(pipe) 的时机,最保险的做法是尽可能早关闭不需要的读写端。
  • wait 操作。
  • 错误处理。

代码

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

#define NULL 0

void perror_exit(char* err_msg) {
  fprintf(2, "%s\n", err_msg);
  exit(-1);
}

void child_processing(int left_pipe[2]) {
  // every process do things below:
  // 0. read from left-side pipe, and try to print a prime.
  // 1. create a new right-side pipe, do fork, pass the filtered dat
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【持续更新】C/C++ 踩坑记录(一) 下一篇VsCode如何配置C语言环境?

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目