В комп’ютингу процесне заміщення - це форма взаємодії між процесами, яка дозволяє ввід та вивід представляти файлом. оболонка заміщує назву файлу викликом програми. Це дозволяє програмам, які зазвичай лише приймають файли, напряму читати або записувати результат в іншу програму.
Історія
Процесне заміщення було доступне для вибору при компіляції в ksh88
, KornShell[1] версії 1988 року. RC оболонка подає цю можливість як “розгалуження конвеєру” в Version 10 Unix, випущеній в 1990 році.[2] Bash shell запропонував таку можливість в версії 1.14 1994 року.[3]
Приклади
Наступні приклади використовують KornShell синаксис.
Команда diff в Unix зазвичай приймає назви двох файлів, які треба порівняти, або один файл і стандатний ввід. Процесне заміщення дозволяє порівнювати вивід двох програм напряму:
$ diff <(sort file1) <(sort file2)
Вираз <(command)
вказує командному інтерпретатору виконати command і вивести вихідні дані файлом. Command може бути будь-якою командою оболонки довільної складності.
Альтернатива цьому, не використовуючи заміщення, виглядає наступним чином:
- Зберегти вивід команди в тимчасовий файл, тоді його зчитати
$ sort file2 > /tmp/file2.sorted
$ sort file1 | diff - /tmp/file2.sorted
$ rm /tmp/file2.sorted
- Створити іменований канал (також відомий як FIFO)), розпочати одну команду, що вводить в нього дані, у фоновому режимі, тоді виконати іншу команду, вхідними даними для якої слугуватиме цей іменований канал.
$ mkfifo /tmp/sort2.fifo
$ sort file2 > /tmp/sort2.fifo &
$ sort file1 | diff - /tmp/sort2.fifo
$ rm /tmp/sort2.fifo
Обидві альтернативи є більш громіздкими. процесне заміщення можна також використовувати, щоб захопити вивід, який типово записувався би у файл, і перенаправити його на ввід іншому процесу. У оболонці Bash синтаксисом для запису в процес є >(команда). Ось приклад використання tee, wc та gzip команд, що рахують кількість стрічок у файлі командою wc -l
і стискає командою gzip
одним рядком:
$ tee >(wc -l >&2) < bigfile | gzip > bigfile.gz
Переваги
Основні переваги процесного заміщення над його альтернативою є:
- Простота: команди можна передавати вбудовано, немає потреби зберігати тимчасові файли і заздалегідь створювати іменовані канали.
- Продуктивність: читання безпосередньо з іншого процесу є часто швидшим, ніж запис тимчасового файлу на диск, а тоді зчитування його в потік наново.Це також економить пам’ять диску.
- Паралелізм: заміщений процес може виконуватись паралельно з командою, яка читає його вивід і передає дані на ввід, користуючись перевагами мультипроцесорності для зменшення загального часу компіляції.
Механізм роботи
Під капотом процесне заміщення має два шляхи виконання. В системах, що підтримують /dev/fd
(тобто більшість Unix-подібних систем) воно виконує системний виклик pipe()
, який повертає файловий дескриптор $fd
для неіменованого каналу, тоді створює рядок /dev/fd/$fd
і заміщує нею дані в командному рядку. В системах, де така директорія не підтримується, воно викликає mkfifo
з новою тимчасовою назвою файлу для створення іменованого каналу і заміщує дані в командному рядку цією назвою файлу. Для наочного прикладу наведених кроків, перегляньмо наступний приклад командного заміщення в системі, що підтримує/dev/fd
$ diff file1 <(sort file2)
Кроки, що виконує оболонка:
- Створити новий неіменований канал. До нього можна доступитися за
/dev/fd/63
або схожим шляхом. Перевірити можна командоюecho <(true)
.
- Виконати командне заміщення у фоновому режимі (в даному випадку це команда
sort file2
), направивши його вивід в неіменований канал.
- Виконати основну команду, замінюючи потрібну команду шляхом до неіменованого каналу. В цьому випадку повний вигляд команди буде приблизно наступним:
diff file1 /dev/fd/63
.
- Коли виконання завершено, закрити неіменований канал.
Для іменованих каналів виконання відрізняється лише створенням на видаленням каналу: mkfifo
для створення та unlink
для видалення. Усі інші аспекти залишаються незмінними
Обмеження
Створенні “файли” не відслідковуються, тобто процес, що виконує читання та запис до файлу не має безпосереднього доступу до нього, він повинен зчитати чи записати файл від початку до кінця з першого разу. Програми, що явно перевіряють тип файлу перед його відкриттям, можуть не працювати з процесним заміщенням, тому що “файл”, який є результатом процесного заміщення не є звичайним файлом. До того ж, аж до Bash 4.4 (2016 року випуску) отримати код виходу з програми, створений самою оболонкою, було неможливо.[4]
Див. також
Посилання