国内的OS课程可能只是在表面上教你操作系统的概念,像是在玩一场模拟器游戏,只是看看别人玩的样子,终究还是在OS的世界里迷失了方向。
本文原载自我的个人博客MIT6.S081 lab1
Q1.sleep (easy)
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.
Some hints:
-
Before you start coding, read Chapter 1 of the xv6 book.
(1.先看书捏)
-
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.
(2.看上面几个文件来你如何获取命令行参数)
-
If the user forgets to pass an argument, sleep should print an error message.
(3.没传参需要特殊处理)
-
The command-line argument is passed as a string; you can convert it to an integer using atoi (see user/ulib.c).
(4.命令行输入的参数都是字符串,sleep需要的数字需要用atoi转化成整数)
-
Use the system call sleep.
(5.使用写好的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.
(确保程序最后用系统调用exit()退出)
-
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.
(MakeFile文件里要把sleep加上,这部分我参考的别人的MakeFile)
-
Look at Kernighan and Ritchie's book The C programming language (second edition) (K&R) to learn about C.
(C基础薄弱的可以看这本书)
///user/echo.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int i;
for(i = 1; i < argc; i++){
write(1, argv[i], strlen(argv[i]));
if(i + 1 < argc){
write(1, " ", 1);
} else {
write(1, "\n", 1);
}
}
exit(0);
}
//user/grep.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int fd, i;
char *pattern;
if(argc <= 1){
fprintf(2, "usage: grep pattern [file ...]\n");
exit(1);
}
pattern = argv[1];
if(argc <= 2){
grep(pattern, 0);
exit(0);
}
for(i = 2; i < argc; i++){
if((fd = open(argv[i], 0)) < 0){
printf("grep: cannot open %s\n", argv[i]);
exit(1);
}
grep(pattern, fd);
close(fd);
}
exit(0);
}
//user/rm.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int i;
if(argc < 2){
fprintf(2, "Usage: rm files...\n");
exit(1);
}
for(i = 1; i < argc; i++){
if(unlink(argv[i]) < 0){
fprintf(2, "rm: %s failed to delete\n", argv[i]);
break;
}
}
exit(0);
}
参考一下上面的三个.c文件,很明显看出:
1.argc是参数个数,agrv是个二维字符数组,argv[0]是第一个参数,argv[1]是第二个参数, 那么对于我们要实现的sleep,输入sleep xxx,则sleep是作为argv[0],xxx作为argv[1]。
2.没传sleep需要的参数,需要特判。
3.若有参数,则用atoi把字符串转化成整数,最后调用系统调用sleep
以下是我实现的sleep.c,已通测试
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc,char *argv[]){
int time;
if(argc < 2){
printf("You forget to pass an argument, so I print an error message.");
exit(1);
}
time = atoi(argv[1]);
sleep(time);
exit(0);
}
Q2.pingpong (easy)
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 "<pid>: received ping", where <pid> 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 "<pid>: received pong", and exit. Your solution should be in the file user/pingpong.c.
Some hints:
-
Use pipe to create a pipe.
(使用pipe系统调用来创建管道,这个博主讲的很好,易于理解linux管道pipe详解_linux pipe-CSDN博客)
-
Use fork to create a child.
(使用fork创建子进程,父子通信嘛)
-
Use read to read from the pipe, and write to write to the pipe.
(使用read系统调用来从管道读写)
-
Use getpid to find the process ID of the calling process.
(使用getpid调用获得当前进程id,answer要输出)
-
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.
(用user.h下提供的调用)
Run the program from the xv6 shell and it should produce the following output:
$ make qemu
...
init: starting sh
$ pingpong
4: received ping
3: received pong
$
我的代码如下,已满分:
(想了大半天,知道用两个管道那就很容易了,一锤定easy)
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc,char * argv[]){
int p[2];
int p2[2];
char buf[1024];
pipe(p);
pipe(p2);
char *a = "hello mychild";
char *b = "hello myparent";
if(fork() == 0){
close(p[1]);
int len = read(p[0],buf,sizeof(buf));
if(len > 0)
printf("%d: received ping\n",getpid());
close(p[0]);
close(p2[0]);
write(p2[1],b,strlen(b));
close(p2[1]);
}else{
close(p[0]);
write(p[1],a,strlen(a));
wait((int*)0);
int len = read(p2[0],buf,sizeof(buf));
if(len > 0)
printf("%d: received pong\n",getpid());
close(p[0]);
close(p[1]);
close(p2[0]);
close(p2[1]);
}
exit(0);
}
最近主要在忙别的,后面的题也会好好做,慢慢更~