Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
3.1.1. Идентификаторы процессов
Каждый процесс в Linux помечается уникальным идентификатором (PID, process identifier). Идентификаторы — это 16-разрядные числа, назначаемые последовательно по мере создания процессов.
У всякого процесса имеется также родительский процесс (за исключением специального демона init
, о котором рассказывается в разделе 3.4.3, "Процессы-зомби"). Таким образом, все процессы Linux организованы в виде древовидной иерархии, на вершине которой находится процесс init
. К атрибутам процесса относится идентификатор его предка (PPID, parent process identifier).
Работая с идентификаторами процессов в программах, написанных на языках С и C++, следует объявлять соответствующие переменные как имеющие тип pid_t
(определен в файле ). Программа может узнать идентификатор своего собственного процесса с помощью системного вызова getpid()
, а идентификатор своего родительского процесса — с помощью вызова getppid()
. В листинге 3.1 показано, как это сделать.
#include
#include
int main() {
printf("The process ID is %d\n", (int)getpid());
printf("The parent process ID is %d\n", (int)getppid());
return 0;
}
Обратите внимание на важную особенность: при каждом вызове программа сообщает о разных идентификаторах, поскольку всякий раз запускается новый процесс. Тем не менее, если программа вызывается из одного и того же интерпретатора команд, то родительский идентификатор оказывается одинаковым.
3.1.2. Получение списка активных процессов
Команда ps
отображает список процессов, работающих в данный момент в системе. Версия этой команды в GNU/Linux имеет множество опций, так как пытается быть совместимой со своими "родственниками" в других UNIX-системах. С помощью опций можно указывать, о каких процессах и какую именно требуется получить информацию.
Будучи вызванной без аргументов, команда ps выводит список тех процессов, управляющим терминалом которых является ее собственный терминал:
% ps
PID TTY TIME CMD
21693 pts/8 00:00:00 bash
21694 pts/8 00:00:00 ps
В данном случае мы видим два процесса. Первый из них. bash
, — это интерпретатор команд, запущенный на данном терминале. Второй — выполняющийся экземпляр самой команды ps
. В самом левом столбце, PID, отображаются идентификаторы процессов.
Более полный список можно получить с помощью следующей команды:
% ps -е -о pid,ppid,command
Опция -е
заставляет команду ps отображать все процессы, выполняющиеся в системе. Опция -о pid,ppid,command
сообщает о том, какая информация о процессе нас интересует. В данном случае это идентификатор самого процесса, идентификатор его родительского процесса и команда, посредством которой был запущен процесс.
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] Команда kill позволяет посылать процессам и другие сигналы. Об этом рассказывается в разделе 3.4, "Завершение процесса".
По умолчанию, если в программе отсутствует обработчик данного сигнала, процесс просто завершает свою работу. О сигналах речь пойдет в разделе 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()
преобразовать одну из копий в экземпляр запускаемой программы.
Интервал:
Закладка: