Sleep
easy-
实现 Unix 程序
sleepfor xv6: 暂停指定的 ticks(ticks 的定义由xv6内核提供) 解决方案应该在user/sleep.c - 提示:
- https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf 的 Chapter 1
- 参考
user目录下的其他命令 - 如果用户忘记传参数,应该返回错误信息
- 命令行参数应该以 string 类型传递,可以在代码层使用
user/lib.c下的atoi函数将字符串转换成一个 integer - 使用系统调用
sleep - 查看
kernel/sysproc.c中实现的sleep系统调用,user/user.h中定义了sleep用户调用的函数名,user/usys.S中的汇编代码实现了sleep调用从用户态跳转到内核态 - 确保
main调用exit()结束代码 - 加入实现的
sleep程序到 Makefile 的UPROGS中。这样在重新 make qemu 时就能运行sleep - 学习 C 语言开发
实验过程
- 运行:
-
make qemu sleep 10 - 进行评分
-
./grade-lab-util sleep
实验笔记
- {{embed ((68c3424b-2a2a-4e9f-b4ea-ab13675a5098))}}
- 核心代码:
#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" int main(int argc, char **argv) { if (argc < 2) { printf("usage: sleep <ticks>\n"); exit(1); } sleep(atoi(argv[1])); exit(0); }
pingpong
easy-
编写一个程序,程序使用 UNIX 的系统调用将一个字节“打乒乓球”似的在两个管道进程中传递。父进程发送一个字节到子进程,子进程应该打印
<pid>:received ping,<pid>是这个进程的PID,并且子进程写回这个字节给父进程,然后退出。父进程读取到这个子进程发送回的字节,打印<pid>: received pong,然后退出。解决方案应该在user/pingpong.c
-
- 提示:
- 使用
pipe创建一个管道 - 使用
fork创建一个子进程 - 使用
read从管道中读取,使用write写入管道 - 添加到
UPROGS到 Makefile - 用户程序的库是有限的
- 使用
- 核心代码:
#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" int main(int argc, char **argv) { int pipe_p2c[2], pipe_c2p[2]; // 创建管道,在数组中写入管道读端和写端的文件描述符,[0]是读取端,[1]是写入端 pipe(pipe_p2c); pipe(pipe_c2p); char ball = '.'; if (fork() != 0) { write(pipe_p2c[1], &ball, 1); close(pipe_p2c[1]); char buf; read(pipe_c2p[0], &buf, 1); printf("%d: received pong\n", getpid()); wait(0); } else { char buf; read(pipe_p2c[0], &buf, 1); printf("%d: received ping\n", getpid()); write(pipe_c2p[1], &buf, 1); close(pipe_c2p[1]); } close(pipe_c2p[0]); close(pipe_p2c[0]); exit(0); }
Primes
hard-
编写一个并发版本的质数筛。
{:height 175, :width 698} - 核心代码:
#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" #define END_MARKER -1 #define MAX_NUMBER 35 void sieve_process(int read_fd) { int prime; int bytes_read = read(read_fd, &prime, sizeof(prime)); if (bytes_read == 0 || prime == END_MARKER) { close(read_fd); exit(0); } printf("prime %d\n", prime); int next_pipe[2]; pipe(next_pipe); if (fork() == 0) { close(read_fd); close(next_pipe[1]); sieve_process(next_pipe[0]); } else { close(next_pipe[0]); int number; while (read(read_fd, &number, sizeof(number)) > 0) { if (number == END_MARKER) { write(next_pipe[1], &number, sizeof(number)); break; } if (number % prime != 0) { write(next_pipe[1], &number, sizeof(number)); } } close(read_fd); close(next_pipe[1]); wait(0); exit(0); } } int main(int argc, char **argv) { int numbers_pipe[2]; pipe(numbers_pipe); if (fork() == 0) { close(numbers_pipe[1]); sieve_process(numbers_pipe[0]); } else { close(numbers_pipe[0]); for (int i = 2; i <= MAX_NUMBER; i++) { write(numbers_pipe[1], &i, sizeof(i)); } int end_marker = END_MARKER; write(numbers_pipe[1], &end_marker, sizeof(end_marker)); close(numbers_pipe[1]); wait(0); } exit(0); }