Implement a user-level sleep program for xv6, along the lines of the UNIX sleep command. 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.
Write a user-level program that uses xv6 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.
编写一个用户级程序,使用 xv6 系统调用在一对管道之间“乒乓”传输一个字节,每个方向一个管道。父进程应向子进程发送一个字节;子进程应打印“pid: received ping”,其中pid是其进程 ID,将字节写入管道给父进程,然后退出;父进程应从子进程读取字节,打印“pid: received pong”,然后退出。你的解决方案应放在文件 user/pingpong.c 中。
#include "kernel/types.h"
#include "user/user.h"
int
main()
{
int parent_fd[2];
int child_fd[2];
char buf[1];
if (pipe(parent_fd) < 0 || pipe(child_fd) < 0) {
fprintf(2, "pipe error\n");
exit(1);
}
int pid = fork();
if (pid < 0) {
fprintf(2, "fork error\n");
exit(1);
} else if (pid == 0) {
// child
close(parent_fd[1]);
close(child_fd[0]);
if (read(parent_fd[0], buf, sizeof(buf)) != 1) {
fprintf(2, "read error\n");
exit(1);
}
printf("%d: received ping\n", getpid());
if (write(child_fd[1], buf, sizeof(buf))!= 1) {
fprintf(2, "write error\n");
exit(1);
}
close(parent_fd[0]);
close(child_fd[1]);
exit(0);
} else {
// parent
close(parent_fd[0]);
close(child_fd[1]);
if (write(parent_fd[1], buf, sizeof(buf))!= 1) {
fprintf(2, "write error\n");
exit(1);
}
if (read(child_fd[0], buf, sizeof(buf))!= 1) {
fprintf(2, "read error\n");
exit(1);
}
printf("%d: received pong\n", getpid());
close(parent_fd[1]);
close(child_fd[0]);
exit(0);
}
}
primes (moderate/hard)
Write a concurrent prime sieve program for xv6 using pipes and the design illustrated in the picture halfway down this page and the surrounding text. This idea is due to Doug McIlroy, inventor of Unix pipes. Your solution should be in the file user/primes.c.
为 xv6 编写一个并发素数筛程序,使用管道和本页中间图片及周围文字所示的设计。这个想法归功于 Unix 管道的发明者 Doug McIlroy。你的解决方案应该在文件 user/primes.c 中。
// child
close(p[1]); // 关闭写端
int prime;
while (read(p[0], &prime, sizeof(prime)) == sizeof(prime)) {
printf("prime %d\n", prime);
int new_p[2]; // 创建新管道
pipe(new_p);
int num; // 过滤素数
while(read(p[0], &num, sizeof(num)) == sizeof(num)) {
if (num % prime != 0) {
if (write(new_p[1], &num, sizeof(num))) {
fprintf(2, "write error\n");
exit(1);
}
}
}
close(new_p[1]);
}
close(p[0]);
exit(0);
需要把这部分抽象成函数,代码:
#include "kernel/types.h"
#include "user/user.h"
void child(int p[2]);
int
main()
{
int p[2];
if (pipe(p) < 0) {
fprintf(2, "pipe error\n");
exit(1);
}
int pid = fork();
if (pid < 0) {
fprintf(2, "fork error\n");
exit(1);
} else if (pid == 0) {
child(p);
} else {
// parent
close(p[0]);
for (int i = 2; i <= 280; i++) {
if (write(p[1], &i, sizeof(i)) != sizeof(i)) {
fprintf(2, "write error\n");
exit(1);
}
}
close(p[1]);
wait(0);
exit(0);
}
}
void child(int p[2]) {
// child
close(p[1]);
int prime;
if (read(p[0], &prime, sizeof(prime)) != sizeof(prime)) {
close(p[0]);
exit(0);
}
printf("prime %d\n", prime);
int new_p[2];
pipe(new_p);
int pid = fork();
if (pid < 0) {
fprintf(2, "fork error\n");
exit(1);
} if (pid == 0) {
close(new_p[1]);
child(new_p);
} else {
close(new_p[0]);
int num;
while (read(p[0], &num, sizeof(num)) == sizeof(num)) {
if (num % prime != 0) {
if (write(new_p[1], &num, sizeof(num)) != sizeof(num)) {
fprintf(2, "write error\n");
exit(1);
}
}
}
close(new_p[1]);
close(p[0]);
wait(0);
exit(0);
}
}
但是结果出现错误,后期乱码,怀疑是某个管道未正确关闭。
tinuvile@LAPTOP-7PVP3HH3:~/xv6-labs-2024$ make qemu
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -global virtio-mmio.force-legacy=false -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
xv6 kernel is booting
hart 2 starting
hart 1 starting
init: starting sh
$ primes
prime 2
prime 3
prime 5
prime 7
prime 11
prime 13
prime 17
prime 19
prime 23
prime 29
prime 31
prime 37
$ /5;=CGIOSYaegkmq�����������������������
$QEMU: Terminated
Write a simple version of the UNIX find program for xv6: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c.
为 xv6 编写一个简单的 UNIX find 程序版本:在目录树中查找具有特定名称的所有文件。你的解决方案应该在文件 user/find.c 中。
xv6 kernel is booting
hart 2 starting
hart 1 starting
init: starting sh
$ echo > b
$ mkdir a
$ echo > a/b
$ mkdir a/aa
$ echo > a/aa/b
$ find . b
./b
./a/b
./a/aa/b
xargs (moderate)
Write a simple version of the UNIX xargs program for xv6: its arguments describe a command to run, it reads lines from the standard input, and it runs the command for each line, appending the line to the command's arguments. Your solution should be in the file user/xargs.c.
为 xv6 编写一个简单的 UNIX xargs 程序版本:其参数描述了要运行的命令,它从标准输入读取行,并为每一行运行命令,将该行附加到命令的参数中。你的解决方案应该在文件 user/xargs.c 中。
xv6 kernel is booting
hart 1 starting
hart 2 starting
init: starting sh
$ sh < xargstest.sh
$ $ $ $ $ $ hello
hello
hello
通过。
那么这个Lab除了一些拓展练习就全部写完了,拓展练习有时间再写吧。
Optional challenge exercises
Write an uptime program that prints the uptime in terms of ticks using the uptime system call. (easy)
编写一个 uptime 程序,使用 uptime 系统调用以滴答数打印运行时间。(简单)
Support regular expressions in name matching for find. grep.c has some primitive support for regular expressions. (easy)
在名称匹配中支持正则表达式。 grep.c 对正则表达式有一些基本的支持。(简单)
The xv6 shell (user/sh.c) is just another user program. It lacks many features found in real shells, but you can modify and improve it. For example, modify the shell to not print a $ when processing shell commands from a file (moderate), modify the shell to support wait (easy), modify the shell to support tab completion (easy), modify the shell to keep a history of passed shell commands (moderate), or anything else you would like your shell to do. (If you are very ambitious, you may have to modify the kernel to support the kernel features you need; xv6 doesn't support much.)
xv6 shell( user/sh.c )只是另一个用户程序。它缺少真实 shell 中的许多功能,但你可以修改和改进它。例如,修改 shell 使其在处理来自文件的 shell 命令时不打印 $ (中等难度),修改 shell 以支持 wait(简单),修改 shell 以支持 tab 补全(简单),修改 shell 以保留已执行 shell 命令的历史记录(中等难度),或者任何你希望 shell 实现的功能。(如果你非常有雄心壮志,你可能需要修改内核以支持你所需的内核功能;xv6 不支持太多功能。)