Перейти к содержимому

Что такое дескриптор процесса linux

  • автор:

Дескриптор процесса и структура task structure

Ядро хранит информацию о всех процессах в двухсвязном списке, который называется task list[10] (список задач). Каждый элемент этого списка является дескриптором процесса и имеет тип структуры struct task_struct, которая описана в файле include/linux/sched.h. Дескриптор процесса содержит всю информацию об определенном процессе.

Структура task_struct — достаточно большая структура данных размером порядка 1,7 Кбайт на 32-разрядной машине. Однако этот размер не такой уж большой, учитывая, что в данной структуре содержится вся информация о процессе, которая необходима ядру. Дескриптор процесса содержит данные, которые описывают выполняющуюся программу, — открытые файлы, адресное пространство процесса, ожидающие на обработку сигналы, состояние процесса и многое другое (рис. 3.1).

Рис. 3.1. Дескриптор процесса и список задач

Читайте также

Общий обзор средств безопасности: дескриптор безопасности

Общий обзор средств безопасности: дескриптор безопасности Анализ дескриптора безопасности предоставляет хорошую возможность для общего ознакомления с наиболее важными элементами системы безопасности Windows. В этом разделе речь будет идти о самых различных элементах

Дескриптор памяти

Дескриптор памяти Ядро представляет адресное пространство процесса в виде структуры данных, которая называется дескриптором памяти. Эта структура содержит всю информацию, которая относится к адресному пространству процесса. Дескриптор памяти представляется с помощью

Internet Engineering Task Force

Internet Engineering Task Force IETF (Internet Engineering Task Force — группа, отвечающая за решение сетевых инженерных задач) — это большое открытое международное сообщество сетевых разработчиков, операторов, производителей и исследователей, работающих в области развития архитектуры Интернета и

При каких условиях дескриптор становится готовым?

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

(1.10) Что такое Task Manager?

(1.10) Что такое Task Manager? Task Manager – это один из самых мощных и удобных инструментов в NT, предназначенных для управления процессами. Вызывается он либо Ctrl+Shift+Esc, либо выбором в меню, появляющимся после нажатия правой кнопкой на Taskbar-е. Можно его выбрать и после Ctrl+Alt+Del.Task manager

(3.18) Как задать пpиоpитет пpоцесса еще пpи его запyске? Чтоб не лазить постоянно для этого в task manager?

(3.18) Как задать пpиоpитет пpоцесса еще пpи его запyске? Чтоб не лазить постоянно для этого в task manager? Запуская с помощью консольной команды start можно запускать приложение с нужным приоритетом, указывать время, через которое приложение должно быть закрыто, и некоторые другие

(3.30) Как отключить (запретить) Task Manager?

(3.30) Как отключить (запретить) Task Manager? Для этого в реестре по адресу HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPoliciesSystem создайте ключ типа DWORD под названием DisableTaskMgr, и присвойте ему значение 1. Удалив этот ключ, или присвоив ему 0, вы вновь разрешите Task

Структура

Структура Первое, с чего следует начинать планирование, – это структура сайта. Структура главным образом определяется содержимым сайта и должна обеспечивать удобство доступа к нужной информации. Если неправильно выбрать структуру, то пользователь может очень быстро

Структура

Структура Одно из основных отличий хорошего резюме от плохого – это лаконичность. Работодатели – люди, как правило, занятые, а писем, подобных вашему, им предстоит прочесть не один десяток, и тратить свое время на изучение вашей подробной биографии они наверняка не будут.

1.9. Что такое Task Manager?

1.9. Что такое Task Manager? Task Manager — это один из самых мощных и удобных инструментов в NT, предназначенных для управления процессами. Вызывается он либо Ctrl+Shift+Esc, либо выбором в меню, появляющимся после нажатия правой кнопкой на Taskbar-е. Task manager в XP состоит из пяти закладок — Applications,

3.8. Как задать пpиоpитет процесса еще пpи его запyске, чтоб не лазить постоянно для этого в task manager?

3.8. Как задать пpиоpитет процесса еще пpи его запyске, чтоб не лазить постоянно для этого в task manager? Запуская с помощью консольной команды start можно запускать приложение с нужным приоритетом, указывать время, через которое приложение должно быть закрыто, и некоторые другие

8.1.1. Структура

8.1.1. Структура Это – структура, которой следуют все сценарии в этом руководстве. Если вы обнаружите, что это не так, то скорее всего это моя ошибка, если конечно я не объяснил, почему я нарушил эту структуру.1. Configuration – Прежде всего мы должны задать параметры конфигурации,

7.3.2. Концепции, касающиеся основных средств производственного процесса организации Основные средства производственного процесса организации (ППО)

7.3.2. Концепции, касающиеся основных средств производственного процесса организации Основные средства производственного процесса организации (ППО) Организация устанавливает и сопровождает набор основных средств производственного процесса, как показано на рис. 4.1. К

Структура

Структура Режим Структура используется при создании больших документов, насыщенных заголовками и подзаголовками (рис. 2.60). Для работы с этим режимом нужно, чтобы документ был отформатирован при помощи стилей (см. разд. 4.7), иначе этот режим в работе помочь не сможет. Рис.

Структура

Структура Так как вы имеете дело с отображением структурированных данных, необходимо определится с общим размещением. Обычно Joomla! использует структуру размещения элементов показанную ниже: Рис. 1: СтруктураСекция 1: Часть 1: Тут стоит разместить логотип или название

Тема3,4,5: процессы и потоки ос Linux

Основными активными сущностями в ос Linuxявляются процессы. Процессы в Linux — классические, последовательные процессы. Каждый процесс выполняет одну программу и изначально получает один поток управления. У процесса есть один счетчик команд, который отслеживает следующую исполняемую команду. Linuxпозволяет процессу создавать дополнительные потоки. Также Linux представляет собой многозадачную систему, так, что несколько независимых процессов могут работать одновременно. У каждого процесса в Linux есть пользовательская часть, в которой работает программа пользователя, однако, когдаодин из потоков делает системный вызов,то происходит эмулированное прерывание с переключением в режим ядра. После этого поток начинает работу в контексте ядрас другой картой памяти, своимстеком ядра, счетчиком команд в режиме ядра и полным доступом ко всем ресурсам машины. Ядро ОC Linux внутренним образом представляет процессы как задачи при помощи структуры задачtask_struct. Процесс с одним потоком представляется одной структурой задач, а многопоточный процесс будет иметь по одной структуре задачи для каждого из потоков пользовательского уровня. Само ядро является многопоточным и имеет потоки уровня ядра, которые не связаны ни с какими пользовательскими процессами и выполняют код ядра. Для каждого процесса в памяти находится его дескриптор типа task_struct. Он содержит важную информацию, необходимую ядру для управления всеми процессами. Дескриптор процесса создается при создании процесса. Для совместимости с другими системами unix процессы в Linux идентифицируются при помощи идентификатора процессаPID(ProcessIdentifier). Ядро организует все процессы в двунаправленный список структур задач. Информация в дескрипторе процесса подразделяется на следующие категории:

Параметры блокирования (приоритет процесса, израсходованное за последний учитываемый период времени, количество проведенного в режиме ожидания времени)

Образ памяти (указатели на сегмент текста, данных и стека) Когда процесса нет в памяти, то здесь так же хранится, как найти его части на диске.

Сигналы (маски, указывающие, какие сигналы перехватываются, какие временно заблокированы, и какие находятся в процессе доставки).

Машинные регистры. Когда происходит эмулированное прерывание в ядро, то машинные регистры сохраняются здесь

Состояние системного вызова (здесь хранится информация о текущем системном вызове)

Таблица дескрипторов файлов (Когда делается системный вызов, использующий дескриптор файла, то файловый дескриптор используется как индекс в этой таблице для обнаружения соответствующей этому файлу структуры данных).

Учетные данные (Указатель на таблицу, в которой отслеживается использованное процессом пользовательское и системное время процесса).

Стек ядра (фиксированный стек для использования той частью процесса, которая работает в режиме ядра)

Разное (текущее состояние процесса, ожидаемое процессом событие, PID процесса, идентификаторы родительского процесса, группы)

2*. Взаимодействие процессов

В системе Linux процессы могут общаться друг с другом с помощью следующих структур:

трубы (pipes) – создается канал между двумя процессами, в который один процесс может писать поток байтов, а другой процесс может его читать.

Сигналы (signals) – процессы общаются при помощи программных прерываний. Процессы могут сообщить системе, какие действия следует предпринимать, когда придет сигнал: проигнорировать сигнал, перехватить его, позволить сигналу убить процесс.

SIGABRT– посылается, чтобы прервать процесс и создать дамп памяти

SIGFPE – произошла ошибка при выполнении операции с плавающей точкой

SIGILL – пользователь нажал клавишу delete, чтобы прервать процесс

