netlib.narod.ru | < Назад | Оглавление | Далее > |
Процессы реального времени Linux добавляют новый уровень к схеме приоритетов. Приоритет реального времени хранится в члене rt_priority структуры struct task_struct и является целым числом в диапазоне от 0 до 99. (Значение, равное 0, означает, что процесс не является процессом реального времени, и в этом случае его членом policy должен быть SCHED_OTHER.)
Задачи реального времени используют тот же член counter, что и их аналоги не реального времени, и поэтому их динамические приоритеты обрабатываются таким же образом. Задачи реального времени даже используют член priority для той же цели, что и задачи не реального времени — в качестве значения, посредством которого они пополняют значение counter, когда оно полностью использовано. Для ясности, следует отметить, что член priority используется только для ранжирования процессов реального относительно друг друга — в остальном они обрабатываются идентично процессам не реального времени.
rt_priority процесса устанавливается в качестве части определения его политики планирования с помощью стандартизованных POSIX.1b функций sched_setscheduler и sched_setparam (которые, обычно, имеет право вызывать только привилегированный пользователь, как будет показано при рассмотрении возможностей). Это означает, что политика планирования процесса может изменяться во время его существования, если, конечно, процесс имеет разрешение выполнять изменение.
Системные вызовы, реализующие эти функции POSIX sched_setscheduler (строка 27688) и sched_setparam (строка 27694), делегируют всю реальную работу функции setscheduler (строка 27618), которую мы теперь и исследуем.
27618: Тремя аргументами этой функции являются целевой процесс pid (значение 0 означает текущий процесс), новая политика планирования policy и param, структура, содержащая дополнительную информацию — новое значение rt_priority.
27630: Выполняя некоторые профилактические проверки, функция setscheduler копирует переданную структуру struct sched_param из области пользователя. Эта структура, определенная в строке 16204, имеет только один член sched_priority, который является затребованным вызывающей функцией значением rt_priority\ для целевого процесса.
27639: Находит целевой процесс, используя функцию find_process_by_pid (строка 27608), которая возвращает либо указатель на текущую задачу (если pid равен 0), либо указатель на процесс с заданным PID (если таковой существует), либо NULL (если не существует ни одного процесса с этим PID).
27645: Если аргумент policy был отрицательным, текущая политика планирования сохраняется. В противном случае она принимается временно, если ее значение допустимо.
27657: Убеждается, что приоритет находится в допустимом диапазоне. Это достигается несколько сложным путем. Данная строка — всего лишь первый шаг, подтверждающий, что переданное значение не слишком выходит за рамки диапазона.
27659: Теперь известно, что приоритет реального времени лежит в диапазоне между 0 и 99, включая крайние значения. Если значением policy является SCHED_OTHER, но новый приоритет реального времени не равен 0, этот тест не пройдет. Тест не пройдет, также, если policy определяет один из планировщиков реального времени, но новый приоритет реального времени равен 0 (если он не равен 0, значит, он имеет значение от 1 до 99, как и должно быть). В противном случае тест будет успешным. Эта конструкция не очень понятна, но она верна, максимально минимизирована и (как мне кажется) работает быстро. Однако, я не уверен, что в данном случае требуется особенно высокая скорость работы — в конце концов, как часто процесс устанавливает свой планировщик? Следующая конструкция была бы более читабельной и наверняка не на много более медленной:
if (policy == SCHED_OTHER) { if (lp.sched_priority != 0) goto out_unlock; } else { /* SCHED_FIFO или SCHED_RR */ if ((lp.sched_priority < 1) || (lp.sched_priority > 99)) goto out_unlock; }
27663: He каждому процессу должно быть разрешено устанавливать собственную политику планирования или политику планирования другого процесса. Если бы было можно, любой процесс мог бы узурпировать центральный процессор, по существу блокируя систему, просто устанавливая свою политику планирования в значение SCHED_FIFO и входя в бесконечный цикл. Естественно, это нельзя допустить. Поэтому функция setscheduler позволяет процессу устанавливать собственную политику планирования, только если он имеет возможность сделать это. Возможности подробнее освещены в следующем разделе.
27666: Следуя этой же логике, нежелательно, чтобы кто угодно мог изменять политику планирования процессов любых других пользователей; как правило, пользователю должно разрешаться изменять политику планирования только собственных процессов. Поэтому setscheduler убеждается, что пользователь либо устанавливает планировщик собственного процесса, либо имеет возможность устанавливать политику планирования любых пользователей.
27672: Именно здесь функция setscheduler наконец берется за дело, устанавливая поля policy и priority в структуре struct task_struct целевого процесса. И, если процесс находится в текущей очереди (что проверяется путем проверки того, что значение его члена next_run не является NULL), он перемещается в ее начало — это несколько странно; возможно, это было сделано, чтобы помочь процессу SCHED_FIFO получить доступ к процессору. Процесс помечается для повторного планирования, а функция setscheduler осуществляет уборку и выход.
netlib.narod.ru | < Назад | Оглавление | Далее > |