Lab Util report
Boot Xv6 (easy)
没啥复杂的,按照教程来就可以了,基本没踩坑。
Sleep
描述: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.
指导(可以称得上是保姆级了。。。):
- 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, and user/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.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.
- 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.
- Look at Kernighan and Ritchie’s book The C programming language (second edition) (K&R) to learn about C.
按照教程即可。代码如下:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc, char *argv[])
{
int t;
if (argc <= 1 || argc > 2) {
fprintf(2, "usage: sleep <seconds>\n");
exit(1);
}
t = atoi(argv[1]);
sleep(t);
exit(0);
}
实现sleep命令没啥好讲的,实际上好玩的是sleep syscall的实现,即如何从用户态陷入内核空间,进而完成sleep命令的。
首先在user.h中声明了sleep这个函数,在usys.S中看到,首先.global sleep在全局符号表中注册函数名sleep,之后调用sleep这个系统调用时就会执行以下这段riscv汇编代码:
.global sleep
sleep:
li a7, SYS_sleep
ecall
ret
这段汇编的意思也很明确,就是把SYS_sleep的值放入a7寄存器中,记录系统调用的类型,之后的ecall指令产生一个异常,此时陷入内核态,然后查看kernel/syscall.c可知SYS_sleep和sys_sleep存在映射关系,syscall函数可以根据SYS_<name>值的不同执行不同的sys_<name>函数(kernel/syscall.c:140)。
void
syscall(void)
{
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
p->trapframe->a0 = syscalls[num]();
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}
反正目前看kernel/syscall.c里的syscall实现,是通过中断实现的(trapframe),具体的实现会等到后面的实验再详细解释。
以上是一个基本的理解,更详细的了解估计在后面的课程中会涉及。
参考:
- riscv特权等级介绍:riscv特权等级
- riscv指令手册:riscv-spec
PingPong
描述: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.
指导:
- Use pipe to create a pipe.
- Use fork to create a child.
- Use read to read from the pipe, and write to write to the pipe.
- Use getpid to find the process ID of the calling process.
- 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.
之前实现过unix的版本,直接把代码copy稍作改动即可。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main()
{
int p[2], q[2];
pipe(p), pipe(q);
if (fork() > 0) {
close(p[0]);
close(q[1]);
char x[1];
write(p[1], "0", 1);
read

本文介绍了在 xv6 操作系统中实现 sleep 系统调用、并发 ping-pong 程序、并发 primes 素数筛选、find 文件查找以及 xargs 命令行工具的过程。通过阅读 xv6 代码,理解系统调用、管道、进程创建和同步等概念,加深了对操作系统内核和并发编程的理解。
最低0.47元/天 解锁文章
379

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



