sleep

注意👇这三个头文件的顺序不能修改,如果IDE有自动排序include的功能要关闭,否则通过不了编译

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"

int main(int argc, char const *argv[]) {
if (argc < 2) {
printf("Usage: need sleep seconds\n");
exit(1);
}
int time = atoi(argv[1]);
sleep(time);
exit(0);
}

pingpong

代码看起来比较多,其实核心比较少的,我加了很多close,这个文件里面可以不加,应该用不了几个文件描述符,但是下面那一题一定要加,否则过不了

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
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"

#define BUF_SIZE 1
int main(int argc, char const *argv[]) {
int p1[2], p2[2];
char buf[BUF_SIZE];
if (pipe(p1) < 0 || pipe(p2) < 0) {
fprintf(2, "pipe failed\n");
exit(1);
}
int pid = fork();
if (pid < 0) {
fprintf(2, "fork failed\n");
exit(1);
} else if (pid == 0) {
close(p1[1]);
close(p2[0]);
if (read(p1[0], buf, BUF_SIZE) < 0) {
fprintf(2, "read failed\n");
exit(1);
} else {
int pid = getpid();
printf("%d: received ping\n", pid);
}
if (write(p2[1], buf, BUF_SIZE) < 0) {
fprintf(2, "write failed\n");
exit(1);
}
close(p1[0]);
close(p2[1]);
} else {
close(p1[0]);
close(p2[1]);
if (write(p1[1], buf, BUF_SIZE) < 0) {
fprintf(2, "write failed\n");
exit(1);
}
if (read(p2[0], buf, BUF_SIZE) < 0) {
fprintf(2, "read failed\n");
exit(1);
} else {
int pid = getpid();
printf("%d: received pong\n", pid);
}
wait(0);
close(p1[1]);
close(p2[0]);
}
exit(0);
}

primes

这题需要了解什么是质数筛,作业里面给出了个链接,解释了一下,这里我也简单画个图解释下该题的处理流程。

image-20231014112948202

看懂了上面这个图,再看下面的代码就很清晰了

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
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"

void process(int left[2]) {
int num;
read(left[0], &num, sizeof(num));
if (num == -1) exit(0);
printf("prime %d\n", num);
int right[2];

if (pipe(right) < 0) {
printf("pipe failed\n");
exit(1);
}
if (fork() == 0) {
// 跟main函数做的一样
close(right[1]);
close(left[0]);
process(right);
close(right[0]);
exit(0);
} else {
close(right[0]);
int buf;
while (read(left[0], &buf, sizeof(buf)) && buf != -1) {
if (buf % num != 0)
write(right[1], &buf, sizeof(buf));
}
// 把-1传递给下一个进程
write(right[1], &buf, sizeof(buf));
close(right[1]);
close(left[0]);
wait(0); // 等待子进程处理完毕
exit(0);
}
}

int main(int argc, char const *argv[]) {
int p[2];
if (pipe(p) < 0) {
printf("pipe failed\n");
exit(1);
}
if (fork() == 0) {
// 子进程只读,因此关闭写
close(p[1]);
process(p);
exit(0);
} else {
// 父进场只写,关闭读
close(p[0]);
int i;
for (i = 2; i <= 35; i++) {
write(p[1], &i, sizeof(i));
}
i = -1;
// 哨兵标识处理完毕
write(p[1], &i, sizeof(i));
wait(0);
exit(0); // 等待子进程处理完毕
}
}

find

find主要注意不要处理”.”和”..”文件夹,否则会死循环下去,其他的就按照ls.c文件下面的写法

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
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"
#include "kernel/fs.h"
#include "kernel/fcntl.h"

void find(const char *path, const char *filename) {
int fd;
struct stat st;
struct dirent de;
char buf[512];
char *p;
if ((fd = open(path, O_RDONLY)) < 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_DEVICE:
case T_FILE:
if (strcmp(path + strlen(path) - strlen(filename), filename) == 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)
continue;
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if (stat(buf, &st) < 0) {
fprintf(2, "find: cannot stat %s\n", buf);
continue;
}
find(buf, filename);
}
break;
}
close(fd);
}
int main(int argc, char const *argv[]) {
if (argc != 3) {
fprintf(2, "usage: find <path> <filename>\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}

xargs

这部分可能不了解这个命令在linux有什么作用的人会不知所措,可以先去了解看看这个命令是干什么的,作业里面是比较简化的版本

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
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"

#define BUF_SIZE 512

int main(int argc, char* argv[]) {
// 检查命令行参数
if (argc < 2) {
fprintf(2, "Usage: xargs command\n");
exit(1);
}

// 将除第一个参数外的其他参数存储到一个数组中
char* args[MAXARG + 1];
int index = 0;
for (int i = 1; i < argc; ++i) {
args[index++] = argv[i];
}

// 从标准输入中读取一行行的文本
char buf[BUF_SIZE];
char* p = buf;
while (read(0, p, 1) == 1) {
if ((*p) == '\n') {
// 当读取到一行文本时,创建一个子进程
*p = 0;
int pid;
if ((pid = fork()) == 0) {
// 子进程
// 将该行文本作为参数传递给指定的命令
args[index] = buf;
// 执行指定的命令
exec(argv[1], args);
// 如果执行失败,则输出错误信息并退出子进程
fprintf(2, "exec %s failed\n", argv[1]);
exit(0);
}
// 父进程
// 等待子进程执行完毕
wait(0);
// 重置缓冲区指针,准备读取下一行文本
p = buf;
} else {
// 继续读取下一个字符
++p;
}
}
// 退出程序
exit(0);
}

最后要记住在主目录下面添加应该time.txt文件,然后写上一个整数,不然分数只有99

image-20231014113517139