+ All Categories
Home > Documents > Linux Kernel Processes

Linux Kernel Processes

Date post: 25-Dec-2014
Category:
Upload: eduard-antsupov
View: 696 times
Download: 6 times
Share this document with a friend
Description:
 
32
Управление процессами в Linux-ядре Обзор реализации
Transcript
Page 1: Linux Kernel Processes

Управление процессами в Linux-ядре

Обзор реализации

Page 2: Linux Kernel Processes
Page 3: Linux Kernel Processes

From: [email protected] (Линус Бенедикт Торвальдс)Newsgroups: comp.os.minixSubject: Маленький опрос о моей новой операционной системеMessage-ID:<[email protected]>Date: 25 Aug 91 20:57:08 GMTOrganization: Хельсинкский УниверситетПривет всем, кто использует миникс — Я делаю (бесплатную) операционную систему (всего лишь хобби, не будет большой и профессиональной как gnu) для клонов 386 (486) AT. Она ваялась с апреля, и скоро будет готова. Я хочу отзывов о том, что людям нравится/не нравится в миниксе, ибо моя система на неё похожа(такое же устройство файловой системы(по практическим соображениям) среди всего прочего).Я уже включил bash (1.08) и gcc (1.40), и похоже всё работает. Это значит, что что-то полезное появится через несколько месяцев, и я хотел бы узнать, чего люди хотят. Любые советы принимаются, но я не обещаю, что всё исполню :-)Линус ([email protected])PS. Да, у неё никакого миниксового кода, и многозадачная фс. Она НЕ переносима (применяет переключение задач 386-го, и т. п.), и скорее всего будет поддерживать только AT-винчестеры, так как это всё, что у меня есть :-(

Page 4: Linux Kernel Processes

Основные характеристики ядра Linux

● Реализовано на языке C ● Монолитно● Преемптивно ● Поддержка динамической загрузки модулей● Странично-сегментная организация памяти ● Поддержка симметричной многопроцессорной

обработки(SMP)● Возможность использования в качестве гипервизора● Открытая модель разработки(GNU GPL 2)

Page 5: Linux Kernel Processes

Процессы и потоки

● Процесс - это программа, т.е. объектный код, хранящийся на каком-либо носителе информации и находящийся в состоянии исполнения.

● Поток(thread) - объект, выполняющий определенные операции внутри процесса.

Page 6: Linux Kernel Processes

Дескриптор процесса

struct task_struct { /* ... */ volatile long state; /* Состояние процесса в текущий момент */ int prio; pid_t pid; /* Идентификатор процесса(уникален) */ struct task_struct *parent; unsigned int policy; /* ... */ };

struct thread_info { struct task_struct *task; struct exec_domain *exec_domain; unsigned long flags; unsigned long status; __u32 cpu; __s32 preempt_count; mm_segment_t addr_limit; struct restart_block restart_block; unsigned long previous_esp; __u8 supervisor_stack[0]; };

Page 7: Linux Kernel Processes
Page 8: Linux Kernel Processes

Состояния процесса● TASK_RUNNING: Процесс выполняется (использует процессор) или

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

● TASK_INTERRUPTIBLE: Процесс приостановлен до наступления определенного события. Это состояние может быть прервано сигналами. После получения сигнала или возобновления путем явного выполнения "пробуждающего" вызова процесс переходит в состояние TASK_RUNNING.

● TASK_UNINTERRUPTIBLE: Данное состояние аналогично TASK_INTERRUPTIBLE, с той лишь разницей, что в нем не происходит обработка сигналов. Прерывание процесса, находящегося в этом состоянии, может быть нежелательным, поскольку ожидание может быть частью некоторой важной задачи. При наступлении ожидаемого события процесс возобновляется путем явного выполнения "пробуждающего" вызова.

● TASK_STOPPED: Выполнение процесса остановлено, он не выполняется и не может начать выполняться. Процесс переходит в это состояние по получении таких сигналов, как SIGSTOP, SIGTSTP и т.д. Процесс сможет снова стать исполняемым после получения сигнала SIGCONT.

Page 9: Linux Kernel Processes

Состояния процесса

● EXIT_ZOMBIE: Процесс завершен. Он будет находиться в системе до момента получения родительским процессом статистической информации по его выполнению.

● EXIT_DEAD: Конечное состояние (соответствующее своему названию). Процесс переходит в это состояние при его удалении из системы после того, как родительский процесс получит всю статистическую информацию, выполнив системный вызов wait4() или waitpid().

Page 10: Linux Kernel Processes

TASK_KILLABLE - новое состояние процессаВ ядре Linux 2.6.25 появилось новое состояние приостановки процесса TASK_KILLABLE: если процесс приостановлен с приоритетом, допускающим прерывания, он ведет себя так, как если бы находился в состоянии TASK_UNINTERRUPTIBLE, но вдобавок имеет возможность обрабатывать фатальные сигналы

Page 11: Linux Kernel Processes
Page 12: Linux Kernel Processes

Создание процесса

Page 13: Linux Kernel Processes

Создание процесса● При создании потока ядра оно вызывает функцию kernel_thread (.

/linux/arch/i386/kernel/process.c), выполняющую предварительную работу и затем вызывающую do_fork.

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

● Функция do_fork начинает создание процесса с обращения к вызову alloc_pidmap, возвращающему новый PID. Затем do_fork проверяет, не находится ли родительский процесс в состоянии трассировки отладчиком. Если это так, то в параметре clone_flags функции do_fork устанавливается флаг CLONE_PTRACE. Далее функция do_fork вызывает функцию copy_process, передавая ей флаги, стек, регистры, дескриптор родительского процесса и ранее полученный новый PID.

● Функция copy_process создает новый процесс путем копирования родительского процесса. Она выполняет все необходимые действия кроме запуска процесса, который происходит позже. Сначала copy_process проверяет, допустимо ли сочетание флагов CLONE. Если это не так, она возвращает код ошибки EINVAL. Затем она запрашивает Модуль безопасности Linux (LSM), разрешено ли текущей задаче породить новую задачу.

Page 14: Linux Kernel Processes

Завершение процесса

Page 15: Linux Kernel Processes

Завершение процесса● Независимо от события, послужившего причиной завершения

процесса, эта работа выполняется вызовом функции ядра do_exit● Функция do_exit предназначена для удаления из системы всех

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

● Освобождение ресурсов, занятых процессом в течение его жизненного цикла, выполняется вызовами соответствующих функций, от exit_mm (освобождающей занятые страницы памяти) до exit_keys (удаляющей криптографические ключи потока, сеанса и процесса). Функция do_exit выполняет различные вспомогательные операции по завершению процесса и затем вызывает функцию exit_notify, рассылающую сигналы, оповещающие о завершении процесса (например, родительский процесс о завершении порожденного процесса).

Page 16: Linux Kernel Processes

Планирование процессов

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

● Многозадачные ОС бывают двух видов: системы с кооперативной(cooperative) многозадачностью и системы с вытесняющей(преемптивной) многозадачностью.

● Кооперативная многозадачность: процесс продолжает выполняться до тех пор, пока сам не примет решение о прекращении выполнения.

● Вытесняющая многозадачность: решение о том, когда один процесс должен прекратить, а другой возобновить его, принимает планировщик.

● Вытеснение(preemption) - принудительное замораживание выполняющегося процесса.

● Минусы кооперативной многозадачности: планировщик не может принимать глобальные решения относительно того, сколько процессы должны выполняться; процесс может монополизировать процесс на большее время, чем это необходимо пользователю; "зависший" процесс может привести к неработоспособности всей системы.

● В ядре Linux(начиная с версии 2.5) используется O(1)-планировщик(O(1)-scheduler)

Page 17: Linux Kernel Processes

Планирование процессов

● Стратегия(policy) планирования - это характеристики поведения планировщика, которые определяют, что когда должно выполняться. Стратегия планирования определеяет глобальный характер поведения системы и отвечает за оптимальное использование процессорного времени.

● Процессы можно поделить на те, которые ограничены скоростью ввода-вывода(I/O-bound), и те, которые ограничены скоростью процессора(processor-bound).

● Стратегия планирования ОС должна стремиться к удовлетворению двух несовместных условий: обеспечение высокой скорости реакции процессов(low latency) и высокой производительности(throughput)

● Управление по приоритетам(priority-based) - процессы распологаются по порядку в соответствии с их важностью и необходимостью использования процессорного времени.

Page 18: Linux Kernel Processes

Планирование процессов

● В ОС Linux используется планировщик с динамическим распределением по приоритетам(dynamic priority-based)

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

● Любое большое значение кванта приводит к ухудшению интерактивной производительности.

● Процессы, ограниченные скоростью процессора, требуют продолжительного кванта времени, например, чтобы поддерживать кэши процессора в загруженном состоянии.

Page 19: Linux Kernel Processes

Планирование процессов

Page 20: Linux Kernel Processes

Планирование процессов● Планировщик версии 2.6 спроектирован и разработан Инго

Молнаром. Инго участвует в разработке ядра Linux с 1995 г. Он задался целью создать новый планировщик исключительно на основе алгоритмов сложности O(1) для пробуждения процессов, переключения контекстов и обработки прерывания таймера. Одной из причин возникновения потребности в новом планировщике были виртуальные машины Java™ (JVM). Модель программирования этого языка активно использует потоки, что приводит к росту накладных расходов при использовании планировщика с алгоритмом О(n). Планировщик с алгоритмом O(1) не имеет данного недостатка, поскольку его производительность не ухудшается при высокой нагрузке. Это позволяет обеспечить эффективную работу виртуальных машин Java™.

Page 21: Linux Kernel Processes

Планирование процессов

● Каждый ЦП имеет очередь задач, состоящую из 140 списков, обслуживаемых в порядке FIFO и содержащих задачи, имеющие соответствующий приоритет.

● Задачи, запланированные к выполнению, добавляются в конец списка.

● Каждой задаче выделяется отрезок времени, определяющий продолжительность ее выполнения. Первые 100 списков очереди задач зарезервированы для задач реального времени, а последние 40 - для пользовательских задач.

Page 22: Linux Kernel Processes

Планирование процессов

Page 23: Linux Kernel Processes

Планирование процессов

● Помимо очереди задач ЦП, называемой активной очередью задач, существует еще неактивная очередь. После того, как задача, находящаяся в активной очереди, исчерпывает отведенный ей отрезок времени, она переносится в неактивную очередь. При переносе происходит пересчет ее отрезка времени (также пересчитывается ее приоритет). Если в активной очереди отсутствуют задачи с данным приоритетом, соответствующие указатели активной и неактивной очередей меняются местами; при этом неактивный список становится активным.

Page 24: Linux Kernel Processes

struct runqueue { spinlock_t lock; unsigned long nr_rinning; /* количество задач, готовых к выполнению */ unsigned long nr_switches; /* количество переключений контекста */ unsigned long expired timestamp; /* время последнего обмена массивами*/ unsigned long nr_uninterruptible; /* количество заданий в состоянии непрерываемого ожидания */ unsigned long long timestamp last tick; /* последняя метка времени планировщика */ struct task_struct *curr; /* текущее задание, выполняемое на данном процессоре */ struct task_struct *idle; /* холостая задача данного процессора */ struct mm_struct *prev_mm; /* поле mm_struct последнего выполняемого задания */ struct prio_array *active; /* указатель на активный массив приоритетов*/ struct prio_array *expired; /* указатель на истекший массив приоритетов*/ struct prio_array arrays[2]; /* массивы приоритетов */ struct task_3truct *migration_thread; /* миграционный поток для данного процессора */ struct list_head migration_queue; /* миграционная очередь для данного процессора */ atomic_t nr_iowait; /* количество заданий, ожидающих на ввод-вывод */};

Page 25: Linux Kernel Processes

Очередь выполнения(runqueue)

● Очередь выполнения - это основная структура данных планировщика, которая представляет собой список готовых к выполнению процессов для данного процессора.

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

Page 26: Linux Kernel Processes

Пересчет квантов времени

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

Код: for (каждого задания в системе) ( пересчитать значение приоритета пересчитать значение кванта времени}

Page 27: Linux Kernel Processes

Пересчет квантов времениНедостатки:

● Пересчет потенциально может занять много времени. Хуже того, время такого расчета масштабируется как О(n), где n — количество задач в системе.

● Во время пересчета должен быть использован какой-нибудь тип блокировки для защиты списка задач и отдельных дескрипторов процессов. В результатеполучается высокий уровень конфликтов при захвате блокировок.

Page 28: Linux Kernel Processes

Пересчет квантов времени(решение)● Новый планировщик ОС Linux позволяет избежать

использования цикла пересчета приоритетов. Вместо этого в нем применяется два массива приоритетов длякаждого процессора: активный (active) и истекший (expired)

● После того, как задача, находящаяся в активной очереди, исчерпывает отведенный ей отрезок времени, она переносится в неактивную очередь. При переносе происходит пересчет ее отрезка времени (также пересчитывается ее приоритет). Если в активной очереди отсутствуют задачи с данным приоритетом, соответствующие указатели активной и неактивной очередей меняются местами; при этом неактивный список становится активным.

Page 29: Linux Kernel Processes

Пересчет квантов времени

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

Код: struct prio_array array = rq->active; if (!array->nr_active) { rq->active = rq->expired; rq->expired = array;}

Page 30: Linux Kernel Processes

schedule()

● Работа планировщика задач не отличается сложностью: он просто выбирает задачу для выполнения из списка с наивысшим приоритетом. Чтобы повысить эффективность этого процесса, для определения наличия задач в списке используется битовый массив. Следовательно, для поиска бита, соответствующего списку с наивысшим приоритетом, можно использовать инструкцию find-first-bit-set, которую поддерживает большинство архитектур процессоров

● Время, затрачиваемое на поиск задачи, зависит не от числа активных задач, а от числа приоритетов. Следовательно, планировщик версии 2.6 является процессом сложности O(1), поскольку время, затрачиваемое на планирование задачи постоянно и детерминистично вне зависимости от числа активных задач.

Page 31: Linux Kernel Processes

Основные стратегии планирования

● SCHED_OTHER - обычная стратегия● SCHED_FIFO - Готовое к выполнению задание всегда

будет планироваться на выполнение перед всемизаданиями со стратегией планирования SCHED_OTHER. Когда задание со стратегией SCHED_FIFO становится готовым к выполнению, то оно будет продолжать выполняться до тех пор, пока не заблокируется или пока явно не отдаст управление.

● SCHED_RR - аналогична стратегии SCHED_FIFO, за исключением того, что процесс может выполняться только до тех пор, пока не израсходует предопре-деленный ему квант времени.

Page 32: Linux Kernel Processes

Распределение нагрузки в SMP-системах

● Задачи, запущенные в SMP-системе, попадают в очередь задач одного из ЦП. В общем случае невозможно предсказать, завершится ли задача почти сразу или будет выполняться в течение длительного времени. Следовательно, первоначальное распределение задач по ЦП скорее всего будет неоптимальным.

● Для того чтобы обеспечить сбалансированную загрузку процессоров, необходимо перераспределение задач путем их переноса с перегруженного ЦП на недозагруженный. Планировщик Linux 2.6 делает это путем распределения нагрузки. Каждые 200 миллисекунд планировщик проверяет, сбалансирована ли нагрузка на процессоры. Если нет, производится перенос задач между ними.


Recommended