Краткий обзор
Из этой статьи вы узнаете об основных приемах управления приоритетами исполнения процессов в Linux. Вы научитесь:
- Понимать, что такое приоритеты процессов.
- Назначать приоритеты процессов.
- Изменять приоритеты процессов.
Эта статья поможет вам подготовиться к сдаче экзамена LPI 101 на администратора начального уровня (LPIC-1) и содержит материалы цели 103.6 темы 103. Цель имеет вес 2.
Чтобы извлечь наибольшую пользу из наших статей, необходимо обладать базовыми знаниями о Linux и иметь работоспособный компьютер с Linux, на котором можно будет выполнять все встречающиеся команды. Иногда различные версии программ выводят результаты по-разному, поэтому содержимое листингов и рисунков может отличаться от того, что вы увидите на вашем компьютере. Все примеры этой статьи были выполнены в операционной системе Ubuntu 9.10 (Karmic Koala). В основе этой статьи лежит концепция, описанная в предыдущей статье этой серии "Изучаем Linux, 101: создание, отслеживание и уничтожение процессов".
Получение информации о приоритетах процессов
В Linux, как и во всех современных операционных системах, одновременно может выполняться несколько процессов. Это достигается путем разделения процессорных и других ресурсов между процессами. Если какой-то процесс использует ресурсы центрального процессора на 100%, то все остальные процессы могут перестать отвечать на запросы.
Если вы запустите команду top
, то по умолчанию она отобразит процессы, отсортированные по степени использования ресурсов ЦП в убывающем порядке, как показано в листинге 1. В предыдущей статье этой серии "Изучаем Linux, 101: создание, отслеживание и уничтожение процессов" мы создали сценарий простых цифровых часов, который выводил на экран время с интервалом в 30 секунд, а в остальное время ничего не делал. Если бы у нас был запущен такой процесс, то, вероятно, он бы не повлиял на вывод команды top
, поскольку большую часть времени он не использует ресурсы центрального процессора.
Листинг 1. Типовой вывод команды top на компьютере под управлением Linux
top - 08:00:52 up 1 day, 10:20, 5 users, load average: 0.04, 0.08, 0.04
Tasks: 172 total, 1 running, 171 sleeping, 0 stopped, 0 zombie
Cpu(s): 3.7%us, 0.3%sy, 0.0%ni, 95.6%id, 0.0%wa, 0.0%hi, 0.3%si, 0.0%st
Mem: 4057976k total, 1777976k used, 2280000k free, 225808k buffers
Swap: 10241428k total, 0k used, 10241428k free, 655796k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
11220 ian 20 0 555m 106m 27m S 8 2.7 36:06.16 firefox
7 root 15 -5 0 0 0 S 1 0.0 10:59.36 ksoftirqd/1
10849 ian 20 0 212m 15m 10m S 0 0.4 0:08.11 gnome-terminal
1 root 20 0 19584 1888 1196 S 0 0.0 0:00.83 init
2 root 15 -5 0 0 0 S 0 0.0 0:00.01 kthreadd
3 root RT -5 0 0 0 S 0 0.0 0:00.02 migration/0
4 root 15 -5 0 0 0 S 0 0.0 0:01.08 ksoftirqd/0
5 root RT -5 0 0 0 S 0 0.0 0:00.00 watchdog/0
6 root RT -5 0 0 0 S 0 0.0 0:00.03 migration/1
|
В вашей операционной системе могут присутствовать команды и приложения, существенно загружающие центральный процессор. Например, это могут быть редакторы видеофайлов или конвертеры форматов аудио, например, из mp3 в ogg.
Когда количество имеющихся в вашем распоряжении процессоров ограничено, необходимо решить, как распределить имеющиеся ресурсы между несколькими конкурирующими процессами. Обычно эта задача решается так: выбирается какой-то один процесс, который выполняется на протяжении короткого отрезка времени (другое его название - квант времени , т. е. количество процессорного времени, выделяемого приложению) либо до тех пор, пока он не переходит в состояние ожидания какого-либо события, например, завершения операции ввода/вывода. Чтобы важные процессы всегда имели необходимые им процессорные ресурсы, которые могут оказаться занятыми другими ресурсоемкими приложениями, выбор производится на базе распределения машинного времени . Столбец NI в листинге 1 показывает распределение машинного времени (приоритет, или т. н. niceness ) для каждого процесса. Как правило, значение niceness варьируется от -20 до 19; -20 означает наивысший приоритет, а 19 - наименьший приоритет.
Как узнать приоритет с помощью ps
Помимо команды top
для определения значений приоритета (niceness) можно использовать команду ps
. Вы можете настроить вывод одним из способов, описанных в статье "Изучаем Linux, 101: создание, отслеживание и уничтожение процессов", или просто использовать опцию -l
для вывода подробного списка. Вывод команды ps -l
представлен в листинге 2. Как и в случае с командой top
, значение приоритета отображается в столбце NI.
Листинг 2. Использование ps для поиска значений niceness
ian@attic4:~$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 26502 26501 0 80 0 - 5368 wait pts/4 00:00:00 bash
0 R 1000 27046 26502 0 80 0 - 1684 - pts/4 00:00:00 ps
|
Значение приоритета по умолчанию
Из листингов 1 и 2 видно, что значением приоритета по умолчанию (по крайней мере, для процессов, запущенных обычными пользователями) является 0. Вы можете посмотреть значение приоритета для командного интерпретатора и системы, запустив команду nice
без параметров, как показано в листинге 3.
Листинг 3. Проверка значения приоритета по умолчанию
Установка приоритетов
Прежде чем перейти к заданию или изменению приоритетов, давайте создадим небольшой сценарий, потребляющий существенное количество ресурсов процессора; на его примере мы увидим, как на самом деле работают приоритеты.
Сценарий, загружающий процессор
Мы создадим небольшой сценарий, который потребляет процессорные ресурсы и еще принимает в качестве двух входных параметров счетчик и метку, выводит метку, текущие дату и время на экран, уменьшает счетчик от заданного значения до 0 и, наконец, снова выводит метку и дату. Сценарий, представленный в листинге 4, не содержит проверок на ошибки и не очень надежен, тем не менее, он позволяет получить наглядный пример.
Листинг 4. Сценарий, загружающий ЦП
ian@attic4:~$ echo 'x="$1"'>count1.sh
ian@attic4:~$ echo 'echo "$2" $(date)'>>count1.sh
ian@attic4:~$ echo 'while [ $x -gt 0 ]; do x=$(( x-1 ));done'>>count1.sh
ian@attic4:~$ echo 'echo "$2" $(date)'>>count1.sh
ian@attic4:~$ cat count1.sh
x="$1"
echo "$2" $(date)
while [ $x -gt 0 ]; do x=$(( x-1 ));done
echo "$2" $(date)
|
Если вы запустите этот сценарий на вашем компьютере, то должны увидеть вывод, похожий на вывод в листинге 5. В зависимости от быстродействия вашего компьютера вы можете увеличить значение счетчика, чтобы заметить разницу во времени выполнения. Этот сценарий потребляет много ресурсов процессора, в чем мы скоро убедимся. Если вы используете интерпретатор, отличный от bash, и сценарий не работает в вашей системе, то используйте второй способ запуска, показанный ниже. Если вы работаете не на своем компьютере, то прежде, чем запустить этот сценарий, убедитесь, что на нем можно запускать ресурсоемкие задачи.
Листинг 5. Запуск сценария count1.sh
ian@attic4:~$ sh count1.sh 10000 A
A Wed Jan 20 08:34:16 EST 2010
A Wed Jan 20 08:34:16 EST 2010
ian@attic4:~$ bash count1.sh 99000 A
A Wed Jan 20 08:34:20 EST 2010
A Wed Jan 20 08:34:22 EST 2010
|
Пока все хорошо. Давайте теперь создадим список команд для запуска сценария в фоновом режиме, после чего с помощью команды top
посмотрим, сколько ресурсов процессора он расходует (чтобы освежить ваши знания о списках команд, обратитесь к статье "Изучаем Linux, 101: командная строка Linux"). Список команд показан в листинге 6, а вывод команды top
- в листинге 7.
Листинг 6. Запуск сценария count1.sh и команды top
ian@attic4:~$ (sh count1.sh 5000000 A&);top
|
Листинг 7. Интенсивное использование ресурсов ЦП
top - 15:41:15 up 1 day, 17:59, 6 users, load average: 0.20, 0.06, 0.02
Tasks: 169 total, 2 running, 167 sleeping, 0 stopped, 0 zombie
Cpu(s): 52.1%us, 0.7%sy, 0.0%ni, 47.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4057976k total, 1393772k used, 2664204k free, 235596k buffers
Swap: 10241428k total, 0k used, 10241428k free, 662592k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26756 ian 20 0 4004 588 496 R 100 0.0 0:03.53 sh
11220 ian 20 0 555m 101m 27m S 5 2.6 57:58.07 firefox
26757 ian 20 0 19132 1364 980 R 0 0.0 0:00.03 top
1 root 20 0 19584 1888 1196 S 0 0.0 0:00.89 init
2 root 15 -5 0 0 0 S 0 0.0 0:00.01 kthreadd
|
Неплохо. Запустив наш сценарий, мы используем ресурсы центрального процессора на 100%. Если вы хотите загрузить несколько процессоров, вы можете добавить в список команд запуск дополнительных экземпляров count1.sh
. Если такая задача будет выполняться продолжительное время, то вы (или другие пользователи) заметите, что она существенно влияет на скорость работы компьютера.
Использование nice для назначения приоритетов
Теперь, когда наша система какое-то время нагружена, давайте посмотрим, как можно установить приоритет для процесса. Давайте подведем краткие итоги уже пройденного материала.
- В операционных системах Linux и UNIX® используется система приоритетов, всего 40 уровней, начиная с -20 (наивысший приоритет) и заканчивая 19 (низший приоритет).
- Процессы, запущенные обычными пользователями, обычно имеют приоритет 0.
- Команда
ps
может показать приоритет процесса (например, значение nice или NI) с помощью опции -l
.
- Команда
nice
показывает приоритет по умолчанию.
Команду nice
можно также использовать для запуска процесса с другим приоритетом. Опция -n
(или --adjustment
) с положительным значением повышает приоритет, а эта же опция с отрицательным значением - понижает его. Помните, что процесс с наименьшим приоритетом имеет максимальное значение параметра niceness, поэтому увеличение этого значения означает, что процесс становится более дружелюбным по отношению к другим процессам. Заметьте, что, как правило, понижать значение приоритетов процессов может только суперпользователь (root). Другими словами, обычные пользователи могут делать процессы лишь более дружелюбными.
Чтобы продемонстрировать использование команды nice
для установки приоритетов, давайте запустим два экземпляра сценария count1.sh
в различных подоболочках, но одному из них назначим максимальное значение параметра niceness 19. Через секунду запустим команду ps -l
, чтобы посмотреть статус процесса, включая значение niceness. Наконец, добавим произвольную паузу в интервале 30 секунд, чтобы убедиться, что последовательность команд завершится только после завершения работы подоболочек. Таким образом, мы не увидим новое приглашение, пока ожидаем вывода. Результаты представлены в листинге 8.
Листинг 8. Использование nice для установки приоритетов для двух процессов
ian@attic4:~$ (sh count1.sh 2000000 A&);(nice -n 19 sh count1.sh 2000000 B&);\
> sleep 1;ps -l;sleep 10
A Thu Jan 21 14:38:39 EST 2010
B Thu Jan 21 14:38:39 EST 2010
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 946 1 99 80 0 - 1001 - pts/3 00:00:01 sh
0 R 1000 948 1 99 99 19 - 1001 - pts/3 00:00:01 sh
0 R 1000 952 32408 0 80 0 - 1684 - pts/3 00:00:00 ps
0 S 1000 32408 32407 0 80 0 - 5368 wait pts/3 00:00:02 bash
A Thu Jan 21 14:38:45 EST 2010
B Thu Jan 21 14:38:45 EST 2010
|
Оба задания завершились одновременно несмотря на разные приоритеты. Дело в том, что сценарий использует ресурсы одного процессора, а на моем компьютере установлен двуядерный процессор AMD Athlon™ 7750, который практически не загружен, поэтому каждый из двух процессов выполнялся на отдельном ядре, а необходимость в установке приоритетов в данном случае отсутствовала.
Давайте теперь запустим четыре процесса с различными значениями niceness (0, 6, 12 и 18) и посмотрим, что произойдет в этом случае. Для каждого процесса мы увеличили значение счетчика, чтобы они выполнялись немного дольше. Прежде чем переходить к листингу 9, подумайте, каких результатов можно ожидать теперь, исходя из того, что вы уже видели.
Листинг 9. Использование nice для назначения приоритетов для четырех процессов
ian@attic4:~$ (sh count1.sh 5000000 A&);(nice -n 6 sh count1.sh 5000000 B&);\
> (nice -n 12 sh count1.sh 5000000 C&);(nice -n 18 sh count1.sh 5000000 D&);\
> sleep 1;ps -l;sleep 30
A Thu Jan 21 16:06:00 EST 2010
C Thu Jan 21 16:06:00 EST 2010
D Thu Jan 21 16:06:00 EST 2010
B Thu Jan 21 16:06:00 EST 2010
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 1422 1 94 80 0 - 1001 - pts/3 00:00:00 sh
0 R 1000 1424 1 42 86 6 - 1001 - pts/3 00:00:00 sh
0 R 1000 1427 1 56 92 12 - 1001 - pts/3 00:00:00 sh
0 R 1000 1431 1 14 98 18 - 1001 - pts/3 00:00:00 sh
0 R 1000 1435 32408 0 80 0 - 1684 - pts/3 00:00:00 ps
0 S 1000 32408 32407 0 80 0 - 5368 wait pts/3 00:00:02 bash
A Thu Jan 21 16:06:14 EST 2010
B Thu Jan 21 16:06:17 EST 2010
C Thu Jan 21 16:06:26 EST 2010
D Thu Jan 21 16:06:30 EST 2010
|
Установив четыре различных приоритета, мы видим эффект, который заключается в том, что все задания завершились по порядку. Попробуйте поэкспериментировать с различными значениями приоритетов и самостоятельно проанализировать полученные результаты.
И последнее замечание относительно запуска процессов при помощи nice
: как и в случае с командой nohup
, в качестве аргумента nice
нельзя использовать конвейер или список команд.
Изменение приоритетов
Команда renice
Если вы запустили процесс и поняли, что он должен выполняться с другим приоритетом, то существует способ изменить приоритет работающего процесса с помощью команды renice
. В листинге 10 показано, как указать абсолютное значение (а не величину изменения) приоритета одного или нескольких процессов.
Листинг 10. Использование renice для изменения приоритетов
ian@attic4:~$ sh count1.sh 10000000 A&
[1] 1537
ian@attic4:~$ A Thu Jan 21 16:17:16 EST 2010
sh count1.sh 1renice 1 1537;ps -l 1537
1537: old priority 0, new priority 1
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 1537 32408 99 81 1 - 1001 - pts/3 0:13 sh count1.sh 100
ian@attic4:~$ renice +3 1537;ps -l 1537
1537: old priority 1, new priority 3
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 1537 32408 99 83 3 - 1001 - pts/3 0:18 sh count1.sh 100
|
Помните, что для того, чтобы назначать процессам более высокий приоритет и делать их менее дружелюбными, необходимо иметь привилегии суперпользователя.
Дополнительную информацию о командах nice
и renice
вы можете найти на соответствующих man-страницах.