分叉过程中的确定性malloc
我想要的是让forked进程(它是其父进程的副本)获得从每个malloc函数调用返回的与其父进程相同的地址。我怎样才能做到这一点 实际上,我试图实现的是有两个复制的进程,它们执行相同的事情。我这样做基本上是为了检测软错误,也就是说,如果有任何分歧,它一定是由于错误,而不是非确定性。现在,由于malloc是不确定的,它将使两个过程分开,这是我想要避免的分叉过程中的确定性malloc,c,linux,gcc,x86-64,C,Linux,Gcc,X86 64,我想要的是让forked进程(它是其父进程的副本)获得从每个malloc函数调用返回的与其父进程相同的地址。我怎样才能做到这一点 实际上,我试图实现的是有两个复制的进程,它们执行相同的事情。我这样做基本上是为了检测软错误,也就是说,如果有任何分歧,它一定是由于错误,而不是非确定性。现在,由于malloc是不确定的,它将使两个过程分开,这是我想要避免的 如果不可能,我可以为父进程记录malloc返回的地址,并为分叉进程使用相同的地址。这行吗?您可能想使用。您不能让malloc返回相同的值,因为一旦
如果不可能,我可以为父进程记录malloc返回的地址,并为分叉进程使用相同的地址。这行吗?您可能想使用。您不能让malloc返回相同的值,因为一旦第一次调用执行,该内存就已分配,无法分配给另一个进程。使用
malloc
根本无法做到这一点。malloc
的返回地址未定义为以任何方式确定的(尤其是便携式的)。试图在进程之间同步,即使是孩子和家长,也可能是徒劳的
你能告诉我们你为什么要这样做的更多细节吗?也许还有另一种方法可以达到您想要的效果。如果您的系统是Linux,那么通过禁用地址空间随机化,您将获得更多可复制的地址。您可以使用此命令(以root用户身份运行)实现这一点 (但地址空间随机化是一项可以提高系统安全性的功能) 但是,这并不能保证父进程和子进程将获得相同的行为(因为它们之间有一个很小的区别:返回
fork()
和它们的pid)。你也不能确定他们的分配模式是否足够相似。想象一下,如果在fork之后(forked)程序执行如下操作
char *p = malloc (8192*(3 + (getpid() % 10) + time(NULL) % 100));
然后,您应该期望malloc在父级和子级中请求大不相同的大小,并使用不同的malloc返回地址。因此,这个虚构的例子表明您的需求是不现实的 您不能使用标准的
malloc
执行此操作。但您可以编写自己的自定义分配器,该分配器具有确定的分配方式。例如,作为分配池,使用足够大的静态字符池[pool_SIZE]
在fork()
中,池的地址保持不变。所有指向池的指针也都是。瞧 这是一个奇怪的要求;你介意分享哪种设计需要这个吗?你是在试图自己构建共享内存吗?实际上,我正在尝试实现冗余执行以检测软错误,也就是说,如果有任何分歧,应该是由于错误,而不是由于非确定性。我能想到的获取不同地址的唯一解释是ASLR。在内核级别关闭它,您可能会得到相同的地址。但是依赖这个似乎是一个非常糟糕的主意。现在我知道你在做什么了,我认为这在大多数情况下仍然是被误导的。通常,一个过程的两个分叉副本会因其他原因而出现分歧,例如具有不同的PID、获取独占资源的不同成功顺序(这可能反过来导致不同的malloc
模式)等。如果您的程序(几乎)纯粹是计算性的,这些差异可能无关紧要,但它看起来仍然非常脆弱,怎么会这样呢?不同的进程有完全独立的地址空间,用于各自独立的虚拟内存……嗯,地址空间是不同的,但动态获得的mallod指针可能具有相同的数值(但指向不同的空间)。@KerrekSB从字面意义上讲是非常正确的。我将OPs问题解释为想要指向相同的物理内存块,这显然是不正确的。我试图实现冗余执行,以便能够检测软错误,也就是说,如果有任何分歧,应该是由于错误,而不是由于非确定性。因此,我希望这两个进程,即父进程和它的副本(分叉进程)在没有错误的情况下以完全相同的方式执行。我不知道禁用ASR将如何使其工作。ASR影响虚拟地址空间布局(您显然知道),它是在fork()之后继承的。每个子级中的Malloc()只是在这个布局中分配堆上的空间,因此应该总是分散,或者至少可以这样做。也许我遗漏了什么。@gnometorule:虚拟地址布局与malloc
相关,因为malloc
使用虚拟内存。每个内存块(在Unix中)要么来自进程(brk
空间),要么来自mmap
块<代码>mmap
直接受ASLR影响。当然。但这如何适用于当前的问题?@gnometorule:对于大型分配,glibc
中的malloc()
使用mmap()
获取新的内存块,而不是在当前堆中分配空间。如果启用了ASLR,内核将为这个新的匿名映射提供一个随机地址,该地址反映在malloc()
返回的地址中。
char *p = malloc (8192*(3 + (getpid() % 10) + time(NULL) % 100));