Канали - загальні відомості
Програмний канал в Unix/Linux являє собою один із засобів
взаємодії між процесами. Сама назва (pipe, дослівно - трубка)
досить точно передає сенс функціонування цього кошти. Канал
подібний трубопроводу, прокладеному між двома процесами, і з цього
трубопроводу процеси можуть пересилати один одному дані. Подібно
трубопроводу, канал має власну ємність, дані, спрямовані на канал
процесом-відправником, не обов'язково повинні бути негайно прочитані
процесом-одержувачем, але можуть накопичуватися в каналі. Як і у
трубопроводу, ємність каналу кінцева, коли вона буде вичерпана, запис у
канал стає неможливим.
Операційні системи Unix/Linux представляеют в розпорядження програмістів
два види каналів - іменовані і неименованные. Робота з обома видами під
чому подібна до роботи з файлами.
Неименованные канали
Неіменовані канал є засобом взаємодії між пов'язаними
процесами - батьківським і дочірнім. Батьківський процес створює канал
за допомогою системного виклику:
int pipe(int fd[2]);
Масив з двох цілих чисел є вихідним параметром цього системного
виклику. Якщо виклик виконався нормально, то цей масив містить два
файлових дескриптора. fd[0] є дескриптором для читання
з каналу, fd[1] - дескриптором для запису у канал. Коли
процес породжує інший процес, дескриптори батьківського процесу
успадковуються дочірнім процесом, і, таким чином, прокладається
трубопровід між двома процесами. Природно, що один з процесів
використовує канал лише для читання, а інший - тільки для запису (самі
уявіть собі, що станеться, якщо це правило буде порушуватися).
Тому, якщо, наприклад, через канал повинні передаватися дані з
батьківського процесу в дочірній, батьківський процес відразу після
запуску дочірнього процесу закриває дескриптор каналу для читання, а
дочірній процес закриває дескриптор для запису. Якщо потрібен
двосторонній обмін даними між процесами, то батьківський процес
створює два канали, один з яких використовується для передачі даних до
одну сторону, а інший - в іншу. Після отримання процесами дескрипторів
каналу для роботи з каналом використовуються файлові системні виклики:
int read(int pipe_fd, void *area, int cnt);
int write(int pipe_fd, void *area, int cnt);
Перший аргумент цих викликів - дескриптор каналу, другий - вказівник на
область пам'яті, з якої відбувається обмін, третій - кількість байт. Обидва
виклику повертають кількість переданих байт (або -1 - при помилку).
Виконання цих системних викликів може переводити процес в стан
очікування. Це відбувається, якщо процес намагається читати дані з пустого
каналу або писати дані в переповнений канал. Процес виходить з
очікування, коли в каналі з'являються дані або коли в каналі з'являється
вільне місце, відповідно.
При завершенні використання каналу процес виконує системний виклик:
int close(int pipe_fd);
Якщо батьківський процес, який створив канал, породжує кілька дочірніх
процесів, то всі дочірні процеси підключені до іншого кінця каналу.
Якщо, наприклад, батьківський процес виводить дані в канал, то вони
"дістануться" дочірній процес, який раніше виконає системний
виклик read.
Приклад виконання наведено тут.
Довідковий матеріал
Обрані системні виклики Linux/Unix. Короткий опис.
Довідник бібліотечних функція мови З: частина 1,
частина 2 (кодування кирилиця ibm866).