, используемое в качестве дескриптора динамической библиотеки. Это значение можно передавать функции
dlsym
, которая возвращает адрес функции, загружаемой из библиотеки. Например, если в библиотеке
libtest.so
определена функция
my_function
, то она вызывается следующим образом:
void* handle = dlopen("libtest.so", RTLD_LAZY);
void (*test) = dlsym(handle, "my_function");
(*test);
dlclose(handle);
С помощью функции
dlsym
можно также получить указатель на статическую переменную, содержащуюся в совместно используемой библиотеке.
Обе функции,
dlopen
и
dlsym
, в случае неудачного завершения возвращают
NULL
. В данной ситуации можно вызвать функцию
dlerror
(без параметров), чтобы получить текстовое описание возникшей ошибки.
Функция
dlclose
выгружает совместно используемую библиотеку. Строго говоря, функция
dlopen
загружает библиотеку лишь в том случае, если она еще не находится в памяти. В противном случае просто увеличивается число ссылок на файл. Аналогичным образом функция
dlclose
сначала уменьшает счетчик ссылок, и только если он становится равным нулю, выгружает библиотеку.
Когда совместно используемая библиотека пишется на C++, имеет смысл объявлять общедоступные функции со спецификатором
extern "С"
. Например, если функция
my_function
написана на C++ и находится в совместно используемой библиотеке, а нужно обеспечить доступ к ней с помощью функции
dlsym
, объявите ее следующим образом:
extern "С" void my_function;
Тем самым компилятору C++ будет запрещено подменять имя функции. При отсутствии спецификатора
extern "С"
компилятор подставит вместо имени
my_function
совершенно другое имя, в котором закодирована информация о данной функции. Компилятор языка С не заменяет имена; он работает с теми именами, которые назначены пользователем.
Глава 3
Процессы
Выполняющийся экземпляр программы называется процессом. Если на экране отображаются два терминальных окна, то, скорее всего, одна и та же терминальная программа запущена дважды — ей просто соответствуют два процесса. В каждом окне, очевидно, работает интерпретатор команд — это еще один процесс. Когда пользователь вводит команду в интерпретаторе, соответствующая ей программа запускается в виде процесса. По завершении работы программы управление вновь передается процессу интерпретатора.
Опытные программисты часто создают несколько взаимодействующих процессов в рамках одного приложения, чтобы оно могло выполнять группу действий одновременно. Это повышает надежность приложения и позволяет ему использовать уже написанные программы.
Большинство описанных в данной главе функций управления процессами доступно и в других UNIX-системах. В основном они объявлены в файле
<unistd.h>
, но не помешает проверить это в документации.
3.1. Знакомство с процессами
Пользователю достаточно войти в систему, чтобы в ней начали выполняться процессы. Даже если пользователь ничего не запускает, а просто сидит перед экраном и пьет кофе. в системе все равно "теплится жизнь". Любой выполняющейся программе соответствует один или несколько процессов. Давайте для начала познакомимся с теми из них, которые присутствуют по умолчанию.
3.1.1. Идентификаторы процессов
Каждый процесс в Linux помечается уникальным идентификатором (PID, process identifier). Идентификаторы — это 16-разрядные числа, назначаемые последовательно по мере создания процессов.
У всякого процесса имеется также родительский процесс (за исключением специального демона
init
, о котором рассказывается
в разделе 3.4.3, "Процессы-зомби"). Таким образом, все процессы Linux организованы в виде древовидной иерархии, на вершине которой находится процесс
init
. К атрибутам процесса относится идентификатор его предка (PPID, parent process identifier).
Работая с идентификаторами процессов в программах, написанных на языках С и C++, следует объявлять соответствующие переменные как имеющие тип
pid_t
(определен в файле
<sys/types.h>
). Программа может узнать идентификатор своего собственного процесса с помощью системного вызова
getpid
, а идентификатор своего родительского процесса — с помощью вызова
getppid
. В листинге 3.1 показано, как это сделать.
Листинг 3.1. (print-pid.c) Вывод идентификатора процесса
#include <stdio.h>
#include <unistd.h>
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
отображает идентификатор процесса, имя его владельца, время запуска а также команду, соответствующую процессу. Полный список опций и столбцов можно узнать на