在C中使用Fork的递归Fibonacci(Pt 2)

时间:2012-02-16 13:21:12

标签: c recursion fork fibonacci

我正在尝试编写一个函数,该函数使用C中的for来递归地计算给定int n中的结果fibonacci数。

以下是功能说明: 如果doPrint为true,请将其打印出来。否则,将其提供给父进程。解决方案应该是递归的,并且必须为每个调用分叉一个新的子节点。每个进程应该只调用一次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 <2)
  3. 我的基础案例最终是否正确? (何时打印)
  4. 感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

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

例如,一个好的标志值将是根进程的PID。在开始分离单独的子进程之前,可以在root_pid的前几行中将此保存在名为main()的全局变量中。这样,所有子进程都将为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

}

如上所述,请在if内添加doFib语句:

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