6.S081
xv6安装
# 依赖安装
sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf
参考链接: https://pdos.csail.mit.edu/6.S081/2021/tools.html
git clone git://g.csail.mit.edu/xv6-labs-2020
cd xv6-labs-2020
git checkout util
make qemu
Lab: Xv6 and Unix utilities
sleep
# include "kernel/types.h"
# include "user/user.h"
int
main(int argc, char *argv[]){
int time;
if(argc <= 1){
fprintf(2, "usage: sleep <time>\n");
exit(1);
}
time = atoi(argv[1]);
sleep(time);
exit(0);
}
pingpong
#include "kernel/types.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc >= 2){
fprintf(2, "Usage: pingpong\n");
exit(1);
}
int p1[2], p2[2];
pipe(p1); // parent to child
pipe(p2); // child to parent
if(fork() == 0){
// Child process
char buf[1];
close(p1[1]); // close write end of p1
close(p2[0]); // close read end of p2
// Receive byte from parent
read(p1[0], buf, 1);
close(p1[0]);
printf("%d: received ping\n", getpid());
// Send byte to parent
write(p2[1], buf, 1);
close(p2[1]);
exit(0);
} else {
// Parent process
char buf[1] = {'a'};
close(p1[0]); // close read end of p1
close(p2[1]); // close write end of p2
// Send byte to child
write(p1[1], buf, 1);
close(p1[1]);
// Receive byte from child
read(p2[0], buf, 1);
close(p2[0]);
printf("%d: received pong\n", getpid());
wait(0); // wait for child to exit
exit(0);
}
}
primes
#include "kernel/types.h"
#include "user/user.h"
void sieve(int p[2]) {
close(p[1]); // Close write end
int prime;
if (read(p[0], &prime, sizeof(prime)) <= 0) {
close(p[0]);
exit(0);
}
printf("prime %d\n", prime);
int next_p[2];
pipe(next_p);
if (fork() == 0) {
close(next_p[1]); // Close write end in child
sieve(next_p);
} else {
close(next_p[0]); // Close read end in parent
int num;
while (read(p[0], &num, sizeof(num)) > 0) {
if (num % prime != 0) {
write(next_p[1], &num, sizeof(num));
}
}
close(p[0]);
close(next_p[1]);
wait(0);
exit(0);
}
}
int
main() {
int p[2];
pipe(p);
if (fork() == 0) {
sieve(p);
} else {
close(p[0]); // Close read end in parent
for (int i = 2; i <= 35; i++) {
write(p[1], &i, sizeof(i));
}
close(p[1]);
wait(0);
exit(0);
}
exit(0);
}
find
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
void
find(char *path, char *filename){
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
fprintf(2, "find: cannot open %s\n", path);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", path);
close(fd);
return;
}
switch (st.type){
case T_FILE:
printf("find: the first argument must be a path\n");
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("find: path too long\n");
break;
}
strcpy(buf, path);
p = buf + strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){ // 从fd中读取固定大小数据块sizeof(de),获取目录项
if(de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
}
if(st.type == T_DIR)
find(buf, filename);
else{
if(strcmp(de.name, filename) == 0)
printf("%s\n", buf);
}
}
break;
default:
break;
}
close(fd);
}
int
main(int argc, char *argv[]){
if(argc < 2){
fprintf(2, "usage: find <path> <file name>\n");
exit(1);
}else if(argc == 2)
find(".", argv[1]);
else
find(argv[1], argv[2]);
exit(0);
}
xargs
将标准输入转化为命令参数
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"
int
main(int argc, char *argv[])
{
if(argc <= 1){
fprintf(2, "usage: xargs <command> [args...]\n");
exit(1);
}
char buf[512];
char *args[MAXARG];
int i;
// Copy original arguments
for(i = 1; i < argc; i++) {
args[i-1] = argv[i];
}
// Read from stdin character by character
char *p = buf;
while(read(0, p, 1) > 0) {
if(*p == '\n') {
// End of line - execute command
*p = '\0'; // Null terminate
// Add current argument
args[i-1] = buf;
args[i] = 0; // Null terminate args array
// Fork and exec
int pid = fork();
if(pid == 0) {
// Child
exec(args[0], args);
} else{
wait(0);
// Reset for next line
p = buf;
i = argc;
}
}else {
p++;
}
}
exit(0);
}