【问题标题】:clone system call's argument stores in stack or somewhere else?克隆系统调用的参数存储在堆栈或其他地方?
【发布时间】:2018-08-12 00:17:12
【问题描述】:

让我们来看看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的引用时会得到一个新的副本?

【问题讨论】:

    标签: c linux memory-management stack clone


    【解决方案1】:

    你忘记使用标志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,子进程运行在一个单独的 调用进程时的内存空间副本 克隆()。执行内存写入或文件映射/取消映射 通过其中一个过程不影响另一个,与 叉子(2)。

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

      【讨论】:

      • 仔细阅读克隆手册页,系统调用和 c 库函数略有不同。
      猜你喜欢
      • 2016-08-05
      • 2019-01-05
      • 1970-01-01
      • 2014-10-15
      • 2011-01-31
      • 2016-12-20
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多