Глава 6.12. Процессы и сокеты

6.12.1. Функции управления процессами

Функция Описание
exec Передает управление заданной системной команде.
fork Запускает копию текущей программы.
kill Посылает сигнал завершения списку процессов.
pipe Создает канал межпроцессной коммуникации.
readpipe Выполняет системную команду.
sleep Приостановка работы программы.
system Запускает системную программу и ждет ее завершения.
umask Изменяет маску доступа к процессу.
wait Ожидает завершения процесса-потомка.
waitpid Ожидает завершения процесса с заданным PID.

Функция exec

Синтаксис: exec список
Аргументы: список — список строковых выражений

Функция exec вызывает заданную аргументами системную команду и передает ей управление. После выполнения этой команды управление в perl не возвращается; для вызова системных команд с возвратом управления нужно пользоваться функцией system. Возврат управления в perl происходит только в том случае, когда запрошенной команды не существует.

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

exec('echo ha-ha-ha') or print STDERR "Не могу выполнить echo: $!";

Функция fork

Синтаксис: fork
Результат: целое значение

В Unix функция fork создает новый процесс, который является копией текущего. Она возвращает PID дочернего процесса родительскому процессу, 0 дочернему процессу и undef, если вызов функции звкочился неудачей.

В Windows нет системной поддержки для создания копий процессов, поэтому данная функция эмулируется запуском нового интерпретатора perl в отдельном потоке. Это приводит к ряду несовместимостей с Unix, которые мы здесь не рассматриваем.

Функция kill

Синтаксис: kill сигнал, список
Аргументы: сигнал — числовое или строковое выражение
           список — список числовых выражений
Результат: целое значение

В Unix функция kill посылает заданный сигнал завершения процессам, чьи PID перечислены в списке, и возвращает количество процессов, отреагировавших на этот сигнал. Сигнал задается либо числовым идентификатором, либо именем в кавычках (имена сигналов и соответствующие числовые значения хранятся в глобальном массиве %SIG). Если сигнал является отрицательным числом, то он передается не процессам, а группам процессов. Если сигнал равен нулю, то никакого сигнала не посылается; такая форма функции позволяет проверить, что процесс с заданным PID существует.

В Windows нет сигналов, поэтому здесь данная функция имеет вид kill($sig, $pid) и вызывает немедленное завершение процесса с номером $pid, при этом статус завершения процесса равен $sig. Как и в Unix, если $sig равно нулю и заданный процесс существует, то функция вернет 1, не завершая процесс.

Функция pipe

Синтаксис: pipe ввод, вывод
Аргументы: ввод, вывод — описатели файлов

Функция pipe создает два взаимосвязанных конвейера, один на чтение из файла ввод, а второй на запись в файл вывод. Самостоятельно используется очень редко, см. документацию на PERL IPC (interprocess communication).

Функция readpipe

Синтаксис: readpipe выражение
Аргументы: выражение — строковое выражение
Результат: строка или массив строк

Функция readpipe вызывает системную команду, заданную выражением и возвращает все, что последняя выведет на стандартное устройство вывода (stdout). В скалярном контексте результат вывода возвращается как одна строка, в списочном контексте — как массив строк. Эта функция является внутренней для функции qx(), но может быть вызвана и непосредственно из программы.

Функция sleep

Синтаксис: sleep выражение?
Аргументы: выражение — числовое выражение
Результат: целое значение

Функция sleep вызывает приостановку работы сценария на количество секунд, заданных выражением, или навсегда, если выражение опущено. В Unix приостановка может быть прервана сигналом SIGALRM. Возвращает количество секунд, на которые сценарий был фактически приостановлен. Пример:

sleep 10; # подождать 10 секунд

Функция system

Синтаксис: system список
Аргументы: список — список строковых выражений
Результат: целое значение

Функция system полностью эквивалентна функции exec с одним отличием: указанная системная команда выполняется в дочернем процессе, и сценарий ждет ее завершения. Возвращает код завершения системной команды. Пример:

system('echo ha-ha-ha');

В Windows должна вызывается в формате system(1, @args), где @args состоит из имени запускаемой программы и ее аргументов.

Функция umask

Синтаксис: umask выражение?
Аргументы: выражение — числовое выражение
Результат: целое значение

Функция umask изменяет маску прав текущего процесса на новую, заданную выражением. Если выражение опущено, то возвращает маску прав текущего процесса. Структуру маски прав см. в описании функции chmod. В Windows игнорируется и всегда возвращает 0.

Функция wait

Синтаксис: wait
Результат: целое значение

