Ядро Linux в комментариях

       

Setscheduler


Тремя аргументами этой функции являются целевой процесс pid (значение 0 означает текущий процесс), новая политика планирования policy и param, структура, содержащая дополнительную информацию — новое значение rt_priority.

Выполняя некоторые профилактические проверки, функция setscheduler копирует переданную структуру struct sched_param из области пользователя. Эта структура, определенная в строке , имеет только один член sched_priority, который является затребованным вызывающей функцией значением rt_priority\ для целевого процесса.

Находит целевой процесс, используя функцию find_process_by_pid (строка ), которая возвращает либо указатель на текущую задачу (если pid равен 0), либо указатель на процесс с заданным PID (если таковой существует), либо NULL (если не существует ни одного процесса с этим PID).

Если аргумент policy был отрицательным, текущая политика планирования сохраняется. В противном случае она принимается временно, если ее значение допустимо.

Убеждается, что приоритет находится в допустимом диапазоне. Это достигается несколько сложным путем. Данная строка — всего лишь первый шаг, подтверждающий, что переданное значение не слишком выходит за рамки диапазона.

Теперь известно, что приоритет реального времени лежит в диапазоне между 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; }


He каждому процессу должно быть разрешено устанавливать собственную политику планирования или политику планирования другого процесса. Если бы было можно, любой процесс мог бы узурпировать центральный процессор, по существу блокируя систему, просто устанавливая свою политику планирования в значение SCHED_FIFO и входя в бесконечный цикл. Естественно, это нельзя допустить. Поэтому функция setscheduler позволяет процессу устанавливать собственную политику планирования, только если он имеет возможность сделать это. Возможности подробнее освещены в следующем разделе.

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

Именно здесь функция setscheduler наконец берется за дело, устанавливая поля policy и priority в структуре struct task_struct целевого процесса. И, если процесс находится в текущей очереди (что проверяется путем проверки того, что значение его члена next_run не является NULL), он перемещается в ее начало — это несколько странно; возможно, это было сделано, чтобы помочь процессу SCHED_FIFO получить доступ к процессору. Процесс помечается для повторного планирования, а функция setscheduler осуществляет уборку и выход.


Содержание раздела