文章目录
- 一、boot xv6
- 二、sleep
- 三、pingpong
- 四、primes
- 五、find
- 六、xargs
该实验主要用来熟悉xv6以及其系统调用
一、boot xv6
实验目的:
- 启动xv6系统,并使用提供的命令
- ls,列出系统所有的文件
- ctrl + p,打印当前运行的进程
- ctrl + a,再按 x,退出qemu
实验结果:
二、sleep
实验目的:
- 通过xv6提供的sleep系统调用实现用户层的sleep函数,代码编写在user/sleep.c文件中
- 需要将sleep添加到Makefile的UPROGS中,这样执行make qemu会将sleep编译
- ./grade-lab-util sleep 进行验证(在虚拟机中执行,不是在xv6中执行)
实验代码:
#include "kernel/types.h"
#include "user/user.h"
int
main(int argc, char *argv[]){
int num;
if(argc != 2){
fprintf(2, "sleep must have 1 parameters!\n");
exit(1);
}
num = atoi(argv[1]);
printf("(nothing happens for a little while)\n");
sleep(num);
exit(0);
}
需要在Makefile中添加sleep的编译项:
实验结果:
三、pingpong
实验要求:
- 编写一个pingpong程序,父进程发送一个字节给子进程,子进程收到后,打印 < PID>:received ping,然后写一个字节给父进程并退出,父进程收到后打印 < pid>:received pong,然后退出
- 使用 pipe 创建一对管道
- 使用 fork创建子进程
- 使用read、write读写通道
- 使用 getpid 获取进程ID
实验代码:
#include "kernel/types.h"
#include "user/user.h"
int
main(int argc, char *argv[]){
char msg = 'm';
int length = sizeof(msg);
int p1[2]; //父-->子
int p2[2]; //子-->父
pipe(p1);
pipe(p2);
if(fork() == 0){
close(p1[1]);
close(p2[0]);
//子进程
if(read(p1[0], &msg, length) != length){
printf("child read parent msg error\n");
exit(1);
}
printf("%d: received ping\n", getpid());
if(write(p2[1], &msg, length) != length){
printf("child send msg to parent error\n");
exit(1);
}
exit(0);
}
close(p1[0]);
close(p2[1]);
if(write(p1[1], &msg, length) != length){
printf("parent send msg to child error\n");
exit(1);
}
if(read(p2[0], &msg, length) != length){
printf("parent read child msg error\n");
exit(1);
}
printf("%d: received pong\n", getpid());
wait(0); //不关心子进程的退出状态
exit(0);
}
实验结果:
四、primes
实验要求:
- 使用管道来计算2-35之间的所有素数
- 父进程输入 2 -35
- 对于每个素数,都会产生一个子进程,从管道接收数据,打印当前素数,并将剩下的素数写入另一个管道
实验代码:
#include "kernel/types.h"
#include "user/user.h"
void find_prime(int *input, int num){
if(num == 1){
printf("prime %d\n", *input);
return;
}
int p[2],i;
int prime = *input;
int temp;
printf("prime %d\n", prime);
pipe(p);
for(i = 0; i < num; i++){
temp = *(input + i);
write(p[1], (char *)(&temp), 4);
}
close(p[1]);
if(fork() == 0){
int counter = 0;
char buffer[4];
while(read(p[0], buffer, 4) != 0){
temp = *((int *)buffer);
if(temp % prime != 0){
*input = temp;
input += 1;
counter++;
}
}
find_prime(input - counter, counter);
exit(0);
}
wait(0);
}
int main(){
int input[34];
int i = 0;
for(; i < 34; i++){
input[i] = i+2;
}
find_prime(input, 34);
exit(0);
}
实验结果:
五、find
实验要求:
- 编写 find 的简易版,可以查找具有特定名称的所有文件
- 使用递归,查找子目录
- 不要递归查找
. 和 ..
目录
实验代码:
在这里插入代码片
实验结果:
六、xargs
实验要求:
- 将前一个命令的输出附加到后一个命令上
- echo hello too | xargs echo bye,则echo hello too的输出 hello too,作为附加参数给 echo bye指令
实验代码:
#include "kernel/types.h"
#include "user/user.h"
#include "kernel/param.h"
int main(int argc, char *argv[]){
int i;
int cmd_len = 0;
int buf_len;
char buf[32];
char *cmd[MAXARG];
//读取 xargs 后面的参数,即最终要执行的命令
for(i = 1; i < argc; i++){
cmd[cmd_len++] = argv[i];
}
//read读取管道的输出,即面前的命令的执行结果,并进行处理
while((buf_len = read(0, buf, sizeof(buf))) > 0){
char xargs[32] = {"\0"}; //追加参数
cmd[cmd_len] = xargs;
for(i = 0; i < buf_len; i++){
if(buf[i] == '\n'){
if(fork() == 0){
exec(argv[1], cmd);
}
wait(0);
} else {
xargs[i] = buf[i];
}
}
}
exit(0);
}
实验结果: