【问题标题】:How to ensure child and parent processes have different address space when using fork() in QNX在 QNX 中使用 fork() 时如何确保子进程和父进程具有不同的地址空间
【发布时间】:2018-10-26 12:07:20
【问题描述】:

这个问题是关于 QNX 的,并且在标题中已经说明了很多。 我在两个进程中修改变量地址后尝试记录变量地址,假设写时复制不再起作用并且它们不相同,所以我希望地址不同。但它们是相同的(虚拟地址,但仍然)。

那么如何在不打印变量值的情况下检查一个进程是否不会影响另一个进程,也许有更简单的解决方案?

int q;
q = 3;
...
if (pid == 0) {
    // in child
    q = 5;
    printf("%d\n", &q);
} else {
    // in parent
    q = 9;
    printf("%d\n", &q);
}

【问题讨论】:

  • @cdarke:绝对可以保证。 fork 从根本上要求(现有对象和函数的)虚拟地址在子节点中相同。否则所有指向它们的数据存储指针都将失效。
  • @R - 没错,我的意思是分叉之后的后续操作,例如如果两者都调用malloc 或加载共享对象。

标签: c fork qnx


【解决方案1】:

您打印的虚拟地址将是相同的——子进程几乎是其父进程的副本。一旦一个进程试图修改该页面中的数据,程序访问的物理地址就会分开,但这将对两个进程完全隐藏。这就是虚拟内存的美妙之处。

请注意,您使用了错误的格式来打印地址;您应该使用%p 并将地址转换为void *

printf("%p\n", (void *)&q);

或使用<inttypes.h>uintptr_tPRIXPTR(或PRIdPTR 是你真的想要十进制而不是十六进制的地址):

printf("0x%" PRIXPTR "\n", (uintptr_t)&q);

也打印数字 - 并在循环中执行多次,其中包含某种睡眠。您会看到,尽管逻辑(虚拟)地址相同,但物理地址却不同。但是,您将无法轻松找到物理地址。

【讨论】:

    【解决方案2】:

    如果你创建了一个新进程,而不是一个新线程,那么根据定义它有自己的进程地址空间。

    每个进程地址空间都将具有相同的虚拟地址范围 - 在 32 位机器上 0x00000000 - 0xffffffff。每个进程都有一个虚拟地址 n,它的用途以及它是否映射到任何物理存在的东西都会有所不同。其中一些地址空间将被内核使用,一些可能是共享的(另见man mmap)。

    fork() 之后,如果两个进程中的虚拟地址相同,您应该不会感到惊讶(尽管不能保证 fork 之后的新内存操作)- 这并不意味着写时复制是不起作用,这对普通代码是不可见的。

    页面不一定驻留在 RAM(物理内存)中,但可以放在交换或分页文件中(使用的术语不同)直到需要。虚拟地址是指一个页表,该页表知道其页的实际位置。当 copy-on-write 启动时,意味着创建了一个新页面,这并不意味着虚拟地址发生变化,它将保持不变,但在页表中将引用不同的物理位置。

    你为什么想知道呢?这种操作属于操作系统的范畴。

    【讨论】:

      猜你喜欢
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 2014-12-06
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      相关资源
      最近更新 更多