Флаг 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
Возвращает 0 при успешном завершении или –1, если произошла ошибка
Как и в случае с другими системными вызовами, предназначенными для планирования, аргумент pid обозначает процесс, информацию о котором мы хотим получить, а чтобы задать вызывающий процесс, используется значение 0. Временной отрезок возвращается внутри структуры timespec, на которую указывает аргумент tp:
struct timespec {
time_t tv_sec; /* Секунды */
long tv_nsec; /* Наносекунды */
};
В последних ядрах ветки 2.6 циклический отрезок реального времени равен 0,1 секунды.
Когда планирование происходит в многопроцессорной системе, работа процесса может быть запланирована не на том ЦПУ, на котором он выполнялся до этого. Обычно причина заключается в том, что тот процессор уже занят.
Смена процессоров отражается на производительности: чтобы загрузить линию данных процесса в кэш нового ЦПУ, они сначала должно быть освобождены (удалены, если их никто не успел изменить, или просто сброшены в главную память) из кэша предыдущего процессора (чтобы избежать несогласованности кэшей, многопроцессорные архитектуры позволяют хранить данные в кэше только одного ЦПУ). Эта процедура увеличивает время выполнения. По этой причине ядро Linux (начиная с 2.6) пытается выполнять
Кэш-линия является аналогом страницы в системе управления виртуальной памятью. Она имеет размер, который используется для передачи данных между кэшем процессора и главной памятью. Обычно размер линии варьируется в пределах от 32 до 128 байт. Больше информации можно найти в источниках [Schimmel, 1994] и [Drepper, 2007].
Одно из полей файла /proc/PID/stat (доступного только в Linux) содержит количество ЦПУ, на которых выполняется или ранее выполнялся процесс. Подробности ищите на справочной странице proc(5).
В некоторых случаях предпочтительной является
• Мы можем избежать понижения производительности, вызванного удалением данных из кэша.
• Если несколько потоков (или процессов) работают с одними и теми же данными, мы можем повысить производительность, привязав их к одному и тому же процессору; так они не будут соперничать за общие данные и смогут избежать потери кэша.
• Если приложение чувствительно к времени выполнения, ему можно выделить отдельный процессор, привязав другие процессы к остальным ЦПУ.
Linux 2.6 предоставляет два нестандартных системных вызова для изменения и получения данных о жесткой привязке процесса к ЦПУ: sched_setaffinity() и sched_getaffinity().