克隆系统调用的参数存储在堆栈或其他地方?

时间:2018-03-04 04:09:22

标签: c linux memory-management stack clone

让我们简单地使用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()的手册页中,指定父和子两者都可以共享内存,父进程中的printf()应该打印10而不是50.但是它没有发生。为什么呢?

  • 当孩子的堆栈从顶部的stack_func开始,*arg(不是variable arg)存储在哪里?
  • 为什么子进程在修改arg的引用时会获得新副本?

2 个答案:

答案 0 :(得分:2)

您忘记使用标记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)一样。

答案 1 :(得分:2)

您需要设置CLONE_VM标志。来自the Linux man page

  

如果设置了CLONE_VM,则调用进程和子进程                 在相同的内存空间中运行。特别是,内存写入                 由调用进程或子进程执行的                 在其他过程中也可见。而且,任何记忆                 使用mmap(2)或munmap(2)执行映射或取消映射                 孩子或调用过程也会影响其他过程。

     

如果未设置CLONE_VM,子进程将单独运行                 当时调用进程的内存空间的副本                 克隆()。执行内存写入或文件映射/取消映射                 其中一个进程不会影响另一个进程,如同                 叉(2)。

clone(stack_func, malloc(1024*1024) + (1024*1024), CLONE_VM | SIGCHLD, &a);