Primes
知乎上有一篇解释素数筛的帖子。
、
配合这张图。意思进来一组数,第一个子进程把2的倍数全部去掉并打印2,剩余的输进第二个子进程,第二个子进程把3的倍数全部去掉并打印3,以此类推。
思路:
- 每个子进程的工作:读左边,输出第一个,筛选,筛选结果写入右边
- 管道管理上,每个子进程读完了就关fd[0],写完了就关df[1]。fd是左边的管道。df是该子进程与右边的管道。
- 每层递归,参数传什么? 每层的递归都传该子进程开辟的管道。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void primes(int left[]) {
int first;
int len = read(left[0], &first, sizeof(int));
if (len != 0) { // 如果从左侧管道能读到数
fprintf(1, "prime %d\n", first);
int right[2]; // 开辟与右侧的管道
pipe(right);
int num;
while (read(left[0], &num, sizeof(int))!= 0) { // 开始筛选,并将筛选结果输到右侧
if (num % first) {
write(right[1], &num, sizeof(int));
}
}
close(left[0]); // 读完左侧,关了左侧的读
close(right[1]); // 写完右侧,关了右侧的写
if (fork() == 0) { // 这里的fork在子进程也会执行,因此能递归创造子进程
primes(right);
}
else{ // 这里我一直困惑子进程做判断时胡不会执行fork(),结果是不会
close(right[0]); // 关闭右侧读
wait(0);
}
}
exit(0);
}
int main() {
int left[2];
pipe(left);
for (int i = 2; i <= 35; i++) { // 第一个管道,输入2~35
write(left[1], &i, sizeof(int));
}
close(left[1]);
if (fork() == 0) {
close(left[1]);
primes(left);
}
else{
close(left[0]);
wait(0);
}
exit(0);
}
过程犯错:
- 这里我很粗心的判断了(fork()>0),这个会造成致命错误,子进程运行到这里会执行一次fork()又生成一个孙子进程。这里应该放else
- close别急着放在外面,放到父或者子的执行语句里面去。防止理不清