Управление процессами в Linux
Материал этой статьи ни в коем случае не претендует на свою избыточность. Более подробно о процессах вы можете прочитать в книгах, посвященных программированию под UNIX.
Процессы. Системные вызовы fork() и exec(). Нити.
В Linux поддерживается классическая схема мультипрограммирования. Linux поддерживает параллельное (или квазипараллельного при наличии только одного процессора) выполнение процессов пользователя. Каждый процесс выполняется в собственном виртуальном адресном пространстве, т.е. процессы защищены друг от друга и крах одного процесса никак не повлияет на другие выполняющиеся процессы и на всю систему в целом. Один процесс не может прочитать что-либо из памяти (или записать в нее) другого процесса без «разрешения» на то другого процесса. Санкционированные взаимодействия между процессами допускаются системой.
Ядро предоставляет системные вызовы для создания новых процессов и для управления порожденными процессами. Любая программа может начать выполняться только если другой процесс ее запустит или произойдет какое-то прерывание (например, прерывание внешнего устройства).
В качестве примера рассмотрим этот фрагмент программы
if (fork()==0) wait(0);
else execl(«ls», «ls», 0); /* порожденный процесс */
Установить реакцию на поступление сигнала можно с помощью системного вызова signal
func = signal(snum, function);
Таблица 1. Номера сигналов
| Номер | Название | Описание |
| 01 | SIGHUP | Освобождение линии (hangup). |
| 02 | SIGINT | Прерывание (interrupt). |
| 03 | SIGQUIT | Выход (quit). |
| 04 | SIGILL | Некорректная команда (illegal instruction). Не переустанавливается при перехвате. |
| 05 | SIGTRAP | Трассировочное прерывание (trace trap). Не переустанавливается при перехвате. |
| 06 | SIGIOT или SIGABRT | Машинная команда IOT. |
| 07 | SIGEMT | Машинная команда EMT. |
| 08 | SIGFPE | Исключительная ситуация при выполнении операции с вещественными числами (floating-point exception) |
| 09 | SIGKILL | Уничтожение процесса (kill). Не перехватывается и не игнорируется. |
| 10 | SIGBUS | Ошибка шины (bus error). |
| 11 | SIGSEGV | Некорректное обращение к сегменту памяти (segmentation violation). |
| 12 | SIGSYS | Некорректный параметр системного вызова (bad argument to system call). |
| 13 | SIGPIPE | Запись в канал, из которого некому читать (write on a pipe with no one to read it). |
| 14 | SIGALRM | Будильник |
| 15 | SIGTERM | Программный сигнал завершения |
| 16 | SIGUSR1 | Определяемый пользователем сигнал 1 |
| 17 | SIGUSR2 | Определяемый пользователем сигнал 2 |
| 18 | SIGCLD | Завершение порожденного процесса (death of a child). |
| 19 | SIGPWR | Ошибка питания |
| 22 | Регистрация выборочного события |
Сигналы (точнее их номера) описаны в файле singnal.h
Перенаправление ввода/вывода
Символ > используется для перенаправления стандартного вывода в файл.
Пример:
$ cat > newfile.txt Стандартный ввод команды cat будет перенаправлен в файл newfile.txt, который будет создан после выполнения этой команды. Если файл с этим именем уже существует, то он будет перезаписан. Нажатие Ctrl + D остановит перенаправление и прерывает выполнение команды cat.
Символ < используется для переназначения стандартного ввода команды. Например, при выполнении команды cat > используется для присоединения данных в конец файла (append) стандартного вывода команды. Например, в отличие от случая с символом >, выполнение команды cat >> newfile.txt не перезапишет файл в случае его существования, а добавит данные в его конец.
Команды для управления процессами
Предназначена для вывода информации о выполняемых процессах. Данная команда имеет много параметров, о которых вы можете прочитать в руководстве (man ps). Здесь я опишу лишь наиболее часто используемые мной:
| Параметр | Описание |
| -a | отобразить все процессы, связанных с терминалом (отображаются процессы всех пользователей) |
| -e | отобразить все процессы |
| -t список терминалов | отобразить процессы, связанные с терминалами |
| -u идентификаторы пользователей | отобразить процессы, связанные с данными идентификаторыми |
| -g идентификаторы групп | отобразить процессы, связанные с данными идентификаторыми групп |
| -x | отобразить все процессы, не связанные с терминалом |
Для вывода информации о конкретном процессе мы можем воспользоваться командой:
Предназначена для вывода информации о процессах в реальном времени. Процессы сортируются по максимальному занимаемому процессорному времени, но вы можете изменить порядок сортировки (см. man top). Программа также сообщает о свободных системных ресурсах.
nice [-коэффициент понижения] команда [аргумент]
nohup команда [аргумент]
nohup выполняет запуск команды в режиме игнорирования сигналов. Не игнорируются только сигналы SIGHUP и SIGQUIT.
kill [-номер сигнала] PID
5.8. Команда exec
5.8. Команда exec
Команда exec заменяет текущий интерпретатор shell указанной командой. Обычно она используется для того, чтобы закрыть текущий интерпретатор и запустить другой. Но у нее есть и другое применение. Например, команда вида
Читайте также
9.1.4. Запуск новой программы: семейство exec()
9.1.4. Запуск новой программы: семейство exec() После запуска нового процесса (посредством fork()) следующим шагом является запуск в процессе другой программы. Имеется несколько функций, которые служат различным целям:#include /* POSIX */int execve(const char *filename, /* Системный вызов */char
9.1.4.4. Атрибуты, наследуемые exec()
9.1.4.4. Атрибуты, наследуемые exec() Как и в случае с fork(), после вызова программой exec сохраняется ряд атрибутов:• Все открытые файлы и открытые каталоги; см. раздел 4.4.1 «Понятие о дескрипторах файлов» и раздел 3.3.1 «Базовое чтение каталогов». (Сюда не входят файлы, помеченные для
9.4.3.1. Флаг close-on-exec
9.4.3.1. Флаг close-on-exec После вызова fork() и перед вызовом exec() следует убедиться, что новая программа наследует лишь те открытые файлы, которые ей нужны. Вы не захотите, чтобы порожденный процесс мешался в открытых файлах родителя, если только это так не задумано. С другой стороны,
10.9. Сигналы, передающиеся через fork() и exec()
10.9. Сигналы, передающиеся через fork() и exec() Когда программа вызывает fork(), ситуация с сигналами в порожденном процессе почти идентична ситуации в родительском процессе. Установленные обработчики остаются на месте, заблокированные сигналы остаются заблокированными и т.д.
4.7. Функции fork и exec
4.7. Функции fork и exec Прежде чем рассматривать создание параллельного сервера (что мы сделаем в следующем разделе), необходимо описать функцию Unix fork. Эта функция является единственным способом создания нового процесса в Unix.#include pid_t fork(void);Возвращает: 0 в дочернем
9.2.1.2 Функция exec в системе с замещением страниц
9.2.1.2 Функция exec в системе с замещением страниц Как уже говорилось в главе 7, когда процесс обращается к системной функции exec, ядро считывает из файловой системы в память указанный исполняемый файл. Однако в системе с замещением страниц по запросу исполняемый файл, имеющий
Exec (путь и название исполняемого файла)
Exec (путь и название исполняемого файла) Метод предназначен для выполнения команд и при своем вызове возвращает объект, с помощью которого можно управлять вызванной программой. Данный объект поддерживает следующие методы. ПРИМЕЧАНИЕ Выполнить команду можно также с
Команда
Команда Команда используется для выполнения SQL-запросов к базе данных Важно не путать команду, которая является СОМ-объектом, с текстом команды, который представляет собой строку. Обычно команды используют для описания данных, например для создания таблицы и
1.5. Действие команд fork, exec и exit на объекты IPC
1.5. Действие команд fork, exec и exit на объекты IPC Нам нужно достичь понимания действия функций fork, exec и _exit на различные формы IPC, которые мы обсуждаем (последняя из перечисленных функций вызывается функцией exit). Информация по этому вопросу сведена в табл. 1.4.Большинство функций
16.1. С помощью команды exec
Пример 16-3. Одновременное перенаправление устройств, stdin и stdout, с помощью команды exec
exec – Команда Linux – Команда Unix
exec – вызвать подпроцесс (ы)
конспект
Описание
Эта команда обрабатывает свои аргументы как спецификацию одного или нескольких подпроцессов для выполнения. Аргументы принимают форму стандартного конвейера оболочки, где каждый arg становится одним словом команды, а каждая отдельная команда становится подпроцессом.
-keepnewline
Сохраняет завершающий символ новой строки в выводе конвейера. Обычно завершающий символ новой строки будет удален.
Если arg (или пара arg ) имеет одну из форм, описанных ниже, то он используется exec для управления потоком ввод и вывод среди подпроцесса (ов). Такие аргументы не будут переданы подпроцессу (-ам). В таких формах, как “ имя_файла ”).
Отдельные команды в конвейере. Стандартный вывод предыдущей команды будет передан в стандартный ввод следующей команды.
Отдельные команды в конвейере. Как стандартный вывод, так и стандартная ошибка предыдущей команды будут переданы в стандартный ввод следующей команды. Эта форма перенаправления переопределяет формы, такие как 2> и> &.
Если стандартный вывод не был перенаправлен, то команда exec возвращает стандартный вывод последней команды в конвейере.Если какая-либо из команд в конвейере выйдет ненормально или будет убита или приостановлена, то exec вернет ошибку, и сообщение об ошибке будет содержать выходные данные конвейера, за которыми следуют сообщения об ошибках, описывающие ненормальные завершения; переменная errorCode будет содержать дополнительную информацию о последнем аварийном завершении. Если какая-либо из команд записывает в свой стандартный файл ошибок и эта стандартная ошибка не перенаправлена, то exec вернет ошибку; сообщение об ошибке будет содержать стандартный вывод конвейера, за которым следуют сообщения о ненормальных завершениях (если есть), за которыми следует стандартный вывод ошибок.
Если стандартный ввод не перенаправляется с помощью “
Bash-скрипты, часть 4: ввод и вывод
В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.
Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:
Стандартные дескрипторы файлов
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.
Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
STDIN
STDOUT
Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:
Перенаправление вывода команды в файл
После выполнения этой команды мы увидим сообщения об ошибках на экране.
Попытка обращения к несуществующему файлу
При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.
STDERR
Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.
▍Перенаправление потока ошибок
Как вы уже знаете, дескриптор файла STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:
Перенаправление сообщения об ошибке в файл
▍Перенаправление потоков ошибок и вывода
При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:
Перенаправление ошибок и стандартного вывода
Перенаправление STDERR и STDOUT в один и тот же файл
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
▍Временное перенаправление вывода
Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
Запустим скрипт так, чтобы вывод STDERR попадал в файл.
Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.
Сообщения об ошибках записываются в файл
▍Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec :
Перенаправление всего вывода в файл
Команду exec можно использовать не только в начале скрипта, но и в других местах:
Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.
Перенаправление вывода в разные файлы
Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:
Вот что появится на экране после запуска скрипта.
Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.
Создание собственного перенаправления вывода
Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.
Назначить дескриптор для вывода данных можно, используя команду exec :
Перенаправление вывода, используя собственный дескриптор
Создание дескрипторов файлов для ввода данных
Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.
После окончания чтения файла можно восстановить STDIN и пользоваться им как обычно:
Закрытие дескрипторов файлов
После исполнения скрипта мы получим сообщение об ошибке.
Попытка обращения к закрытому дескриптору файла
Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.
Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.
Получение сведений об открытых дескрипторах
У этой команды есть множество ключей, рассмотрим самые важные.
Вывод сведений об открытых дескрипторах
Посмотрим на вызов команды lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:
Вот что получится, если этот скрипт запустить.
Просмотр дескрипторов файлов, открытых скриптом
Скрипт открыл два дескриптора для вывода ( 3 и 6 ) и один — для ввода ( 7 ). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.
Подавление вывода
Вот, например, как подавить вывод сообщений об ошибках:
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
Итоги
Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.
В следующий раз поговорим о сигналах Linux, о том, как обрабатывать их в сценариях, о запуске заданий по расписанию и о фоновых задачах.
Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.
Глава 11. Внутренние команды
В общем случае, встроенные команды Bash, при исполнении внутри сценария, не порождают новый подпроцесс, в то время как вызов внешних команд, как правило, приводит к созданию нового подпроцесса.
Ввод/вывод
выводит (на stdout) выражение или содержимое переменной (см. Пример 4-1).
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() | Типичная конструкция цикла while с getopts несколько отличается от стандартной из-за отсутствия квадратных скобок, проверяющих условие продолжения цикла. Пример getopts, заменившей устаревшую, и не такую мощную, внешнюю команду getopt. Пример 11-17. Прием опций/аргументов, передаваемых сценарию, с помощью getopts Управление сценарием Пример 11-18. «Подключение» внешнего файла Файл data-file для Пример 11-18, представленного выше, должен находиться в том же каталоге. Сценарий может подключить даже самого себя, только этому едва ли можно найти какое либо практическое применение. Пример 11-19. Пример (бесполезный) сценария, который подключает себя самого. Безусловное завершение работы сценария. Команде exit можно передать целое число, которое будет возвращено вызывающему процессу как код завершения. Вообще, считается хорошей практикой завершать работу сценария, за исключением простейших случаев, командой exit 0, чтобы проинформировать родительский процесс об успешном завершении.
ПримечанияКак правило, исходные тексты подобных библиотек, на языке C, располагаются в каталоге /usr/share/doc/bash-. /functions. |






