这个问题是关于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);
}
答案 0 :(得分:3)
您打印的虚拟地址将是相同的-子进程几乎是其父进程的完全相同的副本。一旦一个进程试图修改该页面中的数据,程序访问的物理地址将是分开的,但是这两个进程将完全隐藏它们。那就是虚拟内存的美。
请注意,您使用错误的格式打印地址;您应该使用%p
并将地址强制转换为void *
:
printf("%p\n", (void *)&q);
或使用<inttypes.h>
和uintptr_t
和PRIXPTR
(或PRIdPTR
是您确实想要的地址是十进制而不是十六进制):
printf("0x%" PRIXPTR "\n", (uintptr_t)&q);
也打印数字-并循环进行几次,并进行某种形式的睡眠。您将看到,尽管逻辑(虚拟)地址相同,但物理地址却不同。但是,您将无法轻松找到物理地址。
答案 1 :(得分:2)
如果您创建的是新进程而不是新线程,那么根据定义,它具有自己的进程地址空间。
每个进程地址空间将具有相同的虚拟地址范围-在32位计算机上为0x00000000 - 0xffffffff
。每个进程的虚拟地址为 n ,它的用途以及是否映射到实际存在的任何事物都将有所不同。某些地址空间将由内核使用,某些地址空间可能会被共享(另请参见man mmap
)。
在fork()
之后,如果两个进程中的虚拟地址相同,则不要感到惊讶(尽管不能保证fork
之后的新内存操作)-这并不意味着复制- on-write不起作用,对于普通代码是看不见的。
页面不一定位于RAM(物理内存)中,而是可以位于交换文件或页面文件中(使用的术语有所不同),直到需要为止。虚拟地址是指一个页面表,该表知道其页面的实际位置。写入时启动复制意味着创建一个新页面,但这并不意味着虚拟地址会更改,它将保持不变,但在页面表中将指向不同的物理位置。
您为什么仍然想知道?这种操作属于操作系统领域。