Какие системные данные хранятся в стеке - PullRequest
2 голосов
/ 13 декабря 2011

Я пытаюсь понять, как распределение и выравнивание стека работает с pthreads в системе Linux x86_64 с gcc и какие данные система хранит в стеке. Я знаю, что вы можете настроить память стека, используя pthread_attr_setstack. Я сделал это в тестовой программе, которая выполняет следующие действия:

1) рекурсивно вызывает себя и обновляет неинициализированный массив, выделенный в стеке

2) выводит значение первого элемента массива, последнего элемента и rsp

Из этого я смог наблюдать, как увеличивается rsp (в моей тестовой программе я заметил, что некоторые из рекурсивных вызовов были встроены компилятором). Я также смог увидеть, что добавление памяти TLS (с переменными __thread) приводит к тому, что первое значение rsp будет ниже. Таким образом, похоже, что переменные TLS расположены в верхней части стека.

Однако я не уверен, что там еще. Мне кажется, что первая страница стека каким-то образом зарезервирована для системы, потому что ни одна из переменных стека, которые я выделяю, не попадает в эту область. Даже если я не использую переменные __thread, переменные, которые я создаю, не отображаются на первой странице (я установил стековую память так, чтобы она была выровнена по страницам).

Итак, мой вопрос: что еще, если вообще что-то есть, находится в стеке для pthread помимо данных TLS и переменных стека?

Ответы [ 2 ]

4 голосов
/ 13 декабря 2011

В Linux NPTL:

В самом верху стека находится TCB.Это также известно как struct pthread или pthread_t.Это немного странно из-за всех странных системных определений glibc, но в основном оно содержит такие вещи, как:

  • Заголовок TLS (эта часть не включает фактические значения TLS)
  • Различные флаги
  • Связанный список для отслеживания кэшированных стеков
  • TID (и флаг использования стека)
  • PID
  • Надежная информация отслеживания мьютекса
  • pthread_cleanup и информация об отмене стека
  • Состояние отмены
  • Еще больше флагов
  • Определенное количество слотов TLS, используемых pthread_setspecific - если вы превысите это числоостальные располагаются в куче
  • Различные блокировки
  • Информация отслеживания для pthread_join
  • Возвращаемое значение потока
  • Политики планирования (из потокаатрибуты)
  • Процедура запуска и аргумент потока
  • Данные отслеживания размера стека
  • и т. д. и т. д.

В основном инициализируется в pthread_create (__pthread_create_2_1 в nptl/pthread_create.c, если вы подписаны на источник eglibc), befили новый поток фактически начинает работать.

Ниже TCB статически размещены __thread переменные - или, по крайней мере, те, которые компоновщик мог идентифицировать во время запуска.Динамический компоновщик инициализирует поле l_tls_offset в карте компоновщика, чтобы сообщить коду NPTL, сколько места нужно зарезервировать.Обратите внимание, что библиотеки, загруженные после запуска программы, не будут частью этого - подробности смотрите в __thread ABI spec .

Ниже переменных __thread находится стек.Вершина этого стека - код start_thread(), так что все еще будут способы, прежде чем он фактически выполнит пользовательский код (но не намного дальше).

0 голосов
/ 13 декабря 2011

как распределение и выравнивание стека работает с pthreads в Linux x86_64

«Стеки» в подпотоках - это на самом деле просто блок памяти, обычно malloc'd (который может быть реализован внутренне путем создания анонимной области), хотя вы также можете использовать саму оригинальную область стека, если она остается действительной в течение срока службы нити, например

char foo[2<<20];
pthread_attr_t attr;
pthread_t tid;

pthread_attr_init(&attr);
pthread_attr_setstack(&attr, foo, sizeof(foo));
pthread_create(&tid, &attr, func, NULL);
pthread_join(tid, NULL);
...