Как работает POSIX Threads в Linux? - PullRequest
       3

Как работает POSIX Threads в Linux?

2 голосов
/ 14 сентября 2010

Я думал, что pthread использует клон для создания одного нового потока в Linux. Но если это так, все потоки должны иметь свои отдельные pid . В противном случае, если они имеют одинаковый pid , глобальные переменные в libc представляются общими. Однако, запустив следующую программу, я получил тот же pid , но другой адрес errno .

extern errno;
void*
f(void *arg)
{
    printf("%u,%p\n", getpid(), &errno);
    fflush(stdin);
    return NULL;
}

int
main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, f, NULL);
    printf("%u,%p\n", getpid(), &errno);
    fflush(stdin);
    pthread_join(tid, NULL);
    return 0;
}

Тогда почему?

Ответы [ 2 ]

4 голосов
/ 14 сентября 2010

Я не уверен, как именно используется clone () при вызове pthread_create (). Тем не менее, глядя на справочную страницу clone () , кажется, что есть флаг с именем CLONE_THREAD, который:

Если установлено значение CLONE_THREAD, дочерний элемент помещены в ту же группу потоков, что и вызывающий процесс. Сделать остаток обсуждения CLONE_THREAD подробнее читаемый, термин «нить» используется для ссылаются на процессы в потоке группа.

Группы тем были добавлены в Linux 2.4 для поддержки потоков POSIX Понятие набора потоков, которые разделяют один PID. Внутренне, это поделился PID - это так называемая группа потоков идентификатор (TGID) для потока группа. Начиная с Linux 2.4, звонки в getpid (2) возвращает TGID Вызывающий.

Затем мы поговорим о функции gettid () для получения уникального идентификатора отдельного потока в процессе. Изменение вашего кода:

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>

int errno;
void*
f(void *arg)
{
    printf("%u,%p, %u\n", getpid(), &errno, syscall(SYS_gettid));
    fflush(stdin);
    return NULL;
}

int
main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, f, NULL);
    printf("%u,%p, %u\n", getpid(), &errno, syscall(SYS_gettid));
    fflush(stdin);
    pthread_join(tid, NULL);
    return 0;
}

(убедитесь, что вы используете "-lpthread"!), Мы видим, что идентификатор отдельного потока действительно уникален, а pid остается прежним.

rascher@coltrane:~$ ./a.out 
4109,0x804a034, 4109
4109,0x804a034, 4110
3 голосов
/ 14 сентября 2010
  1. Глобальные переменные: ваша ошибка в том, что errno - это не глобальная переменная, а макрос, который расширяется до l-типа типа int. На практике он расширяется до (*__errno_location()) или аналогичного.
  2. getpid - это библиотечная функция, которая возвращает идентификатор процесса в смысле процесса POSIX, а не фиктивный Linux per- clone pid. В настоящее время Linux обладает минимальной функциональностью на уровне ядра, необходимой для обеспечения почти POSIX-совместимости в отношении потоков, но большая часть этого все еще зависит от отвратительных хаков на уровне libc пользовательского пространства.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...