Функция wait ждет завершения дочернего процесса и возвращает его PID или -1, если дочерних процессов нет. В Windows применима только к процессам, запущенных вызовом system(1, @args).

Функция waitpid

Синтаксис: waitpid pid, флаги
Аргументы: pid, флаги — числовые выражения
Результат: целое значение

Функция waitpid ждет завершения дочернего процесса с заданным pid и возвращает его PID или -1, если дочерних процессов нет. Допустимые значения параметра флаги зависят от операционной системы, но нулевое значение флагов поддерживается везде. В Windows применима только к процессам, запущенных вызовом system(1, @args).

6.12.2. Функции управления сокетами

Описанные в этом разделе функции выполняют базовые операции над сокетами. Сокет (socket) — это понятие, соответствующее временному соединению двух компьютеров сети, которые в этом случае принято называть хостами (hosts). Сокеты оказались удобной абстракцией для описания сетевых сессий, позволяющей программисту писать программы передачи данных по сети, не опускаясь на уровень сетевых и транспортных протоколов, поэтому они поддерживаются сегодня и в Unix, и в Windows, а также во многих современных языках программирования.

Работа с сокетами построена аналогично работе с файлами. Новый сокет открывается функцией socket, которая создает для него описатель файла, и закрывается функцией shutdown. Остальные операции с сокетами манипулируют с сетевыми адресами и именами, упакованными платформо-независимым образом, поэтому перед программированием сокетов следует ознакомиться с описанием модуля Socket, который содержит стандартные функции преобразования таких структур и символические имена различных констант.

Функция Описание
accept Создает новый сокет для сессии.
bind Связывает сокет с сетевым адресом.
connect Устанавливает связь с удаленным сокетом.
getpeername Возвращает адрес удаленного конца сокета.
getsockname Возвращает адрес локального конца сокета.
getsockopt Возвращает параметры сокета.
listen Запускает прослушивание заданного сокета.
recv Принимает сообщение от сокета.
send Посылает сообщение сокету.
setsockopt Задает параметры сокета.
shutdown Разрывает соединение сокета.
socket Создает новый сокет.

Функция accept

Синтаксис: accept новый, старый
Аргументы: новый, старый — описателb файлов
Результат: адрес сокета

Функция accept принимает входящее соединение от существующего сокета старый. В случае успешного соединения в параметр новый заносится описатель нового сокета и возвращается упакованный адрес соединения; в противном случае возвращается 0.

Функция bind

Синтаксис: bind сокет, имя
Аргументы: сокет — описатель файла
           имя — сетевой адрес
Результат: логическое значение

Функция connect связывает локальный сокет с сетевым адресом, заданным именем. Она возвращает истину при успешном соединении и ложь при неудаче. Имя должно содержать упакованный сетевой адрес; для его формирования проще всего использовать функции модуля Socket. Например, для прослушивания (случайно выбранного) порта 2345 по протоколу TCP мы можем написать:

use Socket;
$proto = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
bind(SOCK, sockaddr_in(2345, INADDR_ANY)) || die "bind: $!";
listen(SOCK, SOMAXCONN) || die "listen: $!";

Функция connect

Синтаксис: connect сокет, имя
Аргументы: сокет — описатель файла
           имя — адрес удаленного сокета
Результат: логическое значение

Функция connect пытается установить связь локального сокета с удаленным сокетом, заданным именем. Она возвращает истину при успешном соединении и ложь при неудаче. Имя должно содержать упакованный адрес удаленного сокета; для его формирования проще всего использовать функции модуля Socket. Например, для связи с удаленным сокетом на том же компьютере по протоколу TCP через (случайно выбранный) порт 2345 мы можем написать:

use Socket;
$iaddr = inet_aton('localhost') || die "no localhost";
$paddr = sockaddr_in(2345, $iaddr);
$proto = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
connect(SOCK, $paddr) || die "connect: $!";

Функция getpeername

Синтаксис: getpeername сокет
Аргументы: сокет — описатель файла
Результат: адрес сокета

Функция getpeername возвращает упакованный адрес удаленного конца соединения, заданого локальным сокетом. Если сокет не имеет соединения, то возникает фатальная ошибка. Для распаковки полученного адреса проще всего пользоваться функциями модуля Socket, например:

use Socket;
$remoteaddr = getpeername(SOCK);
($port, $iaddr) = sockaddr_in($remoteaddr);
$remotehostname = gethostbyaddr($iaddr, AF_INET); // имя удаленного хоста
$remoteaddr = inet_ntoa($iaddr); // строковый адрес удаленного хоста

Функция getsockname

