Тръби Софтуерни канали в Linux

Съдържание

Предговор

В една остроумна статия прочетох следната максима: "Да лишиш привърженик на Unix от софтуерни канали е същото като да отнемеш мишка от потребител на Windows." Може би има известно преувеличение в това твърдение, но в старите времена като цяло беше вярно. Опитните Unixians обичат конзолата и знаят как да я използват. Ние, сегашните, инсталирали Убунту, вече се смятаме за линуксоиди, а какво е конзола, имаме бегла представа. Но минава известно време и, уморени от декорирането на работния плот, след като прочетохме две или три статии, решаваме да щракнем с мишката върху иконата на монитора в системната област. С течение на времето пред нас се разкрива нов свят, пълен с невероятни възможности и непрекъснато усъвършенстване на знанията ни, светът на празника на интелекта, продължаващия експеримент и радостта да бъдеш Хомо Сапиенс. Мотото: „Да върнем радостта от общуването с компютъра!“ - е най-подходящо за този повод.

Избор на термин

Терминът тръба (тръба) е изключително органично вписан в англоезичния компютърен жаргон. Тази дума се отнася не само до метода за прехвърляне на изхода на една команда към входа на друга, но също така и оператора, който обозначава това действие: (вертикална лента). Освен това същата дума служи като глагол, означаващ дадено действие.

Какви термини не се използват на български език за превод на думата "тръби": тръби, тръбопроводи, конвейери, потоци и др. В контекста всички тези термини изглеждат доста тромави. И тук е проблемът - нито едно от тези съществителни не може да образува глагол, да не говорим за наричането на символа на вертикалната лента по този начин. Вярно е, че можете да използвате глагола "тръбопровод", но това не е такаписането е невъзможно. Опитах се да очертая тази статия, като използвам всички изброени термини, но не съм доволен от нито един.

Съвсем случайно в книгата на А. Робачевски "Операционната система UNIX" попаднах на термина "софтуерни канали". Първоначално ми се стори малко тромаво, но след като го изпробвах на практика, се убедих в безспорните му предимства. Не изглежда смешно и диво като „тръби“, лесно се прави глагол от него и най-важното – има брат, пуснал корени в българската почва – „наименувани канали“, които никой няма да нарече „наименувани тръбопроводи“. И така, беше решено в тази статия терминът тръби да звучи като "софтуерни канали".

Въведение в програмните канали

Програмен канал е използването на изхода на една команда като вход към друга програма. Например:

Командата dmesg показва съобщения на ядрото на Linux относно процеса на зареждане на ОС (същите, които се показват на екрана на монитора, когато системата се зарежда). Тези съобщения не се побират на един екран и прелитат толкова бързо, че е невъзможно да се прочетат. Следователно изходът от програмата dmesg се предава като вход към командата less. (Командата less позволява изхода на командата dmesg да запълни само един екран. За да прочетете следващата част от текста, натиснете клавиша за интервал, а за да се върнете към предишната част, натиснете клавиша b. Можете да прекъснете програмата с клавиша q.) Вертикалната лента () е операторът за прехвърляне. (Интервалите преди и след вертикалната лента са за четливост, но можете и без тях.) Всичко заедно е най-простият програмен канал.

Очевидно такава схема е по-малко продуктивна: първо, необходимо е да се дадат две команди, и второ, защото следващата команда може да започне да работи само след завършване на първата.

Необходимо е да се изяснят понятията, които небрежно нарекох "вход" и "изход" на програмата.

Всяка шел програма работи с три потока от данни: стандартен вход (stdin), стандартен изход (stdout) и стандартно съобщение за грешка (stderr). (Можете да прочетете повече за това в статията „Пренасочване на стандартни потоци от данни“).

По подразбиране стандартният вход е от клавиатурата, а стандартният изход е към екрана. Ако използваме оператора за канали на програмата (), тогава стандартният изход на първата програма ще стане стандартен вход на втората, докато вече няма да се показва на екрана на монитора.

Такава верига в никакъв случай не се ограничава до две програми, а може да продължи безкрайно.

Как работи

В повечето Unix системи всички процеси в канал стартират по едно и също време, техните нишки са свързани по съответния начин и се управляват от планировчика заедно с всички други процеси, изпълнявани в системата.

Дори ако изпращащата програма произвежда 5000 байта в секунда, а приемащата програма може да обработва само 100 байта в секунда, пак няма да има загуба на информация, тъй като програмните канали имат буфери. Резултатът от изпращащата програма се събира в буфер, поставен на опашка. Когато получаващата програма е готова да чете данни, операционната система изпраща част от данните от буфера. В случай на препълване на буфера, изпращащата програма се спира (блокира), докато получаващата програма може да прочете отново данните, като по този начин освободи буфера.

Механизмът на това свойство на черупката е доста сложен, в тази статия няма да го разглеждаме, а просто ще използваме тази прекрасна способност на черупката.

какизползвайте канали за програмиране

Най-често използваните програмни канали завършват с командите по-малко и повече. Двете команди са подобни по функция, но по-малкото е по-ново и има редица допълнителни функции, включително възможност за връщане към предишни "страници" на изхода. Мнозина използват тези програмни канали, без да подозират, че правят такива трудни неща.

