11. Управление заданиями#

Введение#

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

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

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

Управление заданиями#

Интерактивные терминальные приложения предлагают разные способы завершения работы. Пейджер less закрывается по команде q, текстовый редактор nano по Ctrl-X, vim по :q!. Остальные (неинтерактивные) программы, если в них не заложено завершение по просьбе, могут быть принудительно завершены системой сочетанием клавиш Ctrl-C.

На заднем плане одновременно могут размещаться несколько заданий. Если в конец команды добавить символ &, то команда запустится на заднем плане.

user@sppo:~/projects/$ find ~ -name lab1.txt &
[1] 33533

Дополнительно на экране выведется номер задания ([1]) и идентификатор процесса (33533). В последующем они понадобятся, чтобы сослаться на задание.

Note

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

Фоновое задание будет выполнять работу до своего завершения или пока ему не понадобится ввод от пользователя. В последнем случае оно приостановит свое выполнение до переключения в активное состояние. Примером программы, постоянно нуждающемся в пользовательских данных, является vim.

user@sppo:~/projects$ vim &
[1] 34226
user@sppo:~/projects$ 

[1]+  Stopped                 vim
user@sppo:~/projects$ 

Фоновые программы выводят сообщения на экране, что может быть неожиданным. Чтобы такого не происходило, используют перенаправление потока вывода в файл или системную корзину: ./program > /dev/null &

Сочетание клавиш Ctrl-Z приостанавливает активное задание. После приостановки на передний план выходит командная оболочка. Встроенная команда bg (сокращение от “background” в переводе “задний план”) запускает приостановленное задание и перемещает его на задний план. Таким образом комбинации Ctrl-Z и bg перемещают задание из переднего плана на задний.

На заднем плане могут размещаться несколько заданий. Их список на экран выводит встроенная команда jobs.

user@sppo:~/projects$ jobs
[1]+  Stopped                 vim
[2]   Running                 bzip2 -k9 bigfile.bin &
[3]-  Running                 sleep 2h &

Она выводит список заданий с номером, состоянием и командной строкой запуска. Знаком + отмечено текущее задание, а знаком - – предыдущее.

Перенос задания на передний план выполняет команда fg (сокращение от “foreground”, что в переводе “передний план”). Если аргумент не указан, то команда перенесет текущее задание (то, что отмечено знаком +). Чтобы сослаться на конкретное задание, используют символ % и номер задания: fg %2.

Сигналы#

Сочетания клавиш Ctrl-C и Ctrl-Z соответственно завершают и приостанавливают активный процесс. Технически, это выглядит как отправка терминалом группе процессов сигнала о завершении (-SIGINT) и приостановке (-SIGTSTP). Те же самые сигналы можно отправить произвольному процессу, воспользовавшись утилитой kill. Утилита требует идентификатор процесса (или номер задания, предваренного символом %) и по умолчанию отправляет сигнал -SIGKILL, который завершает принудительно процесс.

bob@pc:~/projects/sppo$ dd if=/dev/zero of=/dev/null &
[1] 12512
bob@pc:~/projects/sppo$ kill %1
bob@pc:~/projects/sppo$ 
[1]+  Завершено      dd if=/dev/zero of=/dev/null
bob@pc:~/projects/sppo$ 

Note

Сигнал -SIGINT “просит” процесс завершиться. Если программа не переопределяла обработчик событий на него, то она выполнит это действие. Правильно переопределенный обработчик сигнала сохраняет данные и завершает после этого процесс. В отличие от него сигнал -SIGKILL завершает процесс немедленно, без каких-либо предварительных действий. Если -SIGINT можно проигнорировать, установив пустой обработчик сигнала, то -SIGKILL – нет.

Полезное сочетание клавиш Ctrl-\ принудительно завершает активное задание сигналом -SIGQUIT. Но в отличие от -SIGKILL в текущем каталоге сохранится содержимое оперативной памяти процесса (дамп памяти). В последующем дамп памяти может быть использован для отладки программы.

Заключение#

Работа разработчика состоит в изучении и редактировании исходного кода, отладке, в ожидании сборки и результатов тестирования. Вся эта деятельность происходит внутри одного приложения, называемого интегрированной средой разработки. Это позволяет отказаться от переключения между разнородными программами. Редактор vim позволяет настроить себя под полноценную среду разработки.

Альтернативный способ работы с несколькими приложениями – это разделение экрана терминала на несколько вложенных терминалов с неперекрывающимися видами. Подробнее об этом будет рассказано в разделе Терминальный мультиплексор.

Использованные источники#

  1. Раздел “34.7. Управление заданиями” книги М.Керриск “Linux API. Исчерпывающее руководство.” – СПб.: Питер, 2021. – 1248 с.: ил. – (Серия “Библиотека программиста”).

  2. Job Control Basics

  3. Need a Linux command that takes much time

Вопросы для самоконтроля#

  1. Расскажите про активные и фоновые программы. Чем они отличаются? Где они могут понадобиться?

  2. В чем отличия между программой, командой, заданием и процессом?

  3. Как завершить запущенную программу?

  4. Запустите команду sort и завершите запущенную программу.

  5. Запустите на заднем плане перечисленные ниже команды и объясните, что они делают:

    • vim main.c

    • sleep 1h

    • dd if=/dev/zero of=/dev/null

  6. Что произойдет с фоновым заданием, которому вдруг понадобятся пользовательские данные?

  7. Что произойдет, если фоновому заданию понадобится вывести данные на экран?

  8. Как перевести программу из переднего плана на задний?

  9. Как получить список заданий на заднем плане и их состояние.

  10. Как перевести задание из заднего плана на передний?

  11. Какая связь между сочетаниями клавиш Ctrl-C, Ctrl-Z и Ctrl-\ и сигналами?

  12. Что делает утилита kill? Запустите на заднем плане задание sleep 1h и завершите его поочередно отправкой сигналов -SIGINT, -SIGKILL, -SIGQUIT. Чем отличаются сообщения командной оболочки на выходе?

  13. Создайте файл размером 1 Гб командой dd if=/dev/urandom of=bigfile.bin bs=10MiB count=100. Сожмите файл утилитой bzip2 с опцией -9 (максимальный уровень сжатия) и сохранив оригинал (опция --keep). Запустите последнюю команду на заднем плане. Проконтролируйте, как долго выполнится задание.