C中线程的内存访问

时间:2018-07-20 13:32:42

标签: c posix

我在努力理解以下c程序的输出

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void) {
   int i = 1;   
   pid_t childId = fork();
   pid_t pid = getpid();

   if (childId == -1) {
    perror("fork() failed");
    } else if (childId == 0) {            
        printf("child PID: %d\n", pid);
        int *j = NULL;
        j = &i;
        (*j)++;            
        printf("value i in child: %d\t@adresse: %p\n",i ,&i);

    } else {
        pid_t pid = getpid();
        printf("parent PID: %d\nwait for child\n", pid);
        waitpid(childId, NULL, 0);          
        printf("value i in parent: %d\t@adresse: %p\n",i ,&i);          
    }
    return 0;
}

输出:

parent PID: 10656
wait for child
child PID: 10657
value i in child: 2 @address: 0x7fff93b720c0
value i in parent: 1    @address: 0x7fff93b720c0

子线程使存储在给定地址中的'i'递增。等待子级之后,父线程继续执行并在相同的地址但以初始值打印“ i”。这也不应该是2吗?

1 个答案:

答案 0 :(得分:1)

用户应用程序使用virtual memory。如果您使用fork(),则创建一个单独的进程,该进程使用与父进程具有相同地址的虚拟内存。

因此,两个进程都使用具有相同地址的虚拟地址空间(如您的printfs所示),但是它们可能在单独的物理内存上运行。

来自Wikipedia(重点是我的)的更详细的解释:

  

fork操作为孩子创建一个单独的地址空间。的   子进程具有所有内存段的精确副本   父进程。在跟随虚拟内存的现代UNIX变体中   在SunOS-4.0的模型中,实现了写时复制语义,并且   物理内存不需要实际复制。相反,虚拟内存   两个进程中的页面可能引用相同的物理内存页面   直到其中一个人写到这样的页面:然后将其复制。