【问题标题】:Recursive Fibonacci using Fork in C (Pt 2)在 C 中使用 Fork 的递归斐波那契 (Pt 2)
【发布时间】:2012-03-07 21:26:43
【问题描述】:

我正在尝试编写一个函数,该函数使用 C 中的 forks 从给定的 int n 递归计算得到的斐波那契数。

这里是函数说明:如果doPrint为真,打印它。否则,将其提供给父进程。解决方案应该是递归的,并且它必须为每个调用派生一个新的孩子。每个进程都应该只调用一次 doFib()。方法签名不能更改。不能使用辅助函数。

这是这个问题的延续:Recursive Fibonacci using Fork (in C)

不幸的是,我在上一篇文章中从未找到解决问题的方法,但这是我修改后的代码。我以为我已经弄清楚了(伪代码明智),但后来发现我仍然不确定一些部分。

在这一点上,这只是我的娱乐。这不是家庭作业,我的课堂上不会再涉及(在最近的测试通过后)。

static pid_t root_pid;

// Function to return exit code for PID
static int exitcode(pid_t pid)
{
    pid_t retpid;
    int status;

    retpid = waitpid(pid, &status, 0);
    if (pid != retpid)
    {
        printf("waitpid error\n");
    }

    return WEXITSTATUS(status);
}

static void doFib(int n, int doPrint)
{
    root_pid = getpid();

    pid_t pid1;
    int status1;

    pid_t pid2;
    int status2;

    if(n < 2) // Base case, exit back to parent?
    {
        exit(n);
    }
    else // if not base case, fork child processes
    {
        pid1 = fork();
        if (pid1 == 0) // Child Process 1 (for fib(n-1))
        {
            doFib(n-1, doPrint);
            exit(n-1);
        } 
        else if (pid1 > 0) // Parent Process
        {
            pid2 = fork();
            if (pid2 == 0) // Child Process 2 (for fib(n-2))
            {
                doFib(n-2, doPrint);
                exit(n-2);
            }

            // Get value from child process 1
            status1 = exitcode(pid1);
            // Get value from child process 2
            status2 = exitcode(pid2);

            // When to print?
            if (getpid() == root_pid)
            {
                int result =  status1 +  status2;
                if (doPrint)
                {
                    printf("%d\n", result);
                }
                else
                {
                    exit(result);
                }
            }
        }
    }
}

几个问题...

  1. 我需要为每个子进程调用这两个函数吗?

    doFib(n-1, doPrint); exit(n-1);
    
  2. 我一开始的基本情况是否正确? (n
  3. 最后我的基本情况是否正确? (何时打印)

感谢您的帮助。

【问题讨论】:

  • 当你探索这个编码问题时,你应该考虑到斐波那契问题的递归解决方案是一种非常糟糕的方法来获得结果,因为它的效率非常低。
  • @Pointy 欣赏两美分。这是我为准备期中考试而完成的一系列编码问题,但我从来没有弄清楚这一点。至少可以说,这一直困扰着我,但我确信这主要是为了教育目的。

标签: c recursion fork fibonacci


【解决方案1】:

“何时打印”的答案实际上取决于您要打印的内容......如果您只想打印最终答案,那么您很可能需要一个标志来指示您何时处于根父进程,并使用if 语句测试您是否确实是根父进程,以便您只打印一个数字。另一方面,如果您想打印整个序列直到最后一个数字,则不需要if 语句。

例如,一个好的标志值是根进程的 PID。您可以将其保存在 main() 的前几行中名为 root_pid 的全局变量中,然后再开始分叉单独的子进程。这样,所有子进程都将为root_pid 设置相同的值,并且if 语句可以简单地为if (getpid() == root_pid)

所以做这样的事情:

//fib.c
#include <unistd.h>
pid_t root_pid

int main()
{
    root_pid = getpid();

    //... rest of your program

}

如上所述,在doFib 中创建if 声明如下:

if (getpid() == root_pid)
{
    //...print results
}
else
{
    exit(result)
}

【讨论】:

  • 最终答案是我需要打印的内容,而不是顺序。我曾认为我可能需要检测我是否是最终基本情况条件的根父级。您能否提供一些关于如何检测当前 pid 是否为 root/top 进程的代码示例?我用谷歌搜索无济于事。
  • 谢谢,这看起来是最终基本案例的一个很好的解决方案。非常感谢。现在希望有人能弄清楚其余的。 ;)
  • 顺便说一句,你的if 语句中的那些exit(n-1) 行是危险的,如果它们被调用会导致错误的结果。您需要确保在基本情况下调用第一个exit(n),或者您的代码调用exit(result) ...如果您想要正确的答案,它不能做任何其他事情。另一种选择是doFib 返回result 值,然后在doFib() 之后调用exit(result)。但是你不能从正确的递归退出点有一个单独的exit() 路径,而不会导致错误的结果。
  • 我明白了,感谢您的补充。每次我尝试将它们取出时都会导致无限循环,我认为这是因为我的基本情况不正确。现在,当我删除它们时,我遇到了几个“waitpid”错误。呵呵……
  • 那是因为您已将exit(result) 嵌入到另一个嵌套的if 语句中,因此如果进程不是根PID 则不会调用它...如果当前PID 不是根进程 PID。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 2019-01-21
  • 2014-04-02
  • 2021-04-05
  • 2016-07-01
相关资源
最近更新 更多