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

问题描述 投票:0回答:2

让我们简单地使用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的引用时会获得新副本?
c linux memory-management stack clone
2个回答
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)一样。


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);
© www.soinside.com 2019 - 2024. All rights reserved.