Ядро Linux 101: Структуры обработки данных

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

В заключение

Мой официальный аккаунт: Полный стек не существует