正确分配堆栈以克隆线程

时间:2018-07-22 02:52:04

标签: linux memory-management linux-kernel pthreads glibc

所以我想创建一个没有CLONE_FILES flag的线程。我尝试直接调用克隆,但是有一些奇怪的问题。我认为这与不正确的内存分配有关。

#ifndef _GNU_SOURCE
    #define _GNU_SOURCE
#endif
#include <iostream>
#include <sys/mman.h>
#include <pthread.h>
#include <unistd.h>

const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_SYSVSEM
            | CLONE_SIGHAND | CLONE_THREAD
            | CLONE_SETTLS | CLONE_PARENT_SETTID
            | CLONE_CHILD_CLEARTID
            | 0);

static int cloneThread(void* arg)
{
    long arg2 = (long)arg + (long)arg;
    long* arg2_ptr = &arg2;
    return 0;
}

int main(int argc, char** argv)
{
    const int STACK_SIZE = 0x800000;
    void* stackaddr = malloc(STACK_SIZE);
    void* stacktop  = (char*)stackaddr + STACK_SIZE; // assuming stack going downwards

    clone(cloneThread, stacktop, clone_flags, (void*)1);
    sleep(1); // wait for cloneThread running before exit
}

正如您在这里看到的,我正在使用malloc进行堆栈分配。 lldb显示程序在cloneThread开头崩溃。但是,如果我删除long* arg2_ptr = &arg2;,程序将成功退出。

我还阅读了pthread_create.callocatestack.c的源代码。在strace中,我用以下内容替换了malloc

void* stackaddr = mmap(NULL, STACK_SIZE, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);
mprotect(stackaddr, STACK_SIZE, PROT_READ|PROT_WRITE);

但是它具有与使用malloc相同的行为。那么我应该如何使用克隆?

OS:Ubuntu 18.04 LTS,g ++ 7.3.0

1 个答案:

答案 0 :(得分:2)

提供CLONE_SETTLSCLONE_PARENT_SETTIDCLONE_CHILD_CLEARTID标志时,必须为{{提供newtlsptidctid参数1}}。

如果您想要的只是一个带有独立FD表的普通线程,只需使用clone()并调用pthread_create()作为新线程中的第一个操作即可。