更好的阅读体验
-
官方材料:https://pdos.csail.mit.edu/6.S081/2021/labs/util.html
-
参考资料:
-
https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/
-
https://th0ar.gitbooks.io/xv6-chinese/content/
-
https://blog.miigon.net/posts/s081-ending/
-
https://wangchujiang.com/linux-command/
-
Boot xv6 (easy)
$ git clone git://g.csail.mit.edu/xv6-labs-2021
Cloning into 'xv6-labs-2021'...
...
$ cd xv6-labs-2021
$ git checkout util
Branch 'util' set up to track remote branch 'util' from 'origin'.
Switched to a new branch 'util'
Build and run xv6:
$ make qemu
riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel/entry.S
riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -DSOL_UTIL -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o kernel/start.o kernel/start.c
...
riscv64-unknown-elf-ld -z max-page-size=4096 -N -e main -Ttext 0 -o user/_zombie user/zombie.o user/ulib.o user/usys.o user/printf.o user/umalloc.o
riscv64-unknown-elf-objdump -S user/_zombie > user/zombie.asm
riscv64-unknown-elf-objdump -t user/_zombie | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > user/zombie.sym
mkfs/mkfs fs.img README user/xargstest.sh user/_cat user/_echo user/_forktest user/_grep user/_init user/_kill user/_ln user/_ls user/_mkdir user/_rm user/_sh user/_stressfs user/_usertests user/_grind user/_wc user/_zombie
nmeta 46 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 1) blocks 954 total 1000
balloc: first 591 blocks have been allocated
balloc: write bitmap block at sector 45
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -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
$
ls 命令:
$ ls
. 1 1 1024
.. 1 1 1024
README 2 2 2059
xargstest.sh 2 3 93
cat 2 4 24256
echo 2 5 23080
forktest 2 6 13272
grep 2 7 27560
init 2 8 23816
kill 2 9 23024
ln 2 10 22880
ls 2 11 26448
mkdir 2 12 23176
rm 2 13 23160
sh 2 14 41976
stressfs 2 15 24016
usertests 2 16 148456
grind 2 17 38144
wc 2 18 25344
zombie 2 19 22408
console 3 20 0
xv6没有ps命令,Ctrl-p命令可以让kernel打印每个进程的信息
退出 qemu : Ctrl-a x.
编程样例
在实现对应功能后,需要更新Makefile的UPROGS部分,例如实现了sleep.c后,要在UPROGS处追加:
$U/_sleep\
copy.c:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main() {
char buf[64];
while(1) {
int n = read(0, buf, sizeof(buf));
if(n <= 0) break;
write(1, buf, n);
}
exit(0);
}
-
第一个参数是文件描述符,指向一个之前打开的文件。Shell会确保默认情况下,当一个程序启动时,文件描述符0连接到console的输入,文件描述符1连接到了console的输出。所以我可以通过这个程序看到console打印我的输入。当然,这里的程序会预期文件描述符已经被Shell打开并设置好。这里的0,1文件描述符是非常普遍的Unix风格,许多的Unix系统都会从文件描述符0读取数据,然后向文件描述符1写入数据。
-
read的第二个参数是指向某段内存的指针,程序可以通过指针对应的地址读取内存中的数据,这里的指针就是代码中的buf参数。在代码第10行,程序在栈里面申请了64字节的内存,并将指针保存在buf中,这样read可以将数据保存在这64字节中。
-
read的第三个参数是代码想读取的最大长度,sizeof(buf)表示,最多读取64字节的数据,所以这里的read最多只能从连接到文件描述符0的设备,也就是console中,读取64字节的数据。
open.c:
#include "kernel/types.h"
#include "user/user.h"
#include "kernel/fcntl.h"
int
main()
{
int fd = open("output.txt", O_WRONLY | O_CREATE);
write(fd, "ooo\n", 4);
exit(0);
}
-
代码中的第8行,执行了open系统调用,将文件名output.txt作为参数传入,第二个参数是一些标志位,用来告诉open系统调用在内核中的实现:我们将要创建并写入一个文件。open系统调用会返回一个新分配的文件描述符,这里的文件描述符是一个小的数字,可能是2,3,4或者其他的数字。
-
之后,这个文件描述符作为第一个参数被传到了write,write的第二个参数是数据的指针,第三个参数是要写入的字节数。数据被写入到了文件描述符对应的文件中。
-
文件描述符本质上对应了内核中的一个表单数据。内核维护了每个运行进程的状态,内核会为每一个运行进程保存一个表单,表单的key是文件描述符。这个表单让内核知道,每个文件描述符对应的实际内容是什么。这里比较关键的点是,每个进程都有自己独立的文件描述符空间,所以如果运行了两个不同的程序,对应两个不同的进程,如果它们都打开一个文件,它们或许可以得到相同数字的文件描述符,但是因为内核为每个进程都维护了一个独立的文件描述符空间,这里相同数字的文件描述符可能会对应到不同的文件。
fork.c:
#include "kernel/types.h"
#include "user/user.h"
int
main()
{
int pid;
pid = fork();
printf("fork() returned %d\n", pid);
if(pid == 0) {
printf("child\n");
} else {
printf("parent\n");
}
exit(0);
}
-
fork会拷贝当前进程的内存,并创建一个新的进程,这里的内存包含了进程的指令和数据。之后,我们就有了两个拥有完全一样内存的进程。fork系统调用在两个进程中都会返回,在原始的进程中,fork系统调用会返回大于0的整数,这个是新创建进程的ID。而在新创建的进程中,fork系统调用会返回0。所以即使两个进程的内存是完全一样的,我们还是可以通过fork的返回值区分旧进程和新进程。
-
在第11行,你可以看到代码检查pid。如果pid等于0,那么这必然是子进程。在我们的例子中,调用进程通常称为父进程,父进程看到的pid必然大于0。所以父进程会打印“parent”,子进程会打印“child”。之后两个进程都会退出。
$ fork
fork() returned 5
parent
$ fork() returned 0
child
redirected.c:
#include "kernel/types.h"
#include "kernel/fcntl.h"
#include "user/user.h"
int main()
{
int pid;
pid = fork();
if(pid == 0) {
close(1);
open("output.txt", O_WRONLY|O_CREATE);
char *argv[] = {
"echo", "this", "is", "redirected", "echo", 0};
exec("echo", argv);
printf("exec failed!\n");
exit(1);
} else {
wait((int*) 0);
}
exit(0);
}
$ redirected
$ cat output.txt
this is redirected echo
sleep (easy)
Implement the UNIX program
sleepfor xv6; yoursleepshould 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 fileuser/sleep.c.
Some hints:
- Before you start coding, read Chapter 1 of the xv6 book.
- Look at some of the other programs in
user/(e.g.,user/echo.c,user/grep.c, anduser/rm.c) to see how you can obtain the command-line arguments passed to a program. - If the user forgets to pass an argument, sleep should print an error message.
- The command-line argument is passed as a string; you can convert it to an integer using
atoi(see user/ulib.c). - Use the system call
sleep. - See
kernel/sysproc.cfor the xv6 kernel code that implements thesleepsystem call (look forsys_sleep),user/user.hfor the C definition ofsleepcallable from a user program, anduser/usys.Sfor the assembler code that jumps from user code into the kernel forsleep. - Make sure
maincallsexit()in order to exit your program. - Add your
sleepprogram toUPROGSin Makefile; once you’ve done that,make qemuwill compile your program and you’ll be able to run it from the xv6 shell. - Look at Kernighan and Ritchie’s book The C programming language (second edition) (K&R) to learn about C.
sleep.c:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc < 2) {
fprintf(2
提升阅读体验:XV6实用编程教程详解

本文介绍了如何在XV6环境中使用Git进行代码管理和操作,如克隆、切换分支,以及如何构建和运行xv6kernel,包括ls、echo、fork、open等编程样例的实现和测试。此外,还涵盖了如sleep、pingpong、primes、find和xargs等实用程序的编写及测试指南。
最低0.47元/天 解锁文章
1653

被折叠的 条评论
为什么被折叠?