Процесс может посылать сигналы только членам своей группы, состоящих из его братьев, сестер и прочих потомков.

3*. Механизмы создания нового процесса. Системный вызов fork созпдает … называемого родительским процессом (parentprocess), новый процесс называется дочерним процессом (child process). У родительского и дочернего процесса есть свои собственные образы памяти. Если впоследствии, родительский процесс изменяет свои переменные, то эти изменения остаются невидимыми для дочернего процесса. Сразу после выполнения системного вызоваfork, значения всех соответствующих переменных в обоих процессах одинаковы, но после копирования всего адресного пространства родителя, последующие изменения в одном процессе не влияют на другой. Системный вызов fork возвращает дочернему процессу число 0, а родительскому – отличный от нуля PID дочернего процесса. Оба процесса проверяют возвращаемое значение и действуют соответственно. Открытые файлы используются родительскими и дочерними процессами совместно. Это значит, что, если какой-либо файл был открыт в родительском процессе, до выполнения системного вызоваfork, то он остается открытым в обоих процессах. Изменения, произведенные с этим файлом любым из процессов видны другому. Если дочерний процесс желает узнать свой идентификатор, то он может воспользоваться системным вызовом getpid. Например, когда дочерний процесс завершается, его родитель получает идентификатор только что завершившегося процесса.

Механизм создания процесса

Для дочернего процесса создается новый дескриптор и пользовательская область, которая заполняется из родительской. Дочерний процесс получает идентификатор, настраивается его карта памяти. Предоставляется доступ к общим файлам. Далее настраиваются регистры дочернего процесса, после чего он готов к запуску.

При вызове fork() происходит следующее:

Выделение структуры задач для потомка

Заполнение структуры задач потоком данными родителя

Выделение памяти для стека и области пользователя дочернего процесса

Заполнение области пользователя дочернего процесса

Выделение идентификатора для дочернего процесса

Настройка дочернего процесса на использование программы родительского процесса

Копирование таблицы страниц для данных и стека

Настройка совместного использования открытых файлов

Копирование регистров родительского процесса в дочерний процесс

При системном вызове exec() происходит следующее:

Поиск исполняемого файла

Проверка разрешения на выполнение

Чтение и проверка заголовка

Копирование аргументов, среды в ядро

Освобождение нового адресного пространства

Копирование аргументов среды в стек

Когда выполняется системный вызов fork(), вызывающий процесс выполняет эмулированное прерывание в ядро и создает структуру задачи. Большая часть содержимого дескриптора процесса заполняется значениями из дескриптора родителя, затем Linux ищет доступный идентификатор и обновляет элемент хэш-таблицы идентификаторов, чтобы там был указатель на новую структуру задачи. Далее система выделяет дочернему процессу его собственные таблицы страниц, но эти таблицы указывают на страницы родительского процесса, помеченного, как доступные только для чтения. Когда дочерний процесс пытается писать в такую страницу, происходит нарушение защиты. Ядро видит это и выделяет дочернему процессу новую копию этой страницы, которую помечает как доступную для чтения и для записи. Таким образом копируются только те страницы, в которые дочерний процесс пишет. Такой механизм называется копированием при записи. После того, как дочерний процесс начинает работу, его код делает системный вызов exec(), задавая имя команды в качестве параметра, при этом ядро находит и проверяет исполняемый файл, копирует в ядро аргументы и освобождает старое адресное пространство. Далее записывается новое адресное пространство. Сигналы сбрасываются, а все регистры устанавливаются в 0. После этого программа готова к работе.

4* Реализация потоков в ОС Linux

В 2000 году в Linux был введен новый системный вызов clone, который размыл отличия между процессами и потоками

Clone(function, stack_ptr, sharing-flags, arf);

Вызов cloneсоздает новый поток либо в новом процессе, либо в текущем, все зависит от флагаsharing-flags. Если новый поток находится в текущем процессе, то он совместно с существующими потоками использует адресное пространство и каждая запись в любой байт становится видна всем остальным потокам данного процесса. С другой стороны, если адресное пространство совместно не используется, то последующие записи новых потоков не будут видны старым. В обоих случаях новый поток начинает выполнение функции function с аргументом arg в качестве единственного параметра. Также в обоих случаях новый поток получает свой собственный стек, при этом указатель стека инициализируется параметром stack_ptr. Параметрsharing-flagsпредставляет собой битовый массив. Каждый бит может быть установлен независимо от остальных, и каждый из них определят, копирует ли новый поток эту структуру данных или использует ее совместно с вызывающим потоком.

