Неименованные каналы используются для обмена информацией между родственными процессами (родитель и любые его потомки). С одного конца в канал можно только записывать информацию, а с другого конца - только читать.
Между "обычными" файлами и неименованными каналами существует ряд различий:
При порождении дочерних процессов файловые дескрипторы наследуются - это позволяет дочерним процессам взаимодействовать как с родительским процессом, так и между собой.
Данные в канале организованы по принципу FIFO - информация, которая первой записана в канал, будет первой прочитана из канала.
Неименованные каналы широко используются в операционной системe. Например, командный интерпретатор использует их для организации конвейерной обработки.
$ cat /var/log/apt/term.log | wc
32 243 2354
Утилита cat читает текстовый файл term.log и передает последовательный поток символов программе wc, которая подсчитывает число строк, слов и символов в файле.
Утилита архивирования tar использует неименованные каналы для упаковки архивов "на лету" при помощи "внешних" упаковщиков.
$ strace -fe pipe,execve tar cJf ./50GB.zip .
execve("/bin/tar", ["tar", "cJf", "./50GB.zip", "."], 0x7fffd3f85858 /* 70 vars */) = 0
pipe([3, 4]) = 0
strace: Process 15323 attached
[pid 15323] execve("/bin/sh", ["/bin/sh", "-c", "xz"], 0x7ffcf642f850 /* 70 vars */) = 0
strace: Process 15324 attached
[pid 15324] execve("/usr/bin/xz", ["xz"], 0x56374b062148 /* 70 vars */) = 0
[pid 15324] pipe([3, 4]) = 0
^Z
[1]+ Stopped strace -fe pipe,execve tar cJf ./50GB.zip .
В показанном выше примере с помощью strace отслеживается системный вызов pipe, при помощи которого tar создает неименованный канал для связи с упаковщиком xz в дочернем процессе. Затем группа процессов архиватора приостанавливается с помощью SIGTSTP (^Z).
29031 pts/4 Ss 0:00 | | \_ /bin/bash
15320 pts/4 T 0:00 | | | \_ strace -fe pipe,execve tar cJf ./50GB.zip .
15322 pts/4 t 0:00 | | | | \_ tar cJf ./50GB.zip .
15323 pts/4 t 0:00 | | | | \_ /bin/sh -c xz
15324 pts/4 t 0:02 | | | | \_ xz
15349 pts/4 R+ 0:00 | | | \_ ps f
С помощью команды lsof показаны файловые дескрипторы открытых файлов обоих процессов.
$ lsof -p 15322
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
tar 15322 agr 4w FIFO 0,12 0t0 2518136 pipe
$ lsof -p 15324
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
xz 15324 agr 0r FIFO 0,12 0t0 2518136 pipe
Важно отметить, что в процессе архиватора PID=15322 файловый дескриптор передающей части канала сохранил свой номер, а в дочернем процессе упаковщика PID = 15324 файловый дескриптор принимающей части канала был перенаплавлен в STDIN, как того и ожидает упаковщик xz.
Между "обычными" файлами и неименованными каналами существует ряд различий:
- Прочитанная информация немедленно удаляется из канала и становится недоступна для повторного чтения
- При создании файла - создается один файловый дескриптор, при создании канала создаются два дескриптора - для передачи (записи) в канал и для приема (чтения) из канала.
При порождении дочерних процессов файловые дескрипторы наследуются - это позволяет дочерним процессам взаимодействовать как с родительским процессом, так и между собой.
Данные в канале организованы по принципу FIFO - информация, которая первой записана в канал, будет первой прочитана из канала.
Неименованные каналы широко используются в операционной системe. Например, командный интерпретатор использует их для организации конвейерной обработки.
$ cat /var/log/apt/term.log | wc
32 243 2354
Утилита cat читает текстовый файл term.log и передает последовательный поток символов программе wc, которая подсчитывает число строк, слов и символов в файле.
Утилита архивирования tar использует неименованные каналы для упаковки архивов "на лету" при помощи "внешних" упаковщиков.
$ strace -fe pipe,execve tar cJf ./50GB.zip .
execve("/bin/tar", ["tar", "cJf", "./50GB.zip", "."], 0x7fffd3f85858 /* 70 vars */) = 0
pipe([3, 4]) = 0
strace: Process 15323 attached
[pid 15323] execve("/bin/sh", ["/bin/sh", "-c", "xz"], 0x7ffcf642f850 /* 70 vars */) = 0
strace: Process 15324 attached
[pid 15324] execve("/usr/bin/xz", ["xz"], 0x56374b062148 /* 70 vars */) = 0
[pid 15324] pipe([3, 4]) = 0
^Z
[1]+ Stopped strace -fe pipe,execve tar cJf ./50GB.zip .
В показанном выше примере с помощью strace отслеживается системный вызов pipe, при помощи которого tar создает неименованный канал для связи с упаковщиком xz в дочернем процессе. Затем группа процессов архиватора приостанавливается с помощью SIGTSTP (^Z).
29031 pts/4 Ss 0:00 | | \_ /bin/bash
15320 pts/4 T 0:00 | | | \_ strace -fe pipe,execve tar cJf ./50GB.zip .
15322 pts/4 t 0:00 | | | | \_ tar cJf ./50GB.zip .
15323 pts/4 t 0:00 | | | | \_ /bin/sh -c xz
15324 pts/4 t 0:02 | | | | \_ xz
15349 pts/4 R+ 0:00 | | | \_ ps f
С помощью команды lsof показаны файловые дескрипторы открытых файлов обоих процессов.
$ lsof -p 15322
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
tar 15322 agr 4w FIFO 0,12 0t0 2518136 pipe
$ lsof -p 15324
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
xz 15324 agr 0r FIFO 0,12 0t0 2518136 pipe
Важно отметить, что в процессе архиватора PID=15322 файловый дескриптор передающей части канала сохранил свой номер, а в дочернем процессе упаковщика PID = 15324 файловый дескриптор принимающей части канала был перенаплавлен в STDIN, как того и ожидает упаковщик xz.
Комментарии
Отправить комментарий