В допълнение към примера за dmesg по-малко тръба по-горе, често се използва ls по-малко тръба. Командата ls ви позволява да видите съдържанието на директориите, а с опцията -l дава подробна информация за файловете, които "обитават" посочената директория. Ако една директория съдържа достатъчно файлове, за да ги изброи за повече от един екран, тогава използването на по-малко или повече програмен канал е неизбежно:

За тестване направете този пример:

Ясно е, че е проблематично да се намери "ръчно" нещо в такъв списък и тук софтуерните канали отново ще дойдат на помощ.

Командата grep ще намери редовете, от които се нуждаете, ако посочите шаблон за търсене:

Обърнете внимание на символа # в началото на командния ред - това означава, че съм влязъл като root.

Командите, които изграждат програмните канали, често се наричат ​​филтърни команди, защото позволяват на потоците от данни да преминават през тях.

Това е само началото на списъка на реда grep -i usb, не го изброявам изцяло поради причини, свързани с пространството. Опцията -i казва на grep да игнорира разликата между главни и малки букви.

Всеки системен администратор често използва командата ps. С опциите -e и -f, той изброява всички процеси, изпълнявани в системата, в пълна (подробна) форма. Има много от тези процеси, така че не давам пълния резултат от командата:

За да намерите процесите, които ви интересуват в този списък, трябвапрепратете командата ps с командата grep. Да приемем, че се интересувате от халд процеси:

С такъв кратък списък вече е по-лесно да се работи. (Обърнете внимание на последния ред, той показва процеса grep hald, който стартирахме).

Други общи филтърни команди

В допълнение към командата grep (или заедно с нея) често се използват следните команди:

В този списък включих само няколко филтърни команди, след като ги усвоите, можете да се насладите на компилирането на най-сложните програмни канали до насита.

Комплексни програмни канали

Ето пример как да настроите проверка на правописа с помощта на канали за програмиране. Да предположим, че имате файл words.txt, който съдържа всички думи на английски език (разбира се, нямате такъв файл, но можете да заемете списък с думи от някакъв речник; и английски - за да не се бъркате с кодировки). След това се компилира следният програмен канал:

Забележка:Символът (\) се използва за комбиниране на всичките шест реда в един команден ред.

Първа команда: wget получава съдържанието на HTML уеб страница.

Втора команда: sed премахва всички знаци, които не са интервали или букви от текста на страницата и ги заменя с интервали.

Трета команда: tr преобразува всички главни букви в малки (главни букви в малки) и също преобразува интервалите в низове в нови редове, така че всяка „дума“ вече е нов ред.

Четвърта команда: grep оставя само редове, съдържащи поне един азбучен знак (само буква), като премахва всички празни редове.

Петата команда: sort сортира списъка с "думи" по азбучен ред и с опцията -u премахва дубликати.

Шестата и последна команда е: comm намира линии, които са общи за двефайлове. Първият файл е стандартният изход на нашия програмен канал, за който има тире (-) вместо името на първия файл, вторият файл ще бъде файлът words.txt. Редовете, които се срещат само във втория файл и тези, които се срещат и в двата файла, се потискат от опциите -2 и -3. Резултатът ще бъде списък с думи, които се срещат само в първия файл. И ако считаме файла words.txt за определен справочен речник, тогава изходният списък ще съдържа думи, които не са в речника, тоест написани с грешки.

Малко история

Концепция за наречена тръба

Английското име за наименована тръба е named pipe или FIFO (File In, File Out - файлът е дошъл, файлът е напуснал). Наименуваните канали служат предимно за комуникация между процесите, където различни процеси в системата обменят информация. Темата е сложна и мащабна, заслужава отделна статия. Затова в тази статия ще го засегна само накратко.

За разлика от анонимната програмна тръба, създадена автоматично от обвивката, наименуваната тръба има име и се създава изрично с командите mknod или mkfifo. Създайте канал с име fifo1:

Сега нека започнем процес за достъп до този канал:

Въпреки натискането на клавиша ENTER, нищо не се случва, което не е изненадващо, защото fifo1 файлът все още е празен и командата grep няма какво да обработва. Въпреки това, конзолата е заета от чакащ процес и може да бъде отключена само чрез прекъсване на процеса (да речем чрез натискане на CTRL+c).

За да попълни наименуван канал със съдържание, втори процес трябва да има достъп до него. За да направим това, трябва да отворим втора конзола и да изпълним някаква команда, която прехвърля данни към fifo1. Например:

Командата grep веднага ще се изпълни в първата конзола:

Съвсем ясно е какво да използватеНикой няма да бъде такъв неудобен механизъм за потребителски цели, защото е много по-лесно да стартирате един програмен канал:

и да получите същия резултат.

Дадох този пример само за да демонстрирам създаването и работата на наименуван канал. Друго нещо е, когато наименуваните канали се създават от самите процеси за обмен на информация помежду си. Но повтарям, че тази тема не е лесна и няма да бъде разгледана в тази статия.

Програмните канали са най-мощният инструмент на Unix операционните системи. Създаването на програмни канали значително ускорява процеса на обработка на данни, намалява количеството "писане" в командния ред и също така ви позволява да получите резултата в най-удобната форма.