Флаг SCHED_RESET_ON_FORK был создан для использования в приложениях, воспроизводящих мультимедийные данные. Он позволяет создавать отдельные процессы, от которых нельзя наследовать политику выполнения реального времени. Применение этого флага помогает избежать так называемых fork-бомб, которые пытаются обойти ограничения, наложенные ограничением RLIMIT_RTTIME, создавая множество потомков, работающих в режиме реального времени.

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

35.3.3. Освобождение ресурсов процессора

Процессы реального времени могут добровольно освободить ресурсы ЦПУ двумя способами: выполнив блокирующий системный вызов (например, чтение из терминала) или воспользовавшись вызовом sched_yield().

#include

int sched_yield(void);

Возвращает 0 при успешном завершении или –1, если произошла ошибка

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

Стандарт SUSv3 допускает возвращение ошибок вызовом sched_yield(), однако в Linux, как и во многих других реализациях UNIX, он всегда завершается успешно. Тем не менее переносимые приложения обязательно должны делать проверку на ошибки.

Использование вызова sched_yield() вне политики реального времени не определено.

35.3.4. Временной отрезок в политике SCHED_RR

Системный вызов sched_rr_get_interval() позволяет определять длину каждого временного отрезка, на протяжении которого процесс с политикой SCHED_RR может использовать ресурсы ЦПУ.

#include

int sched_rr_get_interval(pid_t pid, struct timespec *tp);

Возвращает 0 при успешном завершении или –1, если произошла ошибка

Как и в случае с другими системными вызовами, предназначенными для планирования, аргумент pid обозначает процесс, информацию о котором мы хотим получить, а чтобы задать вызывающий процесс, используется значение 0. Временной отрезок возвращается внутри структуры timespec, на которую указывает аргумент tp:

struct timespec {

time_t tv_sec; /* Секунды */

long tv_nsec; /* Наносекунды */

};

В последних ядрах ветки 2.6 циклический отрезок реального времени равен 0,1 секунды.

35.4. Привязка к процессору

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

Смена процессоров отражается на производительности: чтобы загрузить линию данных процесса в кэш нового ЦПУ, они сначала должно быть освобождены (удалены, если их никто не успел изменить, или просто сброшены в главную память) из кэша предыдущего процессора (чтобы избежать несогласованности кэшей, многопроцессорные архитектуры позволяют хранить данные в кэше только одного ЦПУ). Эта процедура увеличивает время выполнения. По этой причине ядро Linux (начиная с 2.6) пытается выполнять мягкую привязку процесса к ЦПУ, то есть по возможности работа процесса планируется на одном и том же процессоре.

Кэш-линия является аналогом страницы в системе управления виртуальной памятью. Она имеет размер, который используется для передачи данных между кэшем процессора и главной памятью. Обычно размер линии варьируется в пределах от 32 до 128 байт. Больше информации можно найти в источниках [Schimmel, 1994] и [Drepper, 2007].

Одно из полей файла /proc/PID/stat (доступного только в Linux) содержит количество ЦПУ, на которых выполняется или ранее выполнялся процесс. Подробности ищите на справочной странице proc(5).

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

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

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

• Если приложение чувствительно к времени выполнения, ему можно выделить отдельный процессор, привязав другие процессы к остальным ЦПУ.

Linux 2.6 предоставляет два нестандартных системных вызова для изменения и получения данных о жесткой привязке процесса к ЦПУ: sched_setaffinity() и sched_getaffinity().

Перейти на страницу:

Похожие книги