mit6.s081 - lab1 Xv6 and Unix utilities

本文为本人完成6.s081 2021fall时的一些记录,仅作为备忘录使用。

代码仓库地址:代码

task 1: sleep

Implement the UNIX program sleep for xv6; your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your solution should be in the file user/sleep.c.

描述:实现一个提供sleep功能的unix程序。

解决思路:系统已经实现了sleep函数,直接调用即可。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int
main(int argc, char *argv[])
{
int ticks_num;

if(argc != 2){
fprintf(2, "Usage: sleep times\n");
exit(1);
}

ticks_num = atoi(argv[1]);
sleep(ticks_num);

exit(0);
}

task 2: pingpong

Write a program that uses UNIX system calls to ‘’ping-pong’’ a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print “ : received ping”, where is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print “ : received pong”, and exit. Your solution should be in the file user/pingpong.c.

描述:使用管道(pipe)实现ping-pong(即使用pipe实现父进程子进程之间的通信)

解决思路:fork + pipe + write/read即可,比较简单,要注意pipe会创建两个fd(读/写),fork后子进程会继承文件描述符。
一般而言:fd[0]用于读数据;fd[1]用于写数据;
代码:

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

int
main(int argc, char *argv[])
{
int p[2]; // read, write
char buf[2];
if(argc != 1){
fprintf(2, "Usage: pingpong\n");
exit(1);
}

pipe(p);
if (fork() == 0) { // child
read(p[0], buf, 1);
fprintf(1, "%d: received ping\n", getpid());
write(p[1], "c", 1);
exit(0);
} else { // father、
sleep(1);
write(p[1], "c", 1);
sleep(1);
read(p[0], buf, 1);
fprintf(1, "%d: received pong\n", getpid());
}

exit(0);
}

task 3: primes

Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, inventor of Unix pipes. The picture halfway down this page and the surrounding text explain how to do it. Your solution should be in the file user/primes.c.

描述:使用pipe实现素数筛。

sieve

解决思路:父进程产生2-35的数,然后子进程按以下算法进行筛选即可。

1
2
3
4
5
6
p = get a number from left neighbor
print p
loop:
n = get a number from left neighbor
if (p does not divide n)
send n to right neighbor

代码:(若BUFSIZE过大会panic,排查后发现是stack只有一页。。。)

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

#define MAX_SEQ 35
#define BUFSIZE 100

int getline(int fd, char *buf, int max)
{
int i, cc;
char c;

for (i = 0; i + 1 < max;)
{
cc = read(fd, &c, 1);
if (cc < 1)
{
return 0;
}
if (c == '\n' || c == '\r')
break;
buf[i++] = c;
}
buf[i] = '\0';
return i;
}

int getnum(char *buf, int *pos)
{
int num = 0, i = *pos;
while(buf[i] >= '0' && buf[i] <= '9') {
num = num * 10 + buf[i] - '0';
i++;
}
*pos = i - 1;
return num;
}

int primer(int read_fd)
{
char buf[BUFSIZE];
int len = getline(read_fd, buf, BUFSIZE);
// printf("%s\n", buf);
close(read_fd);

int pipe_fd[2];
pipe(pipe_fd);

int i = 0, first_print_flag = 1;
int is_have = 0;
int first_num = getnum(buf, &i), num_tmp;
printf("prime %d\n", first_num);
for (i = 0; i < len; ++i) {
if (buf[i] >= '0' && buf[i] <= '9') {
num_tmp = getnum(buf, &i);
if (num_tmp % first_num == 0) {
continue;
}
is_have = 1;
break;
}
}
if (is_have) {
if (fork() == 0) { // child
close(pipe_fd[1]);
primer(pipe_fd[0]);
exit(0);
} else {
close(pipe_fd[0]);
for (i = 0; i < len; ++i) {
if (buf[i] >= '0' && buf[i] <= '9') {
num_tmp = getnum(buf, &i);
if (num_tmp % first_num == 0) {
continue;
}
if (first_print_flag) {
fprintf(pipe_fd[1], "%d", num_tmp);
first_print_flag = 0;
} else {
fprintf(pipe_fd[1], " %d", num_tmp);
}
}
}
fprintf(pipe_fd[1], "\n", num_tmp);
close(pipe_fd[1]);
wait(0);
}
} else {
close(pipe_fd[0]);
close(pipe_fd[1]);
}
return 0;
}

int main(int argc, char *argv[])
{
int pipe_fd[2]; // read, write
if (argc != 1)
{
fprintf(2, "Usage: primes\n");
exit(1);
}

pipe(pipe_fd);
if (fork() == 0)
{ // child
close(pipe_fd[1]);
primer(pipe_fd[0]);
exit(0);
}
else
{ // father
close(pipe_fd[0]);
for (int i = 2; i <= MAX_SEQ; ++i)
{
fprintf(pipe_fd[1], "%d", i);
if (i != MAX_SEQ)
{
fprintf(pipe_fd[1], " ", i);
}
else
{
fprintf(pipe_fd[1], "\n", i);
}
}
close(pipe_fd[1]);
wait(0);
}

exit(0);
}

task 4: find

Write a simple version of the UNIX find program: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c.

描述:实现find。

解决思路:魔改ls即可,改成dfs实现。

代码:

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

char*
fmtname(char *path)
{
char *p;

// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;
return p;
}

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

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

switch(st.type){
case T_FILE:
if (strcmp(fmtname(path), target) == 0) {
printf("%s\n", path);
}
break;

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

strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';

// many records
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;

if (!strcmp(".", de.name) || !strcmp("..", de.name)) {
continue;
}

memmove(p, de.name, strlen(de.name));
p[strlen(de.name)] = 0;
find(buf, target);
}
close(fd);
break;
}
}

int
main(int argc, char *argv[])
{
if(argc != 3){
fprintf(2, "Usage: find path keyword\n");
exit(1);
}

find(argv[1], argv[2]);

exit(0);
}

task 5: xargs

Write a simple version of the UNIX xargs program: read lines from the standard input and run a command for each line, supplying the line as arguments to the command. Your solution should be in the file user/xargs.c.

描述:实现xargs。

解决思路:对每行进行处理,因此加上上面的getline函数然后搭配上fork和exec就行(和shell类似)。

代码:

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

#define MAX_LEN 512

int getline(char *buf, int max)
{
int i, cc;
char c;

for(i=0; i+1 < max; ){
cc = read(0, &c, 1);
if(cc < 1) {
return 0;
}
if(c == '\n' || c == '\r')
break;
buf[i++] = c;
}
buf[i] = '\0';
printf("str: %s\n", buf);
return 1;
}

int
main(int argc, char *argv[])
{
// echo hello too | xargs echo bye
char buffer[MAX_LEN];
char* argv_tmp[MAXARG];
// minus "xargs"
memcpy(argv_tmp, argv + 1, (argc - 1) * sizeof(char*));
while (getline(buffer, MAX_LEN))
{
if (fork() == 0) {
argv_tmp[argc - 1] = buffer;
exec(argv_tmp[0], argv_tmp);
exit(0);
} else {
wait(0);
}
}
exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值