6.S081-lab1

sleep

这个简单,随便写一下

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

int main(int argc, char** argv) {
if(argc != 2) {
fprintf(2, "invalid args!");
exit(1);
}
sleep(atoi(argv[1]));
exit(0);
}

pingpong

知识点:

  • fork调用之后返回两次,0表示子进程
  • fork复制调用时的状态,同时管道描述符类似于shared_ptr(个人理解)具有类似于引用计数的东西,被fork后 复制一份引用,计数+1, 计数归0时才会真正的被关闭
  • pipe产生的管道,是单工管道,p[1]写p[0]读
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
#include "kernel/types.h"
#include "user/user.h"

int main(int argc, char** argv) {
int p[2];
pipe(p);

int pid = fork();
if(pid == 0) {
char buf;
if(read(p[0], &buf, 1) == -1) {
exit(1);
}
fprintf(1, "%d: received ping\n", getpid());
write(p[1], &buf, 1);
close(p[0]);
close(p[1]);
exit(0);
}
char buf = 'a';
write(p[1], &buf, 1);
wait(0);
read(p[0], &buf, 1);
fprintf(1, "%d: received pong\n", getpid());
close(p[0]);
close(p[1]);
exit(0);
}

primes

埃氏筛法,递归处理,每个dfs函数处理父进程发送来的剩余数,用第一个数筛数据流后面的数,若处理完剩余有数则fork出子进程采用同样逻辑处理。
注意描述符数量有限,递归时需要及时关闭不用描述符

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

// 1写0读
void dfs(int fa[]) {
close(fa[1]);
int st;
int ret = read(fa[0], &st, 4);
if(ret != 4) {
exit(0);
}
fprintf(1, "prime %d\n", st);
int left[50];
int idx = 0, nxt;
while(read(fa[0], &nxt, 4) == 4) {
if(nxt % st > 0)
left[idx ++] = nxt;
}
if(idx > 0) {
int p[2];
pipe(p);
int pid = fork();
if(pid == 0) {
dfs(p);
exit(0);
}
close(p[0]);
for(int i = 0; i < idx; i ++) {
write(p[1], &left[i], 4);
}
close(p[1]);
wait(0);
}
close(fa[1]);
exit(0);
}

int main(int argc, char** argv) {
int n = 35;
if(argc > 2) {
fprintf(2, "invalid args!");
exit(1);
}
else if(argc == 2) {
n = atoi(argv[1]);
}
int p[2];
if(pipe(p) < 0) {
fprintf(1, "pipe failure!");
exit(1);
}
int pid = fork();
if(pid == 0) {
dfs(p);
exit(0);
}
close(p[0]);
for(int i = 2; i <= n; i ++) {
int ret = write(p[1], &i, 4);
if(ret < 0) {
fprintf(2, "cannot write!");
exit(1);
}
}
close(p[1]);
wait(0);
exit(0);
}

find

递归处理,若找到文件判断是否为目标文件,若是目录继续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
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"

void find(char* dirName, char* fileName) {
int fd;
struct dirent de;
struct stat st;

char buf[512];
memset(buf, 0, sizeof(buf));
memmove(buf, dirName, strlen(dirName));
char *buf_ptr = buf + strlen(dirName);
*buf_ptr++ = '/';
if((fd = open(dirName, 0)) < 0){
fprintf(2, "find: cannot open %s\n", dirName);
return;
}

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

while(read(fd, &de, sizeof(de)) == sizeof(de)) {
if(de.inum == 0) continue;
if(!strcmp(".", de.name) || !strcmp("..", de.name)) continue;
memmove(buf_ptr, de.name, DIRSIZ);
*(buf_ptr + DIRSIZ) = 0;
stat(buf, &st);
if(st.type == T_FILE) {
if(!strcmp(fileName, de.name)) {
fprintf(1, "%s\n", buf);
}
}
else if(st.type == T_DIR) {
find(buf, fileName);
}
}
return;
}

int main(int argc, char** argv) {
if(argc != 3) {
fprintf(2, "invalid args!");
exit(1);
}
char* dirName = argv[1];
char* fileName = argv[2];
find(dirName, fileName);
exit(0);
}

xargs

读取标准输入,然后将标准输入作为参数跟在原始命令和参数后面,通过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
#include "kernel/types.h"
#include "user/user.h"

int main(int argc, char **argv)
{
char* args[32];
int idx = 0;

for (int i = 1; i < argc; i++)
{
args[idx] = malloc(sizeof(argv[i]));
memcpy(args[idx++], argv[i], sizeof(argv[i]));
}
char buf, cur[128];
int pcur = 0;
while (read(0, &buf, 1) > 0)
{
if(buf == ' ' || buf == '\n') {
if(pcur > 0) {
args[idx] = malloc(pcur + 1);
memcpy(args[idx++], cur, pcur);
pcur = 0;
}
}
else
cur[pcur++] = buf;
}
exec(args[0], args);

exit(0);
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!