LINUX.ORG.RU

Вопрос про потоковые редакторы UNIX

 , , ,


0

2

Читаю щас про sed учебник здешнего юзера, кстати, emulek'a встретил подозрительный кусок.

Далее sed последовательно читает все три файла, применяя к каждой строке в них sed-скрипт (пустой в данном случае). Результат выводится в выходной поток. Вот тут действие sed заканчивается, и опять начинает работать оболочка, последовательно записывая весь вывод в файл all.html. Потому код cat примитивен (пара строк на C), она просто читает входные файлы и выводит их в выходной поток, без всякой обработки, поисков и слияний. (Правда cat ещё и может нумеровать строки с ключом -n)

http://emulek.github.io/sed/ch01s02.html

Я, почему-то всегда думал, что выполнение происходит параллельно, или, как минимум, построчно. Типа, каждая строка передается по конвейру, а не буферы, куски etc. Может автор чуток ошибся? Или я что-то путаю?

Анонiмус решил перейти на sed? Что такое поток, по твоему? И кто должнен бить его на куски для параллельной обработки? И почему это должны быть границы строк, а не чанки по 9000 байт?

anonymous ()

Это тот наркоман, который счет три попытки логина в ssh за коннект - защитой от брута? Хороший учебник, наверное.

entefeed ☆☆☆ ()
Ответ на: комментарий от quest2017

Да хоть черезстрочный, если тебе надо слелать интерлив трех файлов, то сделай это отдельным звеном в пайпе. Юникс же, блеать!

anonymous ()
Ответ на: комментарий от entefeed

Емулек конечно странный, но ТС ему сто очков форы накидает.

anonymous ()
Ответ на: комментарий от anonymous

Я не понял, о чем ты. Одна программа должна передать другой строку, затем следующую, и тп. Надо быть идиотом, чтобы бить не на строки, придется потом склеивать каждый раз.

quest2017 ()
Ответ на: комментарий от quest2017

О, тс раскрывается во всей красе! Ты уж определись про какие другие программы идет речь. И почему sed должен отличаться от них.

anonymous ()
Ответ на: комментарий от quest2017

если вызывать read/write на каждую строку, а не на буфер, пирформанс будет сосать из-за избыточных переключений контекста

anonymous ()
Ответ на: комментарий от quest2017

Это утилиты для работы с потоками. Про строки ты придумал сам из частного случая. И мы возвращаемся к первым моим вопросам. Плюс еще один - как сливать результаты параллельной обработки?

anonymous ()

программы не вызывают write() напрямую

По конвееру передаётся то, что запишет туда программа. Она может построчно дёргать write(), а может большими кусками. Причём, обычно в коде программы используют функции потокового ввода/вывода, а не write() и то, как часто скидывается буфер, определяется через setvbuf().

Что касается:

Вот тут действие sed заканчивается, и опять начинает работать оболочка, последовательно записывая весь вывод в файл all.html

То это бред. Вызов:

sed '' *.html > all.html
Вобще не передаёт данные shell'у. Перед вызовом sed, командая оболока заменяет *.html на список существующих файлов, потом с помощью dup2() подменяет STDOUT на файл all.html и потом с таким STDOUT'ом запускает sed. Sed спокойно пишет свой вывод (*.html-файлы) в дискриптор 1, а ядро записывает эти данные не на терминал, а в файл all.html. Оболочка просто ожидает завершения работы sed.

mky ★★★★★ ()
Ответ на: программы не вызывают write() напрямую от mky

По конвееру передаётся то, что запишет туда программа. Она может построчно дёргать write(), а может большими кусками. Причём, обычно в коде программы используют функции потокового ввода/вывода, а не write() и то, как часто скидывается буфер, определяется через setvbuf()

Спасибо за ответ, но я, таки, не совсем понял. Тут не столь важно, какими именно кусками наполняется буфер, важно то, что заполнение должно прерываться, когда встретится перенос строки. Далее (как я себе представлял) обрабатывается строка, и передается далее, и лишь после этого происходит считывание новой строки. таким образом, каждая строка передается отдельно, а не весь считанный в буфер файл целиком, в этом суть вопроса.

quest2017 ()
Ответ на: комментарий от quest2017

Вы прочитали ″man setvbuf″ или лень? Если вам интерестно знать как всё работает на уровне системных вызовов, то лучше почитать про потоковый ввод/вывод, посмотрите работу программы под ″strace″. Если читать лень, то считате, что всё обрабатывается построчно.

Для консольный утилит стандартным является работа с помощью потоковых функций ввода/вывода (Input/Output on Streams). То есть в программе, допустим, написано ″printf(...\n);″ но это не означает, что в этом же месте будет вызван ″write(1, ...)″, данные могут быть помещены в буфер внутри программы и переданы ядру при заполнении буфера (при следующем ″printf()″) или при завершении программы. По умолчанию, если STDOUT указывает на терминал, то буфер скидывается построчно, если в файл, то по заполнению буфера.

Далее, pipe между двумя процессами, это по сути небольшой буфер (4 или 8 кбайт) в ядре. И туда не может записаться больше, чем он есть, запись преостонавливается, пока не будет произведено чтение. Поэтому если строка длинная (допусти 10 кбайт) то она будет передана кусками.

С чтением файла до некоторой степени аналогично. sed парсит строки, но библиотечные функции дергают ″read(0, ...)″ с буфером в несколько килобайт.

mky ★★★★★ ()
Ответ на: комментарий от quest2017

Так никто не делает, потому что так это не работает. Ты бы и сам это понял, если бы подумал, что произойдет например, если первый процесс успеет обработать и записать 2-100500 строк, пока второй тупит над предпоследней.

Нет никаких неявных разделителей записей, кроме \n в данном случае, и каждый буферизует как хочет, потому что нарезать по \n — это задача тех процессов, которым это нужно.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.