在 QNX 中使用 fork() 时如何确保 child 和 parent 进程具有不同的地址 space

How to ensure child and parent processes have different address space when using fork() in QNX

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

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

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

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

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

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

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

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

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

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

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

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

页面不一定位于 RAM(物理内存)中,但可以位于交换文件或分页文件中(使用的术语各不相同)直到需要为止。虚拟地址指的是一个页面 table,它知道它的页面实际所在的位置。当写时复制开始时,它意味着创建了一个新页面,这并不意味着虚拟地址发生了变化,它会保持不变,但在页面中 table 将引用不同的物理位置。

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