使用管道实现素数生成器

Implementing prime number generator using pipes

提问人:user3280530 提问时间:11/13/2023 更新时间:11/13/2023 访问量:45

问:

我正在尝试使用此链接中所示的埃拉托色尼模型的筛子实现素数生成器

这个想法是创建传递一组数字的进程,每个进程消除第一个素数的倍数,并使用管道将结果传递给下一个进程。

到目前为止,我已经得到了

/* 
*  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 有很大帮助。在每个进程分叉后,它会等待子进程,从而创建一堆进程,所有进程都在等待其子进程。 避免等待还是仅在最初的第一个过程中等待更好?

在我完成阅读和写入后,我尝试关闭所有文件描述符,但不确定我是否错过了一些。 让管道文件描述符保持打开状态是否会导致内存泄漏,以及如何验证我是否在运行时将它们保持打开状态?

C Linux 操作系统

评论

1赞 kcm 11/13/2023
我只是好奇你写这种代码是为了什么?
1赞 user3280530 11/13/2023
正在尝试 xv6 的一些操作系统课程 pdos.csail.mit.edu/6.828/2023/labs/util.html
0赞 kcm 11/13/2023
哇。。它为我提供了磨练 C 技能的好资源......让我尝试调试您的代码

答: 暂无答案