Программирование для Linux. Профессиональный подход - страница 25
>ps
В опции >-o
через запятую указываются столбцы которые должны быть включены в вывод команды >ps
. Например, команда >ps -о pid,user,start_time,command
отображает идентификатор процесса, имя его владельца, время запуска а также команду, соответствующую процессу. Полный список опций и столбцов можно узнать на >man
-странице команды >ps
. Имеются три предопределенных формата вывода: >-f
(полный листинг), >-l
(длинный листинг) и >-j
(вывод заданий)
Ниже приведено несколько первых и последних строк, выдаваемых этой командой в нашей системе:
>% ps -e -о pid,ppid,command
>PID PPID COMMAND
> 1 0 init [5]
> 2 1 [kflushd]
> 3 1 [kupdate]
>...
>21725 21693 xterm
>21727 21725 bash
>21728 21727 ps -e -o pid,ppid,command
Заметьте: родительский идентификатор команды >ps
, 21727, соответствует интерпретатору >bash
, из которого была вызвана команда. В свою очередь, родительский идентификатор интерпретатора, 21725, принадлежит программе >xterm
— эмулятору терминала, в котором выполняется интерпретатор.
3.1.3. Уничтожение процесса
Для уничтожения процесса предназначена команда >kill
. Ей достаточно указать идентификатор требуемого процесса.
Команда >kill
посылает процессу сигнал >SIGTERM
, являющийся запросом на завершение.[10] По умолчанию, если в программе отсутствует обработчик данного сигнала, процесс просто завершает свою работу. О сигналах речь пойдет в разделе 3.3, "Сигналы".
3.2. Создание процессов
Существуют два способа создания процессов. Первый из них относительно прост, но применяется редко, поскольку неэффективен и связан со значительным риском для безопасности системы. Второй способ сложнее, но избавлен от недостатков первого.
3.2.1. Функция system()
Функция >system()
определена в стандартной библиотеке языка С и позволяет вызывать из программы системную команду, как если бы она была набрана в командной строке. По сути, эта функция запускает стандартный интерпретатор Bourne shell (>/bin/sh
) и передает ему команду на выполнение. Например, программа, представленная в листинге 3.2, вызывает команду >ls -l /
, отображающую содержимое корневого каталога.
>system()
>#include
>int main() {
> int return_value;
> return_value = system("ls -l /");
> return return_value;
>}
Функция >system()
возвращает код завершения указанной команды. Если интерпретатор не может быть запущен, возвращается значение 127, а в случае возникновения других ошибок — -1.
Поскольку функция >system()
запускает интерпретатор команд, она подвержена всем тем ограничениям безопасности, что и системный интерпретатор. Рассчитывать на наличие какой-то конкретной версии Bourne shell не приходится. В большинстве UNIX-систем программа >/bin/sh
представляет собой символическую ссылку на другой интерпретатор. В Linux — это >bash
(Bourne-Again SHell), причем в разных дистрибутивах присутствуют разные его версии. Вызов из функции >system()
программы с привилегиями пользователя >root
также может иметь неодинаковые последствия в разных системах. Таким образом, лучше создавать процессы с помощью функций >fork()
и >exec()
.
3.2.2. Функции fork() и exec()
В DOS и Windows API имеется семейство функций >spawn()
. Они принимают в качестве аргумента имя программы, создают новый экземпляр ее процесса и запускают его. В Linux нет функции, которая делала бы все это за один заход. Вместо этого имеется функция >fork()
, создающая дочерний процесс, который является точной копией родительского процесса, и семейство функций >exec()
, заставляющих требуемый процесс перестать быть экземпляром одной программы и превратиться в экземпляр другой программы. Чтобы создать новый процесс, нужно сначала с помощью функции >fork()
создать копню текущего процесса, а затем с помощью функции >exec()
преобразовать одну из копий в экземпляр запускаемой программы.
Вызывая функцию >fork()
, программа создает свой дубликат, называемый дочерним процессом. Родительский процесс продолжает выполнять программу с той точки, где была вызвана функция >fork()
. То же самое делает и дочерний процесс.
Как же различить между собой оба процесса? Во-первых, дочерний процесс — это новый, только что появившийся в системе процесс, поэтому его идентификатор отличается от идентификатора родительского процесса. Таким образом, программа может вызвать функцию