Почему lsтребуется отдельный процесс для его выполнения? Я знаю причину, по которой команды наподобие cdне могут быть выполнены механизмом разветвления, но есть ли вред, если они lsвыполняются без разветвления?
Почему lsтребуется отдельный процесс для его выполнения? Я знаю причину, по которой команды наподобие cdне могут быть выполнены механизмом разветвления, но есть ли вред, если они lsвыполняются без разветвления?
Ответы:
Ответ более или менее ls- внешний исполняемый файл. Вы можете увидеть его местоположение, запустив type -p ls.
Почему тогда не lsвстроен в оболочку? Ну почему так должно быть? Задача оболочки состоит не в том, чтобы охватить все доступные команды, а в том, чтобы обеспечить среду, способную их выполнять. У некоторых современных оболочек есть echo, printfи их аналог как встроенные, которые технически не обязательно должны быть встроенными, но сделаны из соображений производительности, когда они запускаются многократно (в основном в тесных циклах). Не делая их встроенными, оболочка должна была бы форкать и выполнять новый процесс для каждого вызова к ним, который может быть очень медленным.
По крайней мере, запуск lsвнешнего исполняемого файла требует выполнения одного из системных вызовов семейства exec. Вы можете сделать это без разветвления, но это заменит основную оболочку, которую вы используете. Вы можете увидеть, что происходит в этом случае, выполнив следующие действия:
exec ls; echo "this never gets printed"
Поскольку образ процесса вашей оболочки заменен, текущая оболочка больше не доступна после этого. Чтобы оболочка могла продолжать работать после запуска ls, команда должна быть встроена в оболочку.
Форкинг позволяет заменить процесс, который не является вашей основной оболочкой, что означает, что вы можете продолжить запускать свою оболочку впоследствии.
echo, printfи т.д.
cdне внешний исполняемый файл?
В Bash Reference Manual гласит:
Встроенные команды необходимы для реализации функциональности, которую невозможно или неудобно получить с помощью отдельных утилит.
То есть оболочки предназначены для включения только встроенных команд, если:
Команда lsне соответствует ни одному из вышеуказанных требований.
Однако здесь нет программных ограничений, которые бы препятствовали lsвнедрению в качестве встроенного, который выполняется в том же процессе, что и интерпретатор bash. Причины, по которым команды не внедряются в состав встроенных командных оболочек:
Что касается первой причины - вы хотите, чтобы оболочка была как можно более независимой и устойчивой. Вы не хотите, чтобы оболочка зависала lsпри монтировании NFS, которое «не отвечает, все еще пытается».
Что касается второй причины - во многих случаях вы можете использовать оболочку для системы, которая использует Busybox или другую файловую систему, которая имеет другую lsреализацию. Или даже использовать один и тот же источник оболочки в ОС, которые имеют разные lsреализации.
Что касается третьей причины - для таких выражений find . -type d | xargs ls -ladбыло бы трудно или невозможно реализовать их lsв том же процессе, что и интерпретатор оболочки.
Что касается четвертой причины - выполнение некоторых lsкоманд может занять много времени. Возможно, вы захотите, чтобы оболочка продолжала делать что-то еще в это время.
Примечание: Смотрите этот полезный пост по Уоррен Янг в ответ на подобный вопрос.
lsво внешний процесс. Это может быть сделано, но это будет сложно.
bashвывод alias | grep ls. входcat /etc/passwd | while read a; do echo "$a"; done
lsне требует отдельного процесса. Очень немногие команды фактически требуют отдельного процесса: только те, которые должны изменить привилегии.
Как правило, оболочки реализуют команды как встроенные, только когда эти команды должны быть реализованы как встроенные. Команды , как alias, cd, exit, export, jobs, ... нужно прочитать или изменить некоторое внутреннее состояние оболочки, и , следовательно , не могут быть отдельные программы. Команды, которые не имеют таких требований, могут быть отдельными командами; таким образом, они могут быть вызваны из любой оболочки или другой программы.
Глядя на список встроенных команд в bash, только следующие встроенные функции могут быть реализованы в виде отдельных команд. Для некоторых из них возможна небольшая потеря функциональности.
command- но он потеряет свою полезность в ситуациях, когда он PATHможет быть неправильно настроен, и сценарий используется commandкак часть его настройки.echo - это встроенный для эффективности.help - он может использовать отдельную базу данных, но встраивание текста справки в исполняемый файл оболочки имеет то преимущество, что делает исполняемый файл оболочки автономным.kill - наличие встроенной функции имеет два преимущества: она может распознавать обозначения заданий в дополнение к идентификаторам процессов и может использоваться даже тогда, когда не хватает ресурсов для запуска отдельного процесса.printf- по той же причине echo, что и для поддержки -vвозможности помещения вывода в переменную.pwd - встроенная функция предоставляет дополнительную возможность логического отслеживания текущего каталога (оставляя символические ссылки без изменений, а не расширяя их).test- это встроенная система для повышения эффективности (и bash также работает с файлами, вызываемыми /dev/fd/…в некоторых операционных системах).Несколько оболочек предлагают значительное количество дополнительных встроенных элементов. Есть sash , представляющий собой оболочку, разработанную как отдельный двоичный файл для аварийного ремонта (когда некоторые внешние команды могут быть недоступны). Он имеет встроенный ls, вызываемый -ls, а также другие инструменты, такие как -grepи -tar. Встроенные Sash-возможности имеют меньше возможностей, чем полноценные команды. Zsh предлагает несколько подобных встроенных функций в своем модуле zsh / files . Он не имеет ls, но подстановочный знак расширения ( echo *) и zstatможет выполнять аналогичную функцию.
Я думаю, что здесь чего-то не хватает людям, это сложная программа GNU lsна Linux. Сравнивая размер исполняемого файла lsс оболочкой bashand dashв моей системе Debian, мы видим, что он довольно большой:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Включение такой lsже полнофункциональной версии, как в версии GNU bash, увеличит размер исполняемого файла на 10%. Это почти такой же размер, как полная dashоболочка!
Большинство встроенных команд оболочки выбраны потому, что они интегрируются с оболочкой таким образом, что внешние исполняемые файлы не могут (вопрос указывает на это cd, но другой пример - это версия killинтеграции bash с управлением заданиями bash) или потому, что они представляют собой очень простые для реализации команды, давая большую скорость против размера выплаты ( trueи falseпримерно так же просто, как он получает).
У GNU lsбыл длинный цикл разработки, и он может реализовывать различные опции для настройки того, какие / как результаты отображаются. Использование встроенных ls по умолчанию либо потеряло бы эту функциональность, либо значительно увеличило бы сложность и размер оболочки.
Это сделать то, что вы ищете:
printf "%s\n" *
Также вы можете хранить имена файлов в массиве:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Но он не заботится о пробелах в именах.
Он переходит к переменной и заботится о пробелах:
printf "%s\n" * | while read a; do echo $a; done
lsэто внешняя программаecho *илиecho * .*(в зависимости от параметров оболочки) довольно неплохо выполняет распечатку файлов без разветвления.