让我们简单地使用clone(2)
int stack_func(void *arg)
{
*(int*)arg = 10;
return 0;
}
int main()
{
int a = 50;
clone(stack_func, malloc(1024*1024) + (1024*1024), SIGCHLD, &a);
sleep(2); //Just to be sure
printf("%d\n", a);
return 0;
}
从clone()
的man-page指定父和子被允许共享内存,父进程中的printf()
应该打印10而不是50.但它没有发生。为什么?
stack_func
开始,*arg
(不是variable arg
)存储在哪里?arg
的引用时会获得新副本?你忘记使用旗帜CLONE_VM
:
clone(stack_func, malloc(1024*1024) + (1024*1024), SIGCHLD | CLONE_VM, &a);
CLONE_VM(自Linux 2.0起)
如果设置了CLONE_VM,则调用进程和子进程在同一内存空间中运行。特别是,由调用进程或子进程执行的内存写入在另一个进程中也是可见的。此外,子进程或调用进程使用mmap(2)或munmap(2)执行的任何内存映射或取消映射也会影响其他进程。
如果未设置CLONE_VM,则子进程在
clone()
时在调用进程的内存空间的单独副本中运行。其中一个进程执行的内存写入或文件映射/取消映射不会影响另一个进程,就像fork(2)一样。
你需要设置CLONE_VM
标志。来自the Linux man page:
如果设置了CLONE_VM,则调用进程和子进程在同一内存空间中运行。特别是,由调用进程或子进程执行的内存写入在另一个进程中也是可见的。此外,子进程或调用进程使用mmap(2)或munmap(2)执行的任何内存映射或取消映射也会影响其他进程。
如果未设置CLONE_VM,则子进程在clone()时在调用进程的内存空间的单独副本中运行。其中一个进程执行的内存写入或文件映射/取消映射不会影响另一个进程,就像fork(2)一样。
clone(stack_func, malloc(1024*1024) + (1024*1024), CLONE_VM | SIGCHLD, &a);