Синтаксис: getsockname сокет
Аргументы: сокет — описатель файла
Результат: адрес сокета

Функция getsockname возвращает упакованный адрес локального конца соединения, заданого локальным сокетом. Если сокет не имеет соединения, то возникает фатальная ошибка. Для распаковки полученного адреса проще всего пользоваться функциями модуля Socket, например:

use Socket;
$mysockaddr = getsockname(SOCK);
($port, $iaddr) = sockaddr_in($mysockaddr);
$myhostname = gethostbyaddr($iaddr, AF_INET); // имя локального хоста
$myaddr = inet_ntoa($iaddr); // строковый адрес локального хоста

Функция getsockopt

Синтаксис: getsockopt сокет, уровень, имя
Аргументы: сокет — описатель файла
           уровень, имя — числовые выражения
Результат: строковое значение

Функция getsockopt возвращает текущее значение параметра имя данного сокета или undef при неудаче. Уровень определяет уровень абстракции, на котором данный параметр определен. Он может принимать значения, имеющие следующие символические имена из модуля Socket: SOL_SOCKET (уровень сокетов) и IPPROTO_TCP (уровень TCP/IP). Допустимые имена параметров и их значения зависят как от выбранного уровня, так и от операционной системы.

Функция listen

Синтаксис: listen сокет, очередь
Аргументы: сокет — описатель файла
           очередь — числовое значение
Результат: логическое значение

Функция listen переводит сокет в режим прослушивания установленного соединения. Она возвращает истину при успешном соединении и ложь при неудаче. Параметр очередь задает максимальный размер очереди отложенных соединений; если он равен SOMAXCONN, то он устанавливается максимально возможным для данного типа сокета. Пример см. в описании функции bind.

Функция recv

Синтаксис: recv сокет, буфер, длина, флаги
Аргументы: сокет — описатель файла
           буфер — скалярная переменная
           длина, флаги — числовые выражения
Результат: строковое значение

Функция recv принимает данные от указанного сокета. Делается попытка считать длину байтов в переменную буфер. Возвращается адрес удаленного сокета или пустая строка, если протокол сокета не поддерживает передачу этого адреса. При ошибке возвращается undef. Допустимые значения флагов зависят от операционной системы. Эта функция предназначена для приема датаграммных сообщений по протоколам типа UDP.

Функция send

Синтаксис: send сокет, сообщение, флаги, приемник?
Аргументы: сокет — описатель файла
           сообщение — текстовое выражение
           длина, флаги — числовые выражения
           приемник — адрес сокета
Результат: строковое значение

Функция send посылает сообщение удаленному сокету. Если локальный сокет не соединен с удаленным, то необходимо явно указать упакованный адрес приемника. Возвращается количество переданных символов; при ошибке возвращается undef. Допустимые значения флагов зависят от операционной системы. Эта функция предназначена для посылки датаграммных сообщений по протоколам типа UDP.

Функция setsockopt

Синтаксис: setsockopt сокет, уровень, имя, значение
Аргументы: сокет — описатель файла
           уровень, имя — числовые выражения
           значение — строковое выражение или undef
Результат: строковое значение

Функция setsockopt устанавливает новое значение параметра имя данного сокета. Уровень определяет уровень абстракции, на котором данный параметр определен. Он может принимать значения, имеющие следующие символические имена из модуля Socket: SOL_SOCKET (уровень сокетов) и IPPROTO_TCP (уровень TCP/IP). Допустимые имена параметров и их значения зависят как от выбранного уровня, так и от операционной системы.

Функция shutdown

Синтаксис: shutdown сокет, способ
Аргументы: сокет — описатель файла
           способ — числовое выражение

Функция shutdown закрывает соединение указанного сокета одним из следующих способов:

Способ Значение
0 Прекратить чтение данных.
1 Прекратить запись данных.
2 Прекратить использование данного сокета.

Функция socket

Синтаксис: socket сокет, домен, тип, протокол
Аргументы: сокет — описатель файла
           домен, тип, протокол — числовые выражения
Результат: целое значение

Функция socket создает новый сокет и заносит его описатель в сокет. Остальные аргументы определяют параметры создаваемого сокета. Для совместимости вместо числовых значений следует использовать их символические имена, доступные по директиве use Socket;. Аргумент домен задает спецификацию семейства адресов; его возможные значения зависят от операционной системы. Для связи по Интернету его значение должно быть равно PF_INET. Аргумент тип специфицирует тип сокета: SOCK_STREAM для связи по протоколу TCP и SOCK_DGRAM для связи по протоколу UDP. Наконец, аргумент протокол указывает конкретный протокол, который будет использоваться сокетом. Пример создания сокета для связи по протоколу TCP см. в описании функции connect.

