提问人:user3280530 提问时间:11/13/2023 更新时间:11/13/2023 访问量:45
使用管道实现素数生成器
Implementing prime number generator using pipes
问:
我正在尝试使用此链接中所示的埃拉托色尼模型的筛子实现素数生成器
这个想法是创建传递一组数字的进程,每个进程消除第一个素数的倍数,并使用管道将结果传递给下一个进程。
到目前为止,我已经得到了
/*
* Program to print primes in [2,35]
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <error.h>
int main()
{
int pipefd[2];
int pipefd2[2];
int num;
bool toggle=false;
int rd_fd_n,wr_fd_n;
int rd_fd_p,wr_fd_p;
if(pipe(pipefd) == -1)
{
printf("pipe failed\n");
return 1;
}
if(fork()) /* Initiator process */
{
close(pipefd[0]); // close read fd
int i = 2;
while(i<=35)
{
if(write(pipefd[1],(void*)&i,4) == -1)
{
printf("write failed\n");
return 1;
}
i++;
}
close(pipefd[1]);
wait(0);
printf("parent exiting\n");
}
else
{
while(1)
{
if(!toggle)
{
rd_fd_p = pipefd[0]; // fd to read previous process
wr_fd_p = pipefd[1];
pipe(pipefd2);
wr_fd_n = pipefd2[1]; // fd to write to next process
rd_fd_n = pipefd2[0];
close(wr_fd_p); // important: close your copy of write fd when reading
}
else
{
rd_fd_p = pipefd2[0]; // fd to read previous process
wr_fd_p = pipefd2[1];
pipe(pipefd);
wr_fd_n = pipefd[1]; // fd to write to next process
rd_fd_n = pipefd[0];
close(wr_fd_p); // important: close your copy of write fd when reading
}
toggle = !toggle;
int ret = read(rd_fd_p,(void*)&num,4);
if( ret == 0) // read prime
{
close(rd_fd_p);
exit(0);
}
else if(ret == -1)
{
perror("read failed");
exit(1);
}
if(fork()) // pipe the numbers to next process
{
close(rd_fd_n); // close read fd to next process
int prime = num;
printf("prime %d\n",prime);
while(read(rd_fd_p,(void*)&num,4) != 0)
{
if(num % prime)
{
write(wr_fd_n,(void*)&num,4);
}
}
close(wr_fd_n);
wait(0);
exit(0);
}
}
}
}
一些令人担忧的事情是我遇到了一些叉子炸弹,但我识别并纠正了它。但是,即使存在终止条件,最好避免在 while(1) 循环中分叉的这种格式吗?
调试这种代码很困难,但 GDB 有很大帮助。在每个进程分叉后,它会等待子进程,从而创建一堆进程,所有进程都在等待其子进程。 避免等待还是仅在最初的第一个过程中等待更好?
在我完成阅读和写入后,我尝试关闭所有文件描述符,但不确定我是否错过了一些。 让管道文件描述符保持打开状态是否会导致内存泄漏,以及如何验证我是否在运行时将它们保持打开状态?
答: 暂无答案
评论