【问题标题】:parent local variable acting as shared variable between three child父局部变量充当三个孩子之间的共享变量
【发布时间】:2014-06-17 12:10:34
【问题描述】:

在下面的程序中,父进程的局部变量如何成为三个子进程之间的共享变量。

int main()
{
    int turn = 0;
    int i;

    for (i = 0; i < 3; i++)
    {
        if (fork() == 0)
        {
            int me = i;
            while (turn != me)
                /*do nothing*/ ;

            // my turn
            printf("Process %d ran\n", me);
            turn++;
        }
    }

    return 0;
}

输出:

进程 0 运行

进程 1 运行

进程 2 运行

但根据我的说法,最后两个进程应该挂起,因为 turn 的值不应该改变它们。

如果我放了一个 exit(0);在转++之后,我立即返回到我的shell提示符,只有一行输出,即: 进程 0 运行

但其他两个进程仍然在后台运行,其他两个进程没有任何输出。

【问题讨论】:

  • 究竟是什么让您认为turn 被分享了?
  • 作为 turn = 0 的初始值,当 for 循环第二次进入时 me = 1 并且 turn 应该等于 0,因为我们已经在子进程中更改了它,而不是在父进程中,所以当第二次进入 for 循环的时间应该是 = 0 和 me = 1 因此 while(turn != me) ; //应该无限运行代码不应该低于这个
  • 您希望您的代码会创建多少个进程?
  • 应该是三个...我哪里弄错了请告诉。
  • 现在我知道将创建 6 个进程,因为如果我们在低级别看到循环结束只是一个分支语句,因此分叉的进程将跳回 for 循环创建这些额外的进程.

标签: c unix process fork


【解决方案1】:

发生了什么:

main process is 0.

process 0 calls fork. i = 0;
process 0 returns from fork = 1;
process 0 calls fork. i = 1;
process 0 returns from fork = 2;
process 0 calls fork. i = 2;
process 0 returns from fork = 3;
process 0 exists;

process 1 returns from fork. i = 0;
process 1 hits the while loop turn = 0, i = 0, me = 0, while loop exists;
process 1 calls printf.
process 1 increments turn, turn = 1;
process 1 goes back to the for loop;
process 1 calls fork, i = 1;
process 1 returns from fork = 4;
process 1 calls fork, i = 2;
process 1 returns from fork = 5;
process 1 exists;

process 2 returns from fork. i = 1;
process 2 hits the while loop turn = 0, i = 1, me = 0, while loop spins forever;

process 3 returns from fork, i = 2;
process 3 hits the while loop turn = 0, i = 2, me = 0, while loop spins forever;

process 4 (spawned from process 1) returns from fork, i = 1, turn = 1 (inherited from process 1).
process 4 hits the while loop turn = 1, i = 1, me = 1, while loop exits;
process 4 calls printf;
process 4 increments turn, turn = 2;
process 4 goes back to the for loop;
process 4 calls fork, i = 2, turn = 2;
process 4 returns from fork = 6;
process 4 exits;

process 5 (spawned from process 1) return from fork, i = 2, turn = 1 (inherited from process 1)
process 5 hits the while loop turn = 1, i = 2, me = 2, while loop spins forever;

process 6 (spawned from process 4) returns from fork i = 2, turn = 2 (inherited from process 4)
process 6 hits the while loop turn = 2, i = 2, me = 2, while loop exists;
process 6 calls printf;
process 6 drops out of the for loop
process 6 exits;

基本上,您需要记住,您将继续运行 for 循环的所有进程,而不仅仅是主进程。在那之后,弄清楚发生了什么并不难。您总共生成了 6 个进程,其中三个将具有正确的状态 i 和 turn。

【讨论】:

  • 因此,如果我们在一个循环中执行 fork,则分叉的进程也将运行该父循环,如果是,那么循环是从头开始还是从当前值继续。即是否会再次进行初始化。
  • 子进程将处于与父进程完全相同的状态(至少在这种情况下)。 for 循环将处于与父循环完全相同的状态。从执行fork调用的操作系统的角度来看,根本没有for循环,寄存器和内存中只有一堆值,而子进程中的寄存器和内存与父母(至少在这种情况下)。
【解决方案2】:

像这样重构你的代码:

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

int main()
{
    int turn = 0;
    int i;

    for (i = 0; i < 3; i++)
    {
        printf("forking i = %d, turn = %d\n", i, turn);

        if (fork() == 0)
        {
            int me = i;
            while (turn != me)
                /*do nothing*/ ;

            // my turn
            printf("Process %d ran\n", me);
            turn++;
        }
    }

    return 0;
}

这可能会让您感到震惊,但上面的 Art 重构非常清楚地表明您的代码将产生 6 个进程。在其中添加更多 printfs 应该可以让您了解真正发生的事情。

【讨论】:

  • 真的很震惊..我从没想过分叉的进程也会继续循环运行
【解决方案3】:

在 fork() 之前声明的变量是为子进程共享的。您可以通过打印 &turn in loop 来检查它。会一样的。

【讨论】:

  • 它将为所有人更新,因为他们没有“转”的副本,他们共享“转”的访问权限,您可以检查转的地址。通过这个命令codeprintf("%u",&turn);code 在循环中。
  • 我确定他们没有共享访问权限。
  • 我试过循环打印“转”的地址,还是一样。这是代码code #include #include int main() { int turn = 0;诠释我; for (i = 0; i code
  • 这个地址是在一个虚拟地址空间而不是实际的物理地址。例如,如果我们有两个盒子,一个命名为父节点,一个子节点。两个盒子都包含数字 1 到 10。所以在子盒子中我们也说数字 5,在父盒子中我们也有数字 5。数字相同但在不同的盒子中。与上述情况类似,地址相同,但在不同的进程地址空间中。
猜你喜欢
  • 2021-10-11
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-08-14
  • 1970-01-01
相关资源
最近更新 更多