6.12.3. Информационные функции

Функция Описание
gethostbyaddr Возвращает информацию о хосте, заданном адресом.
gethostbyname Возвращает информацию о хосте, заданном именем.
getlogin Возвращает имя пользователя.
getprotobyname Возвращает информацию о протоколе по его имени.
getprotobynumber Возвращает информацию о протоколе по его номеру.
getservbyname Возвращает информацию о сервисе по его имени.
getservbyport Возвращает информацию о сервисе по номеру порта.

Функция gethostbyaddr

Синтаксис: gethostbyaddr адрес, тип
Аргументы: адрес, тип — числовые выражения
Результат: массив значений

Функция gethostbyaddr возвращает информацию о хосте, заданном своим адресом. Аргумент тип задает спецификацию семейства адресов; его возможные значения зависят от операционной системы. Для связи по Интернету его значение должно быть равно AF_INET (символическое имя, доступное по директиве use Socket;). Возвращаемый массив устроен так:

Номер элемента Описание
0 Официальное имя хоста.
1 Альтернативные имена хоста.
2 Тип адреса.
3 Длина адреса в байтах.
4 Массив упакованных адресов.

В скалярном контексте возвращается официальное имя хоста. Следующий пример:

use Socket;
$iaddr = inet_aton("127.0.0.1");
($name, $aliases, $addrtype, $length, @addrs) = gethostbyaddr($iaddr, AF_INET);
$straddr = inet_ntoa($addrs[0]);
print "$name $straddr\n";

выведет на экран имя и IP-адрес локального хоста: localhost 127.0.0.1.

Функция gethostbyname

Синтаксис: gethostbyname имя
Аргументы: имя — строковое выражение
Результат: массив значений

Функция gethostbyname возвращает информацию о хосте, заданном своим именем. В скалярном контексте возвращается упакованный адрес хоста, а в списочном — такой же массив, как в функции gethostbyaddr. Следующий пример:

use Socket;
($name, $aliases, $addrtype, $length, @addrs) = gethostbyname('localhost');
$straddr = inet_ntoa($addrs[0]);
print "$name $straddr\n";

выведет на экран имя и IP-адрес локального хоста: localhost 127.0.0.1.

Функция getlogin

Синтаксис: getlogin
Результат: строковое значение

Функция getlogin возвращает имя текущего пользователя. В Unix лучше пользоваться функцией getpwuid($<).

Функция getprotobyname

Синтаксис: getprotobyname имя
Аргументы: имя — строковое выражение
Результат: массив значений

Функция getprotobyname возвращает информацию о протоколе, заданном своим именем. Возвращаемый массив устроен так:

Номер элемента Описание
0 Официальное название протокола.
1 Альтернативные названия протокола.
2 Номер протокола.

В скалярном контексте возвращается номер протокола. Следующий пример:

($name, $aliases, $proto) = getprotobyname('tcp');
print "$name $proto\n";

выведет на экран строку: tcp 6.

Функция getprotobynumber

Синтаксис: getprotobynumber номер
Аргументы: номер — числовое выражение
Результат: массив значений

Функция getprotobynumber возвращает информацию о протоколе, заданном своим номером. В скалярном контексте возвращается официальное имя протокола, а в списочном — такой же массив, как в функции getprotobyname. Следующий пример:

($name, $aliases, $proto) = getprotobynumber(6);
print "$name $proto\n";

выведет на экран строку: tcp 6.

Функция getservbyname

Синтаксис: getservbyname имя, протокол
Аргументы: имя, протокол — строковые выражения
Результат: массив значений

Функция getservbyname возвращает информацию о сервисе, заданном именем и протоколом. Возвращаемый массив устроен так:

Номер элемента Описание
0 Официальное название сервиса.
1 Альтернативные имена сервиса.
2 Номер порта.
3 Название протокола.

В скалярном контексте возвращается номер порта. Следующий пример:

$port = getservbyname('smtp', 'tcp');
print "$port\n";

выведет на экран номер порта 25.

Функция getservbyport

Синтаксис: getservbyport порт, протокол
Аргументы: порт — числовое выражение
           протокол — строковое выражение
Результат: массив значений

Функция getservbyport возвращает информацию о сервисе, заданном номером порта и протоколом. В скалярном контексте возвращается официальное название сервиса, а в списочном — такой же массив, как в функции getservbyname. Следующий пример:

$name = getservbyport(25, 'tcp');
print "$name\n";

выведет на экран строку smtp.