Использует ли cat отложенные вычисления?

Использование цикла while:

#!/bin/sh

while :; do
    read -rp 'Please enter function: '
    case $REPLY in
        author)
            echo "John"
        ;; 
    esac
done

Это будет выполняться до тех пор, пока пользователь не введет прерывающую последовательность, которую я не рекомендую. По крайней мере, я бы обеспечил возможность выхода:

#!/bin/sh

while :; do
    read -rp 'Please enter function: '
    case $REPLY in
        author)
            echo "John"
        ;; 
        exit)
            break
        ;;
    esac
done

Другим вариантом (, если доступен bash, )будет меню выбора:

#!/bin/bash

PS3='Select a function: '
select FUNC in author publisher release_date exit; do
    case $FUNC in
        author)
            echo 'John'
        ;;
        publisher)
            echo 'Penguin'
        ;;
        release_date)
            echo '1996'
        ;;
        exit)
            break 2
        ;;
        *)
            echo 'ERROR! Unknown selection' >&2
        ;;
    esac
done
0
02.04.2020, 16:22
4 ответа

И cat, и strings, и большинство подобных утилит¹ считывают ввод понемногу, обрабатывают его, затем считывают ввод и т. д. Итак, в вашем случае catчитает только то, что отображает less, плюс еще немного того, что находится в пути.

Более подробно, основной операцией catявляется:

  • Зарезервируйте несколько килобайт памяти для использования в качестве буфера.
  • Пока доступно больше ввода :
    • Считать до N байтов ввода в буфер. (Это перезаписывает данные, которые были записаны в предыдущем цикле.)
    • Записать содержимое буфера в вывод.

Операция записи блокируется до тех пор, пока не появится место для копирования вывода. При выводе канала сам канал потребляет немного памяти в ядре, которая называется буфером канала . Когда он заполнен, если catпытается записать в канал, попытка записи блокируется до тех пор, пока не освободится место. В буфере канала может быть место, когда процесс на считывающем конце канала считывает некоторые данные.

Программа stringsработает так же, как cat, за исключением того, что она не копирует весь ввод, а только выбранные части.

Программа lessработает немного по-другому :она сохраняет все, что она читает в памяти. Он не перерабатывает свой буфер, он продолжает увеличивать его до тех пор, пока поступает больше входных данных. Однако часть чтения аналогична в том, что lessсчитывает данные только тогда, когда они нужны :он считывает только до последняя строка, которую он отображает, плюс немного больше, что он читает в ожидании, если доступно.

Итак, когда вы запускаете sudo cat /dev/sda | strings | less, то, что было прочитано из /dev/sda, состоит из:

  • Данные, которые lessуже отображали (или прокручивали после ).
  • До нескольких КБ данных, которые lessпрочитали, но еще не отобразили.
  • До нескольких КБ в конвейерном буфере между stringsи less.
  • До нескольких КБ в памяти strings.
  • До нескольких КБ в конвейерном буфере между catи strings.
  • До нескольких КБ в памяти cat.

Вы можете отслеживать, когда каждая программа читает и записывает данные, отслеживая ее системные вызовы:

sudo strace -e read,write -o cat.strace cat /dev/sda | strace -e read,write -o cat.strace strings | strace -e read,write -o less.strace less

и просмотрите файлы *.strace. Вы также можете проверить, сколько catпрочитано, проверив смещение файла, например, с помощью lsof -p1234или с помощью head /proc/1234/fdinfo/0, где 1234— идентификатор процесса cat.

¹ Среди базовых утилит обработки текста основным исключением является sort, которая не может выдать никаких выходных данных, пока не прочитает весь ввод :, насколько ей известно, первая строка вывода вполне может быть последней строкой ввода, которую он достигает.

2
28.04.2021, 23:19

Каналы имеют ограниченное пространство буфера, и если устройство чтения каналов (, такое как lessв вашем примере ), не считывает больше данных из канала, средство записи будет заблокировано после заполнения буфера. Это повлияет на команду strings, которая, в свою очередь, заблокирует команду catпосле заполнения ее канала.

Естественно, команда catне может прочитать все содержимое устройства sda в основную память, поэтому, если изменяются блоки, которые еще не были прочитаны ею, catувидит измененное содержимое.

3
28.04.2021, 23:19

Это больше связано с тем, как работает less, чем с тем, как работают catили strings.

Команда catвыводит данные только на стандартный вывод и блокируется всякий раз, когда буфер конвейера между ней и stringsзаполнен и никто не читает. catвыполняет минимальную буферизацию сам по себе, а канальный буфер обычно невелик.

Это верно и для strings. Он будет обрабатывать данные из catи блокируется, когда lessне считывает данные, созданные strings.

lessбуферизует свой ввод, чтобы вы могли перемещаться вперед и назад по отображаемым данным. Когда вы переходите на следующую страницу, lessсчитывает дополнительные данные из stringsв свой буфер. Пока вы не прокручиваете вперед, я полагаю, что lessбудет считывать только ограниченный объем данных (и, следовательно, stringsи catбудут заблокированы, пока вы не прокручиваете вперед ).

Если вы передаете большое количество данных в less, довольно много памяти будет использовано для этой буферизации , если вы решите прочитать все это до конца с помощью less.

Существует параметр -B, который ограничивает объем памяти, используемой для буферизации, до 64 килобайт (или столько, сколько вы укажете с помощью параметра -b).Ограничение размера буфера таким образом не позволит вам прокручивать назад больше, чем может быть сохранено в указанном пространстве буфера, но также позволит вам читать огромные объемы данных с помощью lessбез нехватки памяти.

См. также man lessв вашей системе.

5
28.04.2021, 23:19

В некоторых системах (, например. MS -Dos )канал реализован путем копирования вывода первой команды в файл, затем запуска 2-й команды для чтения из этого файла. Unix так не делает .

В Unix-системах это похоже на производственную линию. Каждый этап работает одновременно, считывая ввод и производя вывод. Если процесс A производит быстрее, чем процесс B потребляет, то между процессами A и B происходит накопление запасов. Когда это слишком много (от ½ КБ до 4 КБ ), процесс A приостанавливается. Когда для обработки B нет запаса, B приостанавливается. Процессы приостанавливаются и -не приостанавливаются, чтобы поддерживать низкий уровень запасов.

Код этих программ не заботится об этом. Он просто читает ввод и записывает вывод. Если он попытается прочитать до того, как данные будут доступны, или попытается записать до того, как следующий процесс будет готов, операционная система приостановит его до готовности.

Когда читать больше нечего (и больше ничего не находится в пути ), программа чтения получает конец -файла -и выходит. Это, в свою очередь, вызывает конец -файла -в следующем процессе.

2
28.04.2021, 23:19

Теги

Похожие вопросы