Разработка ядра Linux | страница 35
>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;
>for_each_process(task) {
> /* просто печатается имя команды и идентификатор PID
> для каждой задачи */
> printk("%s[%d]\n", task->comm, task->pid);
>}
Следует заметить, что организация цикла по всем задачам системы, в которой выполняется много процессов, может быть достаточно дорогостоящей операцией. Для применения такого кода должны быть веские причины (и отсутствовать другие альтернативы).
Создание нового процесса
В операционной системе Unix создание процессов происходит уникальным образом. В большинстве операционных систем для создания процессов используется метод порождения процессов (spawn). При этом создается новый процесс в новом адресном пространстве, в которое считывается исполняемый файл, и после этого начинается исполнение процесса. В ОС Unix используется другой подход, а именно разбиение указанных выше операций на две функции: >fork()
и >exec()
[15].
В начале с помощью функции >fork()
создается порожденный процесс, который является копией текущего задания. Порожденный процесс отличается от родительского только значением идентификатора >PID
(который является уникальным в системе), значением параметра >PPID
(идентификатор >PID
родительского процесса, который устанавливается в значение >PID
порождающего процесса), некоторыми ресурсами, такими как ожидающие на обработку сигналы (которые не наследуются), а также статистикой использования ресурсов. Вторая функция —