【问题标题】:new process created using fork but printing same address for variables使用 fork 创建的新进程,但为变量打印相同的地址
【发布时间】:2016-12-11 19:06:33
【问题描述】:

我有以下代码:

#include<stdio.h>
#include<unistd.h>
int main()
{
    int a=0;
    printf("before: %d %p\n",a,&a);
    int t=fork();
    if(t==0)
    {
        a=a+5;
        printf("child: %d %p\n",a,&a);
    }
    else
    {
        a=a+10;
        printf("parent: %d %p\n",a,&a);
    }
    //printf("both: %d %p\n",a,&a);
    return 0;
}

为什么所有地址都打印相同?我认为调用 fork 时会创建变量的新副本。它与虚拟地址和物理地址有什么关系吗?如果是这样,相同的虚拟地址如何映射到不同的物理地址?

【问题讨论】:

    标签: c operating-system fork


    【解决方案1】:

    地址是相同的,因为每个process(父母和孩子)都有自己的自己的virtual address space。 Linux 计算机有virtual memory(由内核和处理器提供)。

    fork system call是“神奇”地将父进程的虚拟地址空间复制到子进程的虚拟地址空间中(fork的结果除外)。此复制使用惰性copy-on-write 技术,因此非常有效。内核正在管理MMU(用于虚拟内存和实现每个虚拟地址空间)

    阅读Advanced Linux Programming(它有几个与之相关的章节)并仔细阅读fork(2)

    顺便说一句,养成打电话给fflush(NULL);的习惯之前fork。见fflush(3)

    【讨论】:

    • 好的!谢谢。我实际上并没有得到如何将具有相同虚拟地址的两个进程映射到不同的物理地址。但我认为我应该先阅读更多内容,然后再提问。
    • 内核正在管理 MMU,所以同样可以配置它。
    【解决方案2】:

    因为 Unix 系统使用 虚拟 地址,而fork 会创建父进程的精确副本。这个确切的副本当然包括(初始)内存映射。

    【讨论】:

      【解决方案3】:

      因为这就是 fork 所做的。每the POSIX standard

      fork() 函数将创建一个新进程。 新工艺 (子进程)应是调用进程的精确副本(父进程) 过程),以下详述除外:

      • 子进程应具有唯一的进程 ID。

      • 子进程 ID 也不应与任何活动进程组 ID 匹配。

      • 子进程应该有一个不同的父进程ID,它应该是调用进程的进程ID。

      • 子进程应拥有自己的父文件描述符副本。每个孩子的文件描述符都应引用

        的对应文件描述符相同的打开文件描述 父母。

      • 子进程应拥有自己的父进程打开目录流的副本。子进程中每个打开的目录流
        可与对应的共享目录流定位
        父目录流。

      • 子进程应拥有自己的父消息目录描述符副本。

      • tms_utime、tms_stime、tms_cutime、tms_cstime的子进程值应设置为0。

      • 距离闹钟信号的剩余时间应重置为零,如果有闹钟,则应取消;看到警报。

      • [XSI] [选项开始] 所有 semadj 值应被清除。 [选项结束]

      • 父进程设置的文件锁不能被子进程继承。

      • 子进程的未决信号集应初始化为空集。

      • [XSI] [选项开始] 间隔计时器应在子进程中重置。 [选项结束]

      • 在父进程中打开的任何信号量也应在子进程中打开。

      • [ML] [选项开始] 子进程不应继承父进程通过调用建立的任何地址空间内存锁
        mlockall() 或 mlock()。 [选项结束]

      • 在父进程中创建的内存映射应保留在子进程中。从父级继承的 MAP_PRIVATE 映射应 也是孩子中的 MAP_PRIVATE 映射,以及对 父级在调用之前所做的这些映射中的数据 fork() 应该对孩子可见。对数据的任何修改 在 fork() 返回后由父级创建的 MAP_PRIVATE 映射中 应仅对父级可见。中数据的修改 子进程创建的 MAP_PRIVATE 映射仅对子进程可见 孩子。

        ....

      【讨论】:

        猜你喜欢
        • 2015-10-25
        • 1970-01-01
        • 2016-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-01
        相关资源
        最近更新 更多