Как можно реализовать pthread_detach на Linux? - PullRequest
0 голосов
/ 19 июня 2020

pthread_detach отмечает поток, так что при его завершении его ресурсы автоматически освобождаются, не требуя от родительского потока вызова pthread_join. Как это сделать? В частности, с точки зрения Linux, есть два ресурса, которые меня особенно интересуют:

  1. В качестве детали реализации, я ожидаю, что если системный вызов wait не будет выполнен на завершенный поток, тогда поток станет зомбом ie. Я предполагаю, что решение этой проблемы библиотекой pthread не включает SIGCHLD, потому что (я думаю) оно по-прежнему работает независимо от того, какое действие, указанное программой, должно произойти при получении SIGCHLD.
  2. Потоки создается с помощью системного вызова clone. Вызывающий должен выделить память для использования в качестве области стека дочернего потока перед вызовом clone. В другом месте в Stack Overflow было рекомендовано, чтобы вызывающая сторона использовала mmap для выделения стека для дочернего элемента. Как можно отключить отображение стека после выхода из потока?

Мне кажется, что pthread_detach должен каким-то образом предоставлять решения обеих этих проблем, иначе программа, которая порождает и отключает множество потоков, в конечном итоге теряют возможность продолжать порождение новых потоков, даже если отсоединенные потоки, возможно, уже завершились.

1 Ответ

1 голос
/ 19 июня 2020

Библиотека pthreads (на Linux, NPTL) предоставляет оболочку для примитивов более низкого уровня, таких как clone(2). Когда поток создается с помощью pthread_create, функция, переданная в clone, является функцией-оболочкой. Эта функция выделяет стек и сохраняет эту информацию, а также любые другие метаданные в структуре, а затем вызывает предоставленную пользователем функцию запуска. Когда пользовательская функция запуска возвращается, происходит очистка. Наконец, внутренняя функция с именем __exit_thread вызывается для выполнения системного вызова для выхода из потока.

Когда такой поток отсоединяется, он все равно возвращается из предоставленной пользователем функции запуска и вызывает код очистки как раньше, за исключением того, что стек и метаданные освобождаются как часть этого, так как никто не ждет завершения этого потока. Обычно это обрабатывается pthread_join.

Если поток завершается или завершается без запуска, то очистка обрабатывается следующим вызовом pthread_create, который вызовет любые обработчики очистки, которые еще не запущены. .

Причина, по которой SIGCHLD не отправляется родительскому элементу и не требуется wait(2), заключается в том, что используется флаг CLONE_THREAD для clone(2). На странице руководства об этом флаге говорится следующее:

Новый поток, созданный с помощью CLONE_THREAD, имеет тот же родительский процесс, что и процесс, который вызвал клонирование (например, как CLONE_PARENT), так что вызовы getppid (2) вернуть одно и то же значение для всех потоков в группе потоков. Когда поток CLONE_THREAD завершается, поток, создавший его, не отправляет сигнал SIGCHLD (или другой сигнал завершения); также нельзя получить статус такого потока с помощью wait (2). (Говорят, что поток отсоединен.)

Как вы заметили, это необходимо для ожидаемой семантики POSIX.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...