Lab1 Utilities
这个lab只是实现了几个Unix的实用工具,熟悉xv6的使用!
Boot xv6 (easy)
准备环境 arch linux
一键配置
$ yay -S risc-v qemu-emulators-full
$ git clone git://g.csail.mit.edu/xv6-labs-2020
$ cd xv6-labs-2020
$ git checkout util
$ make qemu
sleep(easy)
实现代码前,记得在Makefile
中添加sleep
的构建文件
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("The input parameter is incorrect!\n");
}
else
{
int t = atoi(argv[1]);
sleep(t);
}
exit(0);
}
pingpong (easy)
fork创建子进程,创建管道,实现父子进程之间的数据传输
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main()
{
int pipefd[2];
char write_buffer[1] = "0";
char read_buffer[1];
if (pipe(pipefd) == -1)
{
printf("Create Pipe is Fail!\n");
exit(1);
}
int pid;
pid = fork();
if (pid < 0)
{
printf("Create Child is Fail!\n");
exit(1);
}
else if (pid == 0)
{
read(pipefd[0], read_buffer, 1);
printf("%d: received ping\n", getpid());
write(pipefd[1], read_buffer, 1);
}
else
{
write(pipefd[1], write_buffer, 1);
read(pipefd[0], read_buffer, 1);
printf("%d: received pong\n", getpid());
}
exit(0);
}
primes (moderate)/(hard)
通过多进程实现埃氏筛算法,很有意思的一道题目。
主进程:生成 n ∈ [2,35] -> 子进程1:筛掉所有 2 的倍数 -> 子进程2:筛掉所有 3 的倍数 -> 子进程3:筛掉所有 5 的倍数 -> .....
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#define MAXNUM 36
void Prime_filtering(int readfd, int writefd)
{
char nums[MAXNUM];
read(readfd, nums, MAXNUM);
int prime = 0;
for (int i = 0; i < MAXNUM; i++)
{
if (nums[i] == '0')
{
prime = i;
break;
}
}
if (prime == 0)
{
exit(0);
}
printf("prime %d\n", prime);
nums[prime] = '1';
for (int i = prime * 2; i < MAXNUM; i++)
{
if (i % prime == 0)
{
nums[i] = '1';
}
}
int pid;
pid = fork();
if (pid < 0)
{
printf("Create Child is Fail!\n");
exit(1);
}
else if (pid == 0)
{
Prime_filtering(readfd, writefd);
wait(0);
}
else
{
write(writefd, nums, MAXNUM);
wait(0);
}
}
int main()
{
char nums[MAXNUM];
memset(nums, '0', sizeof(nums));
int pipefd[2];
if (pipe(pipefd) == -1)
{
printf("Create Pipe is Fail!\n");
exit(1);
}
int pid;
pid = fork();
if (pid < 0)
{
printf("Create Child is Fail!\n");
exit(1);
}
else if (pid == 0)
{
Prime_filtering(pipefd[0], pipefd[1]);
wait(0);
}
else
{
nums[0] = '1';
nums[1] = '1';
write(pipefd[1], nums, MAXNUM);
wait(0);
}
exit(0);
}
find (moderate)
实现查找,参考ls.c
几乎是照抄
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fs.h"
#include "user/user.h"
void find(char *BaseDir, char *FindDir)
{
struct stat st;
struct dirent dt;
int dirfd;
if ((dirfd = open(BaseDir, 0)) < 0)
{
printf("Open dir is Fail\n");
return;
}
if (fstat(dirfd, &st) < 0 || st.type != T_DIR)
{
printf("Get dir path is Fail\n");
return;
}
char buffer[512];
char *ptr;
if (strlen(BaseDir) + 1 + DIRSIZ + 1 > sizeof(buffer))
{
printf("BaseDir is too Long!\n");
return;
}
strcpy(buffer, BaseDir);
ptr = buffer + strlen(buffer);
*ptr++ = '/';
while (read(dirfd, &dt, sizeof(dt)) == sizeof(dt))
{
if (dt.inum == 0)
{
continue;
}
if (!strcmp(dt.name, ".") || !strcmp(dt.name, ".."))
{
continue;
}
memmove(ptr, dt.name, DIRSIZ);
ptr[DIRSIZ] = 0;
if (stat(buffer, &st) < 0)
{
printf("Cannot Stat %s\n", buffer);
continue;
}
switch (st.type)
{
case T_FILE:
if (!strcmp(dt.name, FindDir))
{
printf("%s\n", buffer);
}
break;
case T_DIR:
find(buffer, FindDir);
break;
}
}
return;
}
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("The input parameter is incorrect!\n");
exit(1);
}
char *BaseDir = argv[1];
char *FindDir = argv[2];
find(BaseDir, FindDir);
exit(0);
}
xargs (moderate)
实现简易的xargs
工具从标准输入读入数据,将每一行当作参数,加入到传给 xargs
的程序名和参数后面作为额外参数,然后执行。
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[])
{
char inputBuf[32];
char charBuf[320];
char *charBufPointer = charBuf;
int charBufSize = 0;
char *commandToken[32];
int tokenSize = argc - 1;
int inputSize = -1;
for (int tokenIdx = 0; tokenIdx < tokenSize; tokenIdx++)
commandToken[tokenIdx] = argv[tokenIdx + 1];
while ((inputSize = read(0, inputBuf, sizeof(inputBuf))) > 0)
{
for (int i = 0; i < inputSize; i++)
{
char curChar = inputBuf[i];
if (curChar == '\n')
{
charBuf[charBufSize] = 0;
commandToken[tokenSize++] = charBufPointer;
commandToken[tokenSize] = 0;
if (fork() == 0)
{
exec(argv[1], commandToken);
}
wait(0);
tokenSize = argc - 1;
charBufSize = 0;
charBufPointer = charBuf;
}
else if (curChar == ' ')
{
charBuf[charBufSize++] = 0;
commandToken[tokenSize++] = charBufPointer;
charBufPointer = charBuf + charBufSize;
}
else
{
charBuf[charBufSize++] = curChar;
}
}
}
exit(0);
}