Lab1 Xv6 and Unix utilities
sleep
user/sleep.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc == 2){
sleep(atoi((const char*) argv[1])); // convert ascii to integer and use system call sleep
exit(0);
}
else{
fprintf(2, "Usage:sleep number...\n"); // put the error masssage to the file descriptor 2
exit(1); // terminate the process,
//status = 1: indicates failure, and reported to wait()
}
}
pingpong
user/pingpong.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int p1[2]; // parent -> child
int p2[2]; // child -> parent
char buffer[] = {'x'};
int length = sizeof(buffer);
if(argc != 1){
fprintf(2, "Usage: pingpong\n");
exit(1);
}
pipe(p1);
pipe(p2);
if(fork() == 0){ // child
close(p1[1]);
close(p2[0]);
if(read(p1[0], buffer, length) == 1){ // child receives the byte
printf("%d: received ping\n", getpid());
write(p2[1], buffer, length); // child sends the byte to child
close(p2[1]);
exit(0);
}
close(p2[1]);
exit(1);
}else{ // parent
close(p1[0]);
close(p2[1]);
write(p1[1], buffer, length); // parent sends a byte to the child
close(p1[1]);
wait((int *)0);
if(read(p2[0], buffer, length) == 1){ // parent receives the byte
printf("%d: received pong\n", getpid());
}
exit(0);
}
}
primes
user/primes.c
#include "kernel/types.h"
#include "user/user.h"
void
close_pipe(int *p) {
close(p[0]);
close(p[1]);
}
void
primes() {
int n, p, len;
int fd[2];
// read the frist number from previous prime
if ((len = read(0, &n, sizeof(int))) <= 0 || n <= 0) {
close(1);
exit(0);
}
// print first number to console
printf("prime %d\n", n);
pipe(fd);
if (fork() == 0) { // child process
close(0);
dup(fd[0]); // link the std i/o 0 to fd[0]
close_pipe(fd);
primes();
} else { // parent process
close(1);
dup(fd[1]); // link the std i/o 1 to fd[1]
close_pipe(fd);
while ((len = read(0, &p, sizeof(int))) > 0 && p > 0) { // read the number from the prime
if (p % n != 0) {
write(1, &p, sizeof(int)); // filter the number
}
}
close(1);
wait((int *)0);
}
exit(0);
}
int
main(void) {
int i;
int fd[2];
pipe(fd);
if (fork() == 0) { // child process
close(0);
dup(fd[0]); // link the std i/o 0 to the fd[0]
close_pipe(fd);
primes();
} else {
close(1);
dup(fd[1]); // link the std i/o 1 to the fd[1]
close_pipe(fd);
for (i = 2; i <= 35; i++) {
write(1, &i, sizeof(int));
}
close(1);
wait((int *)0);
}
exit(0);
}
find
user/find.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
char*
fmtname(char *path) // 将路径格式化为文件名
{
static char buf[DIRSIZ+1];
char *p;
// Find first character after last slash. 从字符串末尾开始遍历,直到遇到'/'或者到字符串的头部为止
for(p=path+strlen(path); p >= path && *p != '/'; p--) ;
p++;
// Return blank-padded name.
if(strlen(p) >= DIRSIZ) // 字符串太长了
return p;
memmove(buf, p, strlen(p)+1);
return buf;
}
void
find(char *path, char *file)
{
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: // 如果这是一个文件
if(strcmp(fmtname(path), file) == 0){
printf("%s\n", path);
}
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)){ // 从该路径读取出文件名或者目录名
if(de.inum == 0 || de.inum == 1)
continue;
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, DIRSIZ); // 在路径后面添加文件名or目录
p[DIRSIZ] = 0; // the end of string is '\0'
find(buf, file);
}
break;
default:
break;
}
close(fd);
}
int
main(int argc, char *argv[])
{
if(argc != 3){
fprintf(2, "Usage: find <path> <file>\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
xargs
user/xargs.c
#include "kernel/types.h"
#include "user/user.h"
#include "kernel/param.h"
int
main(int argc, char *argv[])
{
char *arguments[MAXARG];
char buff[255];
char *p = buff, *q = buff;
int i, offset;
if(argc <= 1){
fprintf(2, "Usage: xargc <command>...\n");
exit(1);
}
for(i = 1; i < argc; i++){ // get the command which is behind the "xargs"
arguments[i-1] = argv[i];
}
i = i - 1;
offset = i; // backup
while(read(0, p, 1)){
if(*p == '\n'){ // meet the '\n' and execute it with arguments
*p = '\0';
arguments[i] = q;
if(fork() == 0){
exec(arguments[0], arguments);
exit(0);
}else{
wait((int*)0);
p = buff;
q = p;
i = offset;
}
}else if(*p == ' ' || *p == '\t'){ // meet the ' ' or '\t', find an argument
*p = '\0';
arguments[i] = q;
i = i + 1;
p = p + 1;
q = p;
}else{
p = p + 1;
}
}
exit(0);
}
other
源代码:https://gitee.com/kiloGrand/xv6-lab/tree/util/user