CLOVE_VM 1 — создать новый поток, 0 – создать новый процесс. Если этот бит установлен, но новый поток добавляется к старым. Если этот бит сброшен, то новый поток получает свое собственное адресное пространство.

CLONE_FS 1 – совместно используется рабочий каталог root и флаг umask. 0 – не использовать их совместно. Даже если у нового потока есть адресное пространство, старый и новый потоки будут использовать совместно общие каталоги.

CLONE_PID 1 – поток получает старый идентификатор. 0 – поток получает свой собственный идентификатор. Это свойство нужно при загрузке системы. Процессам пользователя не разрешается использовать это свойство

CLONE_PARENT1 – новый поток имеет того же родителя, что и вызывающий, 0 – родителем нового потока является вызывающий.

CLONE_FILES 1 – используются общие дескрипторы файлов, если 0 – копируются

Чтобы сохранять совместимость с другим unix-системами, Linux разделяет структуры задач и процессы. Оба этих поля хранятся в структуре задач.

Understanding the Linux Kernel, Second Edition by

Get full access to Understanding the Linux Kernel, Second Edition and 60K+ other titles, with a free 10-day trial of O’Reilly.

There are also live events, courses curated by job role, and more.

Process Descriptor

To manage processes, the kernel must have a clear picture of what each process is doing. It must know, for instance, the process’s priority, whether it is running on a CPU or blocked on an event, what address space has been assigned to it, which files it is allowed to address, and so on. This is the role of the process descriptor — a task_struct type structure whose fields contain all the information related to a single process. As the repository of so much information, the process descriptor is rather complex. In addition to a large number of fields containing process attributes, the process descriptor contains several pointers to other data structures that, in turn, contain pointers to other structures. Figure 3-1 describes the Linux process descriptor schematically.

The Linux process descriptor

Figure 3-1. The Linux process descriptor

The five data structures on the right side of the figure refer to specific resources owned by the process. These resources are covered in future chapters. This chapter focuses on two types of fields that refer to the process state and to process parent/child relationships.

Process State

As its name implies, the state field of the process descriptor describes what is currently happening to the process. It consists of an array of flags, each of which describes a possible process state. In the current Linux version, these states are mutually exclusive, and hence .

Get Understanding the Linux Kernel, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Прочитайте онлайн Разработка ядра Linux | Дескриптор процесса и структура task structure

Читать книгу Разработка ядра Linux

Ядро хранит информацию о всех процессах в двухсвязном списке, который называется task list ( список задач ). Каждый элемент этого списка является дескриптором процесса и имеет тип структуры struct task_struct , которая описана в файле include/linux/sched.h . Дескриптор процесса содержит всю информацию об определенном процессе.

Структура task_struct — достаточно большая структура данных размером порядка 1,7 Кбайт на 32-разрядной машине. Однако этот размер не такой уж большой, учитывая, что в данной структуре содержится вся информация о процессе, которая необходима ядру. Дескриптор процесса содержит данные, которые описывают выполняющуюся программу, — открытые файлы, адресное пространство процесса, ожидающие на обработку сигналы, состояние процесса и многое другое (рис. 3.1).

Онлайн библиотека litra.info

Рис. 3.1. Дескриптор процесса и список задач

Выделение дескриптора процесса

Память для структуры task_struct выделяется с помощью подсистемы выделения памяти, которая называется слябовый распределитель ( slab allocator ), для возможности повторного использования объектов и раскрашивания кэша (cache coloring) (см. главу 11, «Управление памятью»). В ядрах до серии 2.6 структура task_struct хранилась в конце стека ядра каждого процесса. Это позволяет для аппаратных платформ, у которых достаточно мало регистров процессора (как, например, платформа x86), вычислять местоположение дескриптора процесса, только зная значение регистра указателя стека ( stack pointer ), без использования дополнительных регистров для хранения самого адреса этого местоположения. Так как теперь дескриптор процесса создается с помощью слябового распределителя, была введена новая структура thread_info , которая хранится в области дна стека (для платформ, у которых стек растет в сторону уменьшения значения адреса памяти) или в области вершины стека (для платформ, у которых стек растет в сторону увеличения значения адреса памяти) (рис. 3.2.).

Онлайн библиотека litra.info

Рис 3.2. Дескриптор процесса и стек ядра

Структура struct thread_info для платформы x86 определена в файле <asm/thread_info.h> в следующем виде.

