Чому ls
для його виконання потрібен окремий процес? Я знаю причину, чому такі команди, як cd
не можна виконувати за допомогою механізму forking, але чи є шкода, якщо ls
вони виконуються без розгортання?
Чому ls
для його виконання потрібен окремий процес? Я знаю причину, чому такі команди, як cd
не можна виконувати за допомогою механізму forking, але чи є шкода, якщо ls
вони виконуються без розгортання?
Відповіді:
Більш-менш відповідь ls
- це зовнішній виконуваний файл. Ви можете побачити його місцезнаходження, запустивши type -p ls
.
Чому тоді не ls
вбудований в оболонку? Ну чому це має бути? Завдання оболонки - не охоплювати всі наявні команди, а забезпечувати середовище, здатне виконувати їх. Деякі сучасні оболонки мають echo
, printf
і їх називають вбудованими, які технічно не повинні бути вбудованими, але зроблені так з міркувань продуктивності, коли вони запускаються повторно (насамперед у щільних петлях). Не роблячи їх вбудованими, оболонка повинна буде розщедритися та виконати новий процес для кожного дзвінка до них, який може бути дуже повільним.
Як мінімум, запущений ls
зовнішній виконуваний файл вимагає запуску однієї з сімейств exec системних викликів. Ви можете це зробити, не розвантажуючи, але це замінить первинну оболонку, яку ви використовуєте. Ви можете побачити, що відбувається в цьому випадку, виконавши наступне:
exec ls; echo "this never gets printed"
Оскільки зображення процесу вашої оболонки замінено, поточна оболонка більше не доступна після цього. Щоб оболонка могла продовжувати працювати після запуску ls, команда повинна бути вбудована в оболонку.
Форкінг дозволяє замінити процес, який не є вашою основною оболонкою, а це означає, що ви можете продовжувати запускати оболонку згодом.
echo
, printf
і так далі
cd
не зовнішній виконуваний файл?
cd
виконуваний в POSIX-сумісних операційних систем ( дивіться тут ). Якщо ви хочете насправді chdir () в поточному процесі, вам потрібно, щоб він був вбудований в оболонку.
У Довідковому посібнику Баша зазначено:
Команди вбудованих необхідні для реалізації функціональних можливостей, неможливих або незручних для отримання за допомогою окремих утиліт.
Тобто, снаряди призначені для тільки включає вбудовані команди , якщо:
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/…
в деяких операційних системах).Кілька оболонок пропонують значну кількість додаткових вбудованих конструкцій. Там в стулці , яка є оболонкою призначена для автономного довічних для аварійного ремонту (коли деякі зовнішні команди можуть не працювати). У ньому є вбудований ls
, званий -ls
, а також інші інструменти, такі як -grep
і -tar
. Вбудовані Sash мають менше можливостей, ніж повноцінні команди. Zsh пропонує деякі подібні вбудовані модулі zsh / files . Він не має ls
, але розширення підстановки ( echo *
) zstat
може виконувати подібну функцію.
Я думаю, що тут чогось не вистачає людям - це складна складність програми GNU ls
в Linux. Порівнюючи виконуваний розмір ls
до bash
і 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
, але іншим прикладом є bash версія kill
інтеграції з контролем роботи 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 * .*
(залежно від параметрів оболонки) виконує досить непогану роботу з перерахуванням файлів без розгортання.