【问题标题】:C fork dealing with global variableC fork 处理全局变量
【发布时间】:2011-01-10 15:09:11
【问题描述】:

我不明白这个程序的输出:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int i = 0;

int main()
{
    while(i<3)
    {
        fork();

        printf("%d\n",i);
        ++i;
    }
}

输出是:

0
1
2
2
1
2
0
1
2
2
2
1
2
2

请有人告诉我应该如何解决这个问题,以便完全理解为什么我会得到这个输出?

【问题讨论】:

  • 您没有告诉我们您对此有何不满意。
  • 我不喜欢,因为我不明白我们何时在父进程或子进程中增加 fork。通常,如果我们想在子进程中递增,我们会执行 if(fork()==0)++i;但是当我们像这样分叉时,我在中间有点迷失了!
  • 根据答案:孩子增加孩子,父母增加父母,永远不会发生。

标签: c process global-variables fork


【解决方案1】:

Fork 会复制该进程。流程的独立副本。所以,如果一个全局变量在你 fork 的时候包含 3,那么进程的每个副本都会得到它们自己的 3。如果它们修改,它们的修改是完全独立的。

【讨论】:

    【解决方案2】:

    如果您想在进程内创建线程以进行并发编程,请尝试使用 pthreads。你要的函数是 pthread_create 和 pthread_join 供以后整理。

    类似这样的:

    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <malloc.h>
    
    
    int i = 0;
    
    void *threadFunc(void *arg) 
    {
        printf("%d\n",i);
    }
    
    int main()
    {
        int j = 0;  
        int returnValue = 0;
        pthread_t* myThread = (pthread_t*) calloc(3, sizeof(pthread_t));;
    
        while(i < 3)
        {
    
            returnValue = pthread_create(&myThread[i], NULL, threadFunc, NULL);
            printf("main thread: %d\n",i);
            i++;
    
        }
    
    
        for(j = 0; j < 3; j++)
        {
            pthread_join(myThread[j], NULL); 
    
        }
    
        return 0;
    }
    

    但也许不是,这取决于您的实际需求。

    【讨论】:

      【解决方案3】:

      当您 fork() 时,会在当前状态下创建当前进程的完整副本。这意味着您的初始进程将创建三个位于 while 循环中间的新进程,i 在每个进程中分别为 0、1 和 2。它还将打印他自己的值i

      它的每个子代将通过打印出其初始i 值、递增和循环来从fork() 调用继续循环。这意味着孩子 0 将打印 0、1 和 2,并产生两个新孩子,“初始”值为 i 1 和 2。孩子 1 将打印 1 和 2,并产生更多孩子,“初始”值为" i 的值为 2。孩子 2 将打印 2 并离开循环。

      如果你继续这个推理,你会得出这样的结论:总共会打印两个 0、四个 1 和八个 2。但是,由于执行顺序取决于操作系统如何调度并发进程,因此您无法保证这些进程的打印顺序。

      【讨论】:

        【解决方案4】:

        将您的代码更改为此,输出应该更有意义:

        #include <stdio.h>
        #include <sys/types.h>
        #include <unistd.h>
        
        int i = 0;
        
        int main()
        {
            while (i < 3)
            {
                fork();
                printf("pid = %d, i = %d\n", getpid(), i);
                ++i;
            }
            return 0;
        }
        

        【讨论】:

          【解决方案5】:

          有点像……

           1 (main) instance, i = 0(unforked)
           fork() > 2 instances, with i's = 0(forked), and 0(forked)
          0 output from main instance, increments its i, 2 instances with i = 1u, 0f
           main instance forks, there's 3 instances with i's 1f, 1f, 0f
          1 output from main instance, increments its i, 3 instances with i = 2u, 1f, 0f
           main instance forks, there's 4 instances with i's 2f, 2f, 1f, 0f
          2 output from main instance, increments its i, 4 instances with i = 3u, 2f, 1f, 0f
           main instance then dies, 3 instances with i = 2f, 1f, 0f
          2 output from next instance, increments its i, 3 instances with i = 3u, 1f, 0f
           next instance then dies, 2 instances with i = 1f, 0f
          1 output from next instance, increments its i to 2, 2 instances with i = 2u, 0f
          

          ...等

          但是,进程的输出顺序是不确定的,因此您可能不会每次都看到完全相同的输出,即使您这样做也无法保证。

          正如其他人所说,每个进程都有自己跟踪的全局“i”,它的值只是分叉进程在分叉处的 i 的值。

          【讨论】:

            猜你喜欢
            • 2018-06-15
            • 2020-04-19
            • 2023-03-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-22
            • 2015-06-12
            • 1970-01-01
            相关资源
            最近更新 更多