struct task_struct *task;

struct exec_domain *exec_domain;

unsigned long flags;

unsigned long status;

struct restart_block restart_block;

unsigned long previous_esp;

Для каждой задачи ее структура thread_info хранится в конце стека ядра этой задачи. Элемент структуры thread_info с именем task является указателем на структуру task_struct этой задачи.

Хранение дескриптора процесса

Система идентифицирует процессы с помощью уникального значения, которое называется идентификатором процесса ( process identification , PID ). Идентификатор PID — это целое число, представленное с помощью скрытого типа pid_t , который обычно соответствует знаковому целому— int .

Однако, для обратной совместимости со старыми версиями ОС Unix и Linux максимальное значение этого параметра по умолчанию составляет всего лишь 32768 (что соответствует типу данных short int ). Ядро хранит значение данного параметра в поле pid дескриптора процесса.

Это максимальное значение является важным, потому что оно определяет максимальное количество процессов, которые одновременно могут существовать в системе. Хотя значения 32768 и достаточно для офисного компьютера, для больших серверов может потребоваться значительно больше процессов. Чем меньше это значение, тем скорее нумерация процессов будет начинаться сначала, что приводит к нарушению полезного свойства: больший номер процесса соответствует процессу, который запустился позже. Если есть желание нарушить в системе обратную совместимость со старыми приложениями, то администратор может увеличить это максимальное значение во время работы системы с помощью записи его в файл /proc/sys/kernel/pid_max .

Обычно в ядре на задачи ссылаются непосредственно с помощью указателя на их структуры task_struct . И действительно, большая часть кода ядра, работающего с процессами, работает прямо со структурами task_struct . Следовательно, очень полезной возможностью было бы быстро находить дескриптор процесса, который выполняется в данный момент, что и делается с помощью макроса current. Этот макрос должен быть отдельно реализован для всех поддерживаемых аппаратных платформ. Для одних платформ указатель на структуру task_struct процесса, выполняющегося в данный момент, хранится в регистре процессора, что обеспечивает более эффективный доступ. Для других платформ, у которых доступно меньше регистров процессора, чтобы зря не тратить регистры, используется тот факт, что структура thread_info хранится в стеке ядра. При этом вычисляется положение структуры thread_info , а вслед за этим и адрес структуры task_struct процесса.

Для платформы x86 значение параметра current вычисляется путем маскирования 13 младших бит указателя стека для получения адреса структуры thread_info . Это может быть сделано с помощью функции current_thread_info() . Соответствующий код на языке ассемблера показан ниже.

Окончательно значение параметра current получается путем разыменования значения поля task полученной структуры thread_info :

Для контраста можно сравнить такой подход с используемым на платформе PowerPC (современный процессор на основе RISC-архитектуры фирмы IBM), для которого значение переменной current хранится в регистре процессора r2 . На платформе PPC такой подход можно использовать, так как, в отличие от платформы x86, здесь регистры процессора доступны в изобилии. Так как доступ к дескриптору процесса — это очень частая и важная операция, разработчики ядра для платформы PPC сочли правильным пожертвовать одним регистром для этой цели.

Поле state дескриптора процесса описывает текущее состояние процесса (рис. 3.3). Каждый процесс в системе гарантированно находится в одном из пяти различных состояний.

Онлайн библиотека litra.info

Рис. 3.3. Диаграмма состояний процесса

Эти состояния представляются значением одного из пяти возможных флагов, описанных ниже.

TASK_RUNNING — процесс готов к выполнению (runnable). Иными словами, либо процесс выполняется в данный момент, либо находится в одной из очередей процессов, ожидающих на выполнение (эти очереди, runqueue , обсуждаются в главе 4. «Планирование выполнения процессов»).

TASK_INTERRUPTIBLE — процесс приостановлен (находится в состоянии ожидания, sleeping ), т.е. заблокирован в ожидании выполнения некоторого условия. Когда это условие выполнится, ядро переведет процесс в состояние TASK_RUNNING . Процесс также возобновляет выполнение (wake up) преждевременно при получении им сигнала.

TASK_UNINTERRUPTIBLE — аналогично TASK_INTERRUPTIBLE , за исключением того, что процесс не возобновляет выполнение при получении сигнала. Используется в случае, когда процесс должен ожидать беспрерывно или когда ожидается, что некоторое событие может возникать достаточно часто. Так как задача в этом состоянии не отвечает на сигналы, TASK_UNINTERRUPTIBLE используется менее часто, чем TASK_INTERRUPTIBLE .

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

TASK_STOPPED — выполнение процесса остановлено. Задача не выполняется и не имеет право выполняться. Такое может случиться, если задача получает какой-либо из сигналов SIGSTOP , SIGTSTP , SIGTTIN или SIGTTOU , а также если сигнал приходит в тот момент, когда процесс находится в состоянии отладки.

Манипулирование текущим состоянием процесса

Исполняемому коду ядра часто необходимо изменять состояние процесса. Наиболее предпочтительно для этого использовать функцию

set_task state(task, state);

/* установить задание ‘task’ в состояние ‘state’ */

которая устанавливает указанное состояние для указанной задачи. Если применимо, то эта функция также пытается применить барьер памяти ( memory barrier ), чтобы гарантировать доступность установленного состояния для всех процессоров (необходимо только для SMP-систем). В других случаях это эквивалентно выражению:

Вызов set_current_state(state) является синонимом к вызову set_task_state(current, state) .

Одна из наиболее важных частей процесса— это исполняемый программный код. Этот код считывается из выполняемого файла ( executable ) и выполняется в адресном пространстве процесса. Обычно выполнение программы осуществляется в пространстве пользователя . Когда программа выполняет системный вызов (см. главу 5, «Системные вызовы») или возникает исключительная ситуация, то программа входит в пространство ядра .

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

Системные вызовы и обработчики исключительных ситуаций являются строго определенными интерфейсами ядра. Процесс может начать выполнение в пространстве ядра только посредством одного из этих интерфейсов — любые обращения к ядру возможны только через эти интерфейсы.

Дерево семейства процессов

В операционной системе Linux существует четкая иерархия процессов. Все процессы являются потомками процесса init , значение идентификатора PID для которого равно 1. Ядро запускает процесс init на последнем шаге процедуры загрузки системы. Процесс init , в свою очередь, читает системные файлы сценариев начальной загрузки ( initscripts ) и выполняет другие программы, что в конце концов завершает процедуру загрузки системы.

Каждый процесс в системе имеет всего один порождающий процесс. Кроме того, каждый процесс может иметь один или более порожденных процессов. Процессы, которые порождены одним и тем же родительским процессом, называются родственными ( siblings ). Информация о взаимосвязи между процессами хранится в дескрипторе процесса. Каждая структура task_struct содержит указатель на структуру task_struct родительского процесса, который называется parent, эта структура также имеет список порожденных процессов, который называется children . Следовательно, если известен текущий процесс ( current ), то для него можно определить дескриптор родительского процесса с помощью выражения:

struct task_struct *task = current->parent;

Аналогично можно выполнить цикл по процессам, порожденным от текущего процесса, с помощью кода:

struct task_struct *task;

struct list_head *list;

task = list_entry(list, struct task_struct, sibling);

/* переменная task теперь указывает на один из процессов,

порожденных текущим процессом */

Дескриптор процесса init — это статически выделенная структура данных с именем init_task . Хороший пример использования связей между всеми процессами — это приведенный ниже код, который всегда выполняется успешно.

struct task_struct *task;

for (task = current; task != $init_task; task = task->parent)

/* переменная task теперь указывает на процесс init */

Конечно, проходя по иерархии процессов, можно перейти от одного процесса системы к другому. Иногда, однако, желательно выполнить цикл по всем процессам системы. Такая задача решается очень просто, так как список задач — это двухсвязный список. Для того чтобы получить указатель на следующее задание из этого списка, имея действительный указатель на дескриптор какого-либо процесса, можно использовать показанный ниже код:

list_entry(task->tasks.next, struct task_struct, tasks);

Получение указателя на предыдущее задание работает аналогично.

list_entry(task->tasks.prev, struct task_struct, tasks);

Дна указанных выше выражения доступны также в виде макросов next_task(task) (получить следующую задачу), prev_task(task) (получить предыдущую задачу). Наконец, макрос for_each_process(task) позволяет выполнить цикл по всему списку задач. На каждом шаге цикла переменная task указывает на следующую задачу из списка:

struct task_struct *task;

/* просто печатается имя команды и идентификатор PID

для каждой задачи */

Следует заметить, что организация цикла по всем задачам системы, в которой выполняется много процессов, может быть достаточно дорогостоящей операцией. Для применения такого кода должны быть веские причины (и отсутствовать другие альтернативы).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

https://alkogolizm.vyvod-iz-zapoya-v-stacionare-samara11.ru/