Кроме сигналов, которые могут использоваться как простейшие средства межпроцессного взаимодействия (IPC, inter-process communication), для эффективного обмена информацией между процессами используются каналы, сокеты, очереди сообщений и разделяемая память, а для синхронизации действий процессов над совместно используемыми объектами — семафоры.
Самым простым средством обмена информацией между родственными процессами (родитель и любые его потомки) являются неименованные каналы. Канал является «двусторонним однонаправленным безымянным файлом», с одного конца в который можно только записывать информацию, а с другого конца — только считывать.
В отличие от «обычного» файла, при открытии которого создается только один файловый дескриптор (и для чтения, и для записи файла), при создании канала создаются сразу два дескриптора — один для передачи (записи) в канал, а другой — для приема (чтения) из канала.
При порождении дочерних процессов файловые дескрипторы наследуются, что и позволяет им взаимодействовать как с родительским процессом, так и между собой.
Использование неименованных каналов в системе широко распространено. Например, командный интерпретатор использует их для организации конвейерной обработки.
Архиватор tar использует, каналы аналогичным способом — для упаковки архивов «на лету» при помощи «внешних» упаковщиков.
В примере из листинга ниже посредством трассировщика strace отслеживается, системный вызов pipe, при помощи которого tar создает неименованный канал для связи с упаковщиком xz в дочернем процессе. Вся группа процессов архиватора tar приостановлена сигналом AZ SIGTSTP, после чего при помощи команды lsof показаны файловые дескрипторы открытых файлов обоих процессов.
Неименованные каналы
fitz@ubuntu:~$ strace -fe ptpe,execve tar cJf /tnp/docs.tgz /usr/share/doc
plpe([3, 4]) = 0
Process 3967 attached
tar: Удаляется начальный ‘/’ из имен объектов
[pid 3967] execve(«/usr/bin/xz», [«xz»), [/* 43 vars */]) = 0
^Z
[1]+ Остановлено strace -fe pipe tar cJf /tmp/docs.tgz /usr/share/doc
fitz@ubuntu:~$ ps f
PID TTY STAT TIME COMMAND
5472 pts/2 Ss 0:07 bash
3965 pts/2 T 0:00 \_ strace -fe pipe tar cJf /tmp/docs.tgz /usr/share/doc
3966 pts/2 t 0:00 | \_ tar cJf /tmp/docs.tgz /usr/share/doc
3967 pts/2 t 0:01 | \- xz
3968 pts/2 R+ 0:00 \_ ps f
fitz@ubuntu:~$ lsof -p 3966
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
tar 3966 fitz cwd DIR 252,0 69632 20316162 /home/fitz
tar 3966 fitz rtd DIR 252,0 4096 2 /
tar 3966 fitz txt REG 252,0 305968 7208993 /bin/tar
tar 3966 fitz 0u CHR 136,2 0t0 5 /dev/pts/2
tar 3966 fitz 1u CHR 136,2 0t0 5 /dev/pts/2
tar 3966 fitz 2u CHR 136,2 0t0 5 /dev/pts/2
tar 3966 fitz 3r DIR 252,0 106496 3801096 /usr/share/doc
tar 3966 fitz 4w FIFO 0,8 0t0 13S8926 pipe
fltz@ubuntu:~$ lsof -p 3967
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xz 3967 fitz cwd DIR 252,0 69632 20316162 /home/fitz
xz 3967 fitz rtd DIR 252,0 4096 2 /
xz 3967 fitz txt REG 252,0 67460 3802386 /usr/bin/xz
xz 3967 fitz 0r FIFO 0,8 0t0 1358926 pipe
xz 3967 fitz 1w REG 252,0 1466368 26874966 /tmp/docs.tgz
xz 3967 fitz 2u CHR 136,2 0t0 5 /dev/pts/2
Нужно отметить, что в процессе архиватора PID=3966 файловый дескриптор передающей части канала сохранил свой номер, а в дочернем процессе упаковщика PID = 3967 файловый дескриптор принимающей части канала был перенаправлен на STDIN, как того и ожидает упаковщик xz.