【问题标题】:How to use CLONE_SETTLS with CLONE_VM on linux如何在 Linux 上使用 CLONE_SETTLS 和 CLONE_VM
【发布时间】:2011-09-22 12:14:46
【问题描述】:

我遇到过这样一种情况,即在两个处理器之间多次调用 glibc/syscalls,其中一个是通过使用 CLONE_VM 调用 clone() 创建的,最终会导致我的程序崩溃。

根据我的理解,如果我打算使用 CLONE_VM t,那么我还必须指定 CLONE_SETTLS。

谁能给我一个示例,说明如何为我的新克隆准备 TLS 存储以及如何使用 CLONE_SETTLS 实际执行 clone() 调用?

【问题讨论】:

  • CLONE_VM 不需要CLONE_SETTLSvfork() 使用 CLONE_VM 而不使用 CLONE_SETTLS
  • vfork 依赖其他进程不修改任何数据,理论上它应该立即调用 exec。 -- 在这种情况下,两个进程都将修改数据并进行 glibc/syscall。一切正常,直到他们同时进行一些需要 TLS 才能正常运行的调用。

标签: linux process clone


【解决方案1】:

对以下内容持保留态度,因为我只在“编译期间”查看过此内容(此处没有 wooden swords)。

Glibc/NPTL 使用 TLS 来存储大量线程状态。 TLS 指向每个线程 struct pthread pdpd 可能意味着 pthread 描述符),分配在线程本地堆栈中的 allocate_stack(),从 __pthread_create_2_1() 调用。

在 x86 中,struct pthread 的第一个成员是void *tcb,它应该指向一个struct user_desc(它的条目号可能会因架构而异,也可能因内核版本而异,我系统上的 glibc 使用 6 表示其内部 TLS)。这个tcb 作为参数传递给do_clone()

如果你查看这些函数,你会发现 glibc 存储了很多关于 TLS 的信息:关于线程本地堆栈的信息,这个程序是否有多个线程,健壮的互斥体列表,线程启动例程及其参数, pthread 属性标志、调度策略、...

总之,如果你能摆脱真正的 pthread 线程,那就简单多了。

【讨论】:

    【解决方案2】:

    另一种方法是先调用clone,然后再调用pthread_create。 这样您就可以使用线程库来获取正确的 TLS(位于线程堆栈上)。

    示例代码:

    int tmp_run(void *arg) {
        void *ret;
        pthread_t thread;
        // now call the wanted function
        pthread_create(&thread, NULL, run, arg);
        pthread_join(thread, &ret);
        return (long) ret;
    }
    
    int main(...) {
       ...
       int clone_pid = clone (tmp_run, stack, flags arg);
       ...
    }
    

    如果需要对线程属性进行更多控制(例如堆栈位置),请查看pthread_create

    【讨论】:

      猜你喜欢
      • 2016-01-09
      • 2016-08-28
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 2022-06-11
      • 2010-12-12
      • 2014-04-22
      • 1970-01-01
      相关资源
      最近更新 更多