Как использовать CLONE_SETTLS с CLONE_VM в Linux - PullRequest
3 голосов
/ 25 июня 2011

Я столкнулся со сценарием, в котором множественные вызовы glibc / syscall между двумя процессорами, один из которых был создан путем вызова clone () с CLONE_VM, в конечном итоге приведут к сбою моей программы.

На основе моихпонимая, что если я намереваюсь использовать CLONE_VM t, я должен также указать CLONE_SETTLS.

Может ли кто-нибудь дать мне пример того, как подготовить хранилище TLS для моего нового клона и как на самом деле выполнить вызов clone () с использованием CLONE_SETTLS

Ответы [ 2 ]

1 голос
/ 28 июня 2011

Возьмите следующее с крошкой соли, поскольку я только посмотрел на это «во время компиляции» (здесь нет деревянных мечей ).

Glibc / NPTL использует TLS для хранения большого количества потоков. TLS указывает на поток struct pthread pd (pd, вероятно, означает дескриптор pthread ), размещенный в локальном стеке потока на allocate_stack(), вызывается с __pthread_create_2_1().

В x86 первый член struct pthread - это void *tcb, что должно указывать на struct user_desc (его номер записи, вероятно, будет варьироваться в зависимости от архитектуры, а также, вероятно, также от версии ядра, glibc в моей системе используется 6 для внутреннего TLS). Это tcb передается в качестве аргумента do_clone().

Если вы посмотрите эти функции, вы увидите, что glibc хранит много информации о TLS: информацию о локальном стеке потока, есть ли у этой программы несколько потоков, список надежных мьютексов, подпрограмма запуска потока и его аргумент, Флаги атрибутов pthread, политика планирования, ...

Таким образом, если вам удастся получить реальную нить, это будет намного проще.

0 голосов
/ 30 марта 2013

Альтернативным подходом было бы сначала позвонить 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 если требуется больший контроль над атрибутами потоков (например, расположение в стеке).

...