0%

6.s081

Lab1

1 Sleep

首先判断sleep是否有参数,将argv[1]转换为int类型,使用系统调用sleep实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1 #include "kernel/types.h"
2 #include "kernel/stat.h"
3 #include "user/user.h"
4
5 int main(int argc, char* argv[]) {
6 if (argc != 2) {
7 fprintf(2, "usage: sleep 10");
8 exit(1);
9 }
10 int time = atoi(argv[1]);
11 sleep(time);
12
13 exit(0);
14
15 }

2 pingpong

建立两个管道,fd1, fd2,通过readwrite实现父进程和子进程之间的通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 1 #include "kernel/types.h"
2 #include "kernel/stat.h"
3 #include "user/user.h"
4
5 int main(int argc, char* argv[]) {
6 int fd1[2];
7 int fd2[2];
8 int ret1 = pipe(fd1);
9 int ret2 = pipe(fd2);
10 char buffer[] = {'a'};
11 if (ret1 == -1) {
12 fprintf(2, "pipe error");
13 exit(1);
14 }
15 if (ret2 == -1) {
16 fprintf(2, "pipe error");
17 exit(1);
18 }
19 int pid = fork();
20 if (pid == -1) {
21 fprintf(2, "fork error");
22 exit(1);
23 } else if (pid == 0) {
24 //child
25 read(fd1[0], buffer, 1);
26 printf("%d: received ping\n", getpid);
27 write(fd2[1], buffer, 1);
28 } else {
29 //parent
30 write(fd1[1], buffer, 1);
31 read(fd2[0], buffer, 1);
32 printf("%d: received pong\n", getpid);
33
34 }
35 exit(0);
36 }

3 primes

在main函数中的父进程中输入2~35,在main函数的子进程中递归调用filter函数

在filter函数中,首先读的一定是质数,直接输出,通过这个prime判断其他数是否读入到下一个进程中

每个父进程都要写wait,否则会超时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 1 #include "kernel/types.h"
2 #include "kernel/stat.h"
3 #include "user/user.h"
4
5 #define INT_LENGTH 4
6
7 void filter(int fd[2]) {
8 int prime;
9 read(fd[0], &prime, INT_LENGTH);
10 printf("prime %d\n", prime);
11 int num;
12 int flag;
13 flag = read(fd[0], &num, INT_LENGTH);
14 if (flag == 0) {
15 exit(0);
16 }
17 int new_fd[2];
18 int ret = pipe(new_fd);
19 if (ret == -1) {
20 fprintf(2, "pipe error");
21 exit(1);
22 }
23
24 int pid = fork();
25 if (pid == -1) {
26 fprintf(2, "fork error");
27 } else if (pid == 0) {
28 close(new_fd[1]);
29 filter(new_fd);
30 } else {
31 close(new_fd[0]);
32 if (num % prime != 0) {
33 write(new_fd[1], &num, INT_LENGTH);
34 }
35 while (read(fd[0], &num, INT_LENGTH) > 0) {
36 if (num % prime != 0) {
37 write(new_fd[1], &num, INT_LENGTH);
38 }
39 }
40 close(new_fd[1]);
41 close(fd[0]);
42 }
43 wait(0);
44
45
46 }
47
48 int main(int argc, char* argv[]) {
49 int fd[2];
50 int ret = pipe(fd);
51 if (ret == -1) {
52 fprintf(2, "pipe error");
53 }
54 int pid = fork();
55 if (pid == -1) {
56 fprintf(2, "fork error");
57 } else if (pid == 0) {
58 close(fd[1]);
59 filter(fd);
60 } else {
61 close(fd[0]);
62 for (int i = 2; i <= 35; ++i) {
63 write(fd[1], &i, INT_LENGTH);
64 }
65 close(fd[1]);
66 wait(0);
67 }
68 exit(0);
69 }

4 find

find用法:find current_path target

fmtname作用:根据当前路径返回最后一个/后的内容

通过st.type判断是文件还是目录

文件,与target进行比对,相同输出当前路径

目录,递归使用find,构造路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"

#define MAX_PATH 512

void find(char *curr_path, char *target);

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));
buf[strlen(p)] = 0;
return buf;
}

void find(char *curr_path, char *target) {
char buf[MAX_PATH], *p;
int fd;
struct dirent de;
struct stat st;

if ((fd = open(curr_path, 0)) < 0) {
fprintf(2, "find: cannot open %s\n", curr_path);
return;
}

if (fstat(fd, &st) < 0) {
fprintf(2, "find: cannot stat %s\n", curr_path);
close(fd);
return;
}

switch (st.type) {
case T_FILE: {
// Check if the current file matches the target filename
char *f_name = fmtname(curr_path);
if (strcmp(f_name, target) == 0)
printf("%s\n", curr_path);
close(fd);
break;
}

case T_DIR:
// Traverse each entry in the directory
memset(buf, 0, sizeof(buf));
int curr_path_len = strlen(curr_path);
memcpy(buf, curr_path, curr_path_len);
buf[curr_path_len] = '/';
p = buf + curr_path_len + 1;
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
if (de.inum == 0 || strcmp(de.name, ".") == 0 ||
strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
find(buf, target); // Recurse into subdirectories
}
close(fd);
break;
}
}

int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(2, "usage: find [directory] [target filename]\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}

5 xargs

xargs的用法:echo a | xargs echo b,输入 b a,将前一个命令的输出作为后一个命令的参数

注意:下面代码中argv[0]是xargs

使用fork和exec使得新的进程得到执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"

void xargs(char* argv[], char* args[]) {
int fd[2];
int ret = pipe(fd);
if (ret == -1) {
fprintf(2, "pipe error");
exit(1);
}

int pid = fork();
if(pid == -1) {
fprintf(2, "fork error");
} else if (pid == 0) {
//child
close(fd[0]);
close(fd[1]);
exec(argv[1], args);
exit(1);
} else {
wait(0);
}
}

int main(int argc, char* argv[]) {
if (argc < 3) {
fprintf(2, "usage error");
}

char buf[512];
char* args[MAXARG];
args[0] = argv[1];
// printf("argv[0]:%s\n", argv[0]);

while (1) {
gets(buf, 512);
if (buf[0] == '\0') {
break;
}
// printf("buf:%s\n", buf);

buf[strlen(buf) - 1] = '\0';

for (int i = 2; i < argc; i++) {
args[i - 1] = argv[i];
}

args[argc - 1] = buf;
args[argc] = 0;
/*
for (int i = 0; i < argc; i++) {
printf("args:%s\n", args[i]);
}
*/

xargs(argv, args);
}
exit(0);
}