Эта статья относится к:
- Колонка Geek Time «Интересный разговор об операционной системе Linux» 12. Структура данных процесса (часть 1): если проектов слишком много, необходима система управления проектами.
- Chapter 3. Process Management- Shichao's Notes
- How to kill an individual thread under a process in linux?
Список основных понятий
- В Linux процессы и потоки называются задачами, когда они достигают ядра.
- Каждая задача имеет интерфейс данных
task_struct
, используемый для сохранения состояния задачи.
список заданий
Существует связанный список, содержащий все задачи в ядре Linux, соединяющий все структуры task_struct.
как показано на рисунке:
task_struct
определение структуры:
struct list_head tasks;
смотреть на каждыйtask_struct
Какие важные поля включены.
идентификатор задачи
Поля, связанные с идентификатором задачи, следующие:
pid_t pid;
pid_t tgid;
struct task_struct *group_leader;
Конкретные значения этих трех полей:
- pid : у каждой задачи есть уникальный pid, независимо от того, является ли это процессом или потоком.
- tgid: указывает на pid основного потока
- group_leader: указывает на основной поток процесса
Для любого процесса, если есть только основной поток, pid — это он сам, tgid — это он сам, а group_leader указывает на себя.
Но это меняется, если процесс создает другие потоки. Thread имеет свой собственный pid, tgid — это pid основного потока процесса, а group_leader указывает на основной поток процесса.
С помощью tgid мы можем определить, является ли задача потоком или процессом.
Так какой же смысл различать процессы и потоки? Рассмотрим следующие сценарии:
-
ps
Заказ
ps
Отображение по умолчанию представляет собой список всех процессов, а не всех потоков, что будет выглядеть очень беспорядочно и не сфокусировано.
- отправить в ветку
kill -9
Сигнал?
Предположим, мы отправляем сигнал выхода потоку в процессе (например,kill -9
), то мы должны выйти не просто из этого потока, а из всего процесса (см. ниже, почему). Таким образом, должен быть способ получить pid всех потоков в процессе, в котором находится этот поток.
Удаление потока из процесса — очень опасная операция.Например, поток выполняет работу по выделению памяти, в это время он будет удерживать блокировку распределителя памяти. Если вы принудительно убьете его, блокировка никогда не будет снята, а другие потоки остановятся. Следовательно, для корректного выхода из всех потоков требуется помощь основного процесса.
Картинка выше оттудаВопросы и ответы по этому поводу.
Если вы мне не верите, мы можем провести эксперимент.
На рисунке ниже показаноhtop
инструмент,белый для процесса,Зеленый означает нить. Вы можете видеть, что каждый поток имеет уникальный PID.
Теперь присвоим PID, отмеченным на рисунке, как21656
изcode-server
нить отправитьkill -9
сигнал и обнаружил, что весь процесс завершился:
На картинке вышеcode-server
Этот процесс контейнера докеров завершился минуту назад.
обработка сигнала
Адрес исходного кода:GitHub.com/Tor val all/Li…
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct *sighand;
sigset_t blocked;
sigset_t real_blocked;
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;
- заблокировано : заблокировано и пока не будет обрабатываться
- pending : ожидание обработки
- sighand : какой сигнал обрабатывается
Обратите внимание здесьstruct signal_struct *signal;
указал наsignal
структура. В этой структуре есть еще одинstruct sigpending pending;
. Как упоминалось ранее, необходимо различать потоки и процессы, и здесь также можно увидеть небольшую подсказку. Первый используется группой потоков, а другой предназначен для этой задачи.
статус задачи
Состояние задачи может принимать следующие значения:
/* Used in tsk->state: */
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4
#define __TASK_TRACED 8
/* Used in tsk->exit_state: */
#define EXIT_DEAD 16
#define EXIT_ZOMBIE 32
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
/* Used in tsk->state again: */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256
#define TASK_PARKED 512
#define TASK_NOLOAD 1024
#define TASK_NEW 2048
#define TASK_STATE_MAX 4096
В заключение
Мой официальный аккаунт: Полный стек не существует