在fork()之后,C中的char数组是否重复



我想知道在C中调用fork((后,char数组是否会重复。例如,在下面的例子中是输出:

The message in child is secret message
The message in parent is secret message

The message in child is secret message
The message in parent is empty message
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
char msg[50] = "empty message";
pid_t pid = fork();
if(pid > 0) {
wait(0);
printf("The message in parent is %sn", msg);
} else {
strcpy(msg, "secret message");
printf("The message in child is %sn", msg);
}
return 0;
}

我想用一个有趣的实验来回答你。这里有一个类似但更简单的代码版本:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int x = 10;
int *px = &x;
pid_t pid = fork();
if(pid > 0) {
wait(0);
printf("x in parent is %dn", *px);
} else {
*px = 20;
printf("x in child is %dn", *px);
}
return 0;
}

其中,我使用了一个由子进程修改的整数来简化程序集。如果我们编译并停在生成的程序集上(我用ARM编译器做的,我对它更熟悉(,我们可以看到值10保存在sp-16的堆栈上,而x的地址保存在sp-24

mov     w0, 10          // x = 10
str     w0, [sp, 16]    
add     x0, sp, 16      // px = &x
str     x0, [sp, 24]

在子分支中,我们通过从堆栈中检索地址并在该地址写入新值来修改x的值。

ldr     x0, [sp, 24]   // *px = 20;
mov     w1, 20
str     w1, [x0]
ldr     x0, [sp, 24]   // Load value of x and print it with message
ldr     w0, [x0]
mov     w1, w0
adrp    x0, .LC1
add     x0, x0, :lo12:.LC1
bl      printf

所以sp-24的值现在改变了,对吗?那么,当执行父代码时,如何可能:

ldr     x0, [sp, 24]  // Load value of x and print it with message
ldr     w0, [x0]
mov     w1, w0
adrp    x0, .LC0
add     x0, x0, :lo12:.LC0
bl      printf
b       .L3

我们从相同的地址加载,但我们仍然得到值10

x in child is 20
x in parent is 10

正如评论中指出的那样,答案是每个进程都有自己的地址空间。地址空间包含堆栈、堆、映射页等。然而,在fork上,地址空间完全相同,因此我们可以在这两种情况下从相同的地址加载x

最新更新