Читать «Разработка ядра Linux» онлайн - страница 30
Роберт Лав
Системные вызовы и обработчики исключительных ситуаций являются строго определенными интерфейсами ядра. Процесс может начать выполнение в пространстве ядра только посредством одного из этих интерфейсов — любые обращения к ядру возможны только через эти интерфейсы.
Дерево семейства процессов
В операционной системе Linux существует четкая иерархия процессов. Все процессы являются потомками процесса init
, значение идентификатора PID
для которого равно 1. Ядро запускает процесс init
на последнем шаге процедуры загрузки системы. Процесс init
, в свою очередь, читает системные файлы
Каждый процесс в системе имеет всего один порождающий процесс. Кроме того, каждый процесс может иметь один или более порожденных процессов. Процессы, которые порождены одним и тем же родительским процессом, называются task_struct
содержит указатель на структуру task_struct
родительского процесса, который называется parent, эта структура также имеет список порожденных процессов, который называется children
. Следовательно, если известен текущий процесс (current
), то для него можно определить дескриптор родительского процесса с помощью выражения:
struct task_struct *task = current->parent;
Аналогично можно выполнить цикл по процессам, порожденным от текущего процесса, с помощью кода:
struct task_struct *task;
struct list_head *list;
list_for_each(list, ¤t->children) {
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);
Получение указателя на предыдущее задание работает аналогично.