Як зрозуміти труби


21

Коли я просто використовував трубу в баші, я більше про це не думав. Але коли я читаю якийсь приклад коду С, використовуючи системну трубну виклик () разом з fork (), мені цікаво, як зрозуміти труби, включаючи як анонімні, так і названі труби.

Часто чути, що "все в Linux / Unix - це файл". Цікаво, чи справді труба є файлом, так що одна частина, яку вона з'єднує, записує у файл труби, а інша частина читає з файлу труби? Якщо так, то де створюється файл труби для анонімної труби? В / tmp, / dev, або ...?

Однак із прикладів іменованих труб я також дізнався, що використання труб має перевагу в просторі та часі у порівнянні з явним використанням тимчасових файлів, ймовірно, тому, що в реалізації труб немає файлів. Також труби, здається, не зберігають дані, як це роблять файли. Тож я сумніваюся, що труба - це фактично файл.

Відповіді:


23

Щодо вашого питання про продуктивність, труби ефективніші, ніж файли, оскільки не потрібен IO диска. Це cmd1 | cmd2є більш ефективним, ніж cmd1 > tmpfile; cmd2 < tmpfile(це може бути неправдою, якщо tmpfileвін підтримується на диску RAM або іншому пристрої пам'яті, як названа труба; але якщо це ім'я з ім'ям, його cmd1слід запускати у фоновому режимі, оскільки його вихід може блокуватися, якщо труба стає повною ). Якщо вам потрібен результат cmd1і вам все ще потрібно надіслати його вихід cmd2, ви повинні cmd1 | tee tmpfile | cmd2дозволити cmd1і cmd2паралельно запускати, уникаючи операцій з читання диска з cmd2.

Названі труби корисні, якщо багато процесів читають / записують в одну трубу. Вони також можуть бути корисними, коли програма не призначена для використання stdin / stdout для своєї IO, яка потребує використання файлів . Я розміщую файли курсивом, тому що названі труби не є саме файлами в точку зору зберігання, оскільки вони перебувають у пам'яті та мають фіксований розмір буфера, навіть якщо вони мають запис у файловій системі (для довідки). Інші речі в UNIX містять записи файлової системи, не будучи файлами: просто подумайте про /dev/nullінші записи в /devабо /proc.

Оскільки труби (названі та безіменні) мають фіксований розмір буфера, операції читання / запису для них можуть блокуватися, внаслідок чого процес читання / запису переходить у стан IOWait. Крім того, коли ви отримуєте EOF під час читання з буфера пам'яті? Правила такої поведінки чітко визначені і їх можна знайти у чоловіка.

Одне, що ви не можете зробити з трубами (названими та безіменними), - це пошук даних. Оскільки вони реалізовані за допомогою буфера пам'яті, це зрозуміло.

Про "everything in Linux/Unix is a file", я не згоден. Названі труби мають записи файлової системи, але не є точно файловими. У безіменних трубах немає записів файлової системи (крім, можливо, в /proc). Однак більшість операцій вводу-виводу в UNIX виконуються за допомогою функції читання / запису, для якої потрібен дескриптор файлу , включаючи неназвану трубку (і socket). Я не думаю, що ми можемо це сказати "everything in Linux/Unix is a file", але ми можемо це точно сказати "most IO in Linux/Unix is done using a file descriptor".


Спасибі! Чи дві команди, з'єднані трубою, паралельно працює, замість того, щоб друга починала виконуватись після першого закінчення?
Тім

Так, 2 команди виконуються паралельно. Якби їх не було і першого виводу більше, ніж буфера, він би був заблокований. Ви можете спробувати його, запустивши cmd1 > fifoі cmd2 < fifoв 2 -х різних оболонках, створюючи іменований канал з mkfifo fifo.
jfg956

Ще одне випробування, яке ви можете зробити, - це вбити, cmd2поки cmd1він ще працює: cmd1напевно, перестане повідомляти про поломку труби.
jfg956

Спасибі! що ви хотіли б заблокувати? Якщо це станеться, чи означає, що дата в потоці після блоку буде втрачена?
Тім

2
Дані не втрачаються. Якщо буфер труб заповнений, cmd1запис у трубу повернеться лише тоді, коли cmd2будуть прочитані дані з труби. Таким же чином, cmd2зчитування з труби буде заблоковано, якщо буфер порожній, поки не cmd1запише в трубу.
jfg956

4

Двома основними основами філософії UNIX є

  1. Зробити невеликі програми, які добре роблять одне.
  2. і очікуємо, що вихід кожної програми стане входом до іншої,
    поки невідомої програми.

    Використання труб дозволяє використовувати ефекти цих двох
    основ дизайну для створення надзвичайно потужних ланцюгів команд для досягнення бажаного результату.

    Більшість програм командного рядка, які працюють над файлами, також можуть приймати введення стандартного вводу (введення через клавіатуру) та вихід у стандартне виведення (друк на
    екрані).

    Деякі команди призначені для роботи тільки в трубі, не можуть працювати безпосередньо з файлами.

    наприклад trкоманда

  ls -C | tr 'a-z' 'A-Z'
    cmd1 | cmd2
  • Надсилає STDOUT cmd1 до STDIN cmd2 замість екрана.

  • STDERR не передається через труби.

    Коротше кажучи, Pipes is character (|)можна підключати команди.

    Будь-яка команда, яка пише в STDOUT, може бути використана в лівій частині труби.

       ls - /etc | less 

    Будь-яка команда, що читає з STDIN, може бути використана в правій частині труби.

       echo "test print" | lpr 

    Традиційна труба "безіменна", оскільки вона існує анонімно та зберігається лише до тих пір, поки процес триває. Названа труба є стійкою до системи та існує поза терміном експлуатації, і її потрібно видалити, коли вона більше не використовується. Процеси, як правило, приєднуються до названої труби (зазвичай з'являється у вигляді файлу) для здійснення міжпроцесорного зв'язку (IPC).

джерело: http://en.wikipedia.org/wiki/Named_pipe


3

Щоб доповнити інші відповіді ...

stdin і stdout - це дескриптори файлів і читаються і записуються так, ніби вони є файлами. отже, ви можете зробити це echo hi | grep hi, і він замінить stdout відлуння трубкою і замінить stdin grep на інший кінець цієї труби.


1

Все - файл.

Якщо ми сприймемо цю фразу занадто буквально, ми б закінчилися значенням "у нас є лише файли, і більше нічого". Це не правильне тлумачення, так що є.

Коли ми кажемо «Все - це файл», ми не кажемо, що все зберігається на диску. Ми говоримо, що все схоже на файл, його можна прочитати, можна записати.

У Unix, коли файл або не-файл відкритий, він може трактуватися як файл. Однак не всі файли підтримують усі операції. Наприклад, деякі файли (це не файли), не підтримують пошук: вони повинні читатись / записуватися послідовно (це стосується труб та сокетів).

Все має ім'я файлу (у деяких системах: наприклад, Debian Gnu / Linux та багато інших Gnu / Linux).

  • Усі відкриті файли отримують ім’я файлу. Побачити/proc/self/fd/…
  • Мережеві розетки можуть бути відкриті за допомогою файлу см , /dev/tcp
    наприклад ,cat </dev/tcp/towel.blinkenlights.nl/23

Ця остання частина дійсна лише в системах з /procфайловою системою та системах (або оболонках), що забезпечують /dev/tcpструктуру файлів.
Кусалаланда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.