Чому CD не є програмою?


128

Мені завжди було цікаво, чому cdце не програма, але так і не вдалося знайти відповідь.

Хтось знає, чому це так?



1
Я пам'ятаю, як читав (не можу знайти), що оригінальна cdкоманда unix була окремою програмою. Оболонка обробляла її спеціально тим, що цього не робила fork, просто exec. А коли cdце буде зроблено, це буде виконано sh. Я не знаю, чи це справжня історія.
camh

Який би був сенс? Якщо він додасть спеціальну обробку, він також може просто зателефонувати в chdirsyscall. джерела: v1 v5 v7 (перша версія з оболонкою Bourne)
Мікель

2
@camh, це справжня історія. Я також це прочитав у статті, написаній Деннісом М. Річі, «Еволюція системи розподілу часу Unix», технічний журнал AT&T Bell Laboratories, 63 (6), частина 2, жовтень 1984 р.
jlliagre

@Mikel: Я погоджуюся, що це здається безглуздим, але я просто переказував розповідь про cdте, що я прочитав. Я чітко помилявся щодо його аспекту, тепер, коли @jlliagre заповнив деталі.
camh

Відповіді:


171

cdКоманда змінює «поточний робочий каталог», НЕ так?

"поточний робочий каталог" - властивість, унікальна для кожного процесу.

Отже, якби це cdбула програма, вона працювала б так:

  1. cd foo
  2. cdпроцес починається
  3. cdпроцес змінює каталог для процесу кд
  4. то cdпроцес завершується
  5. ваша оболонка все ще має той самий стан, включаючи поточну робочу директорію, як і раніше.

8
Ваші п'ять кроків є правильними, але "якби cdпрограма була, вона працювала б так" повинна бути ", коли cdвона використовується в її зовнішній реалізації програми, вона працює так".
jlliagre

1
Не будучи системним програмістом, а також не маючи глибоких знань про входи та виходи взаємодії з оболонкою, я б очікував, що оболонка відкриє свій поточний робочий каталог, а CD може бути програмою, яка отримує доступ та змінює цю властивість. Розуміння, подивившись на цю відповідь, що, мабуть, є неоптимальним для того, як це насправді працює з багатьох причин.
Джейсон

108

cdна додаток до вбудованої оболонки, насправді це також програма на сумісних з POSIX ОС. Вони повинні забезпечувати незалежні виконувані файли для звичайних утиліт, наприклад cd. Це, наприклад , у випадку з Solaris , AIX , HP-UX та OS X .

Очевидно, що вбудований cdвсе ще є обов'язковим, оскільки його зовнішня реалізація не змінює поточний каталог оболонки. Однак останнє все ж може бути корисним. Ось приклад, який показує, як POSIX передбачає, як cdможна використовувати цю команду:

find . -type d -exec cd {} \;

У системі POSIX цей oneliner повідомить про помилку для всіх каталогів, до яких ви не можете входити cd. У більшості дистрибутивів Gnu / Linux він не працює з цим повідомленням про помилку:

find: `cd': No such file or directory

І ось відповідь на ваше запитання " Чому CD не програма? " Одного з оригінальних співавторів Unix. За дуже раннього впровадження Unix cd(написана chdirна той час) була зовнішньою програмою. Він просто перестав працювати несподівано після того, як forkбув вперше впроваджений.

Цитуючи Денніса Річі :

У розпал нашого радості було виявлено, що команда chdir (змінити поточний каталог) перестала працювати. Читалося читання коду та тривожний самоаналіз щодо того, як додавання вилки могло порушити дзвінок chdir. Нарешті правда осяяла: у старій системі chdir була звичайною командою; він скоригував поточний каталог (унікального) процесу, приєднаного до терміналу. У новій системі команда chdir правильно змінила поточний каталог процесу, створеного для його виконання, але цей процес негайно припинився і не мав жодного впливу на його батьківську оболонку! Необхідно було зробити chdir спеціальну команду, виконану внутрішньо всередині оболонки. Виявляється, кілька функцій, подібних до команд, мають однакову властивість, наприклад, вхід.

Джерело: Денніс М. Річі, « Еволюція системи розподілу часу Unix », Технічний журнал «AT&T Bell Laboratories» 63 (6), частина 2, жовтень 1984, с.1577–93

На сторінці керівництва chdir Unix версії 1 (березень 1971 р.) Зазначено :

Оскільки для виконання кожної команди створений новий процес, chdir був би неефективним, якби він був записаний як звичайна команда. Тому вона визнана і виконана Шеллом.


10
... так, мабуть, POSIX наказує, що має бути незалежний cdвиконуваний файл, але він нічого не робить (крім можливого випромінення повідомлень про помилки, якщо викликається неправильними аргументами). Дивно.
Ільмарі Каронен

4
Ну добре, якщо це правда, це не було б найглупішим у POSIX.
Каз

5
На сторінці cd POSIX також написано "Оскільки cd впливає на поточне середовище виконання оболонки, він завжди надається як регулярний вбудований оболонку."
Мікель

6
@Kaz, це не зовсім різні речі. Вони роблять те саме, але тільки вбудований впливає на поточну оболонку.
jlliagre

13
@Kaz: Будь ласка, не називайте мене дурним, поки я лише повідомляю факт. Ви можете погодитись або не погодитися з POSIX, але не знімайте месенджер.
jlliagre

47

З вступу Баша ( Що таке оболонка? ):

Оболонки також забезпечують невеликий набір вбудованих команд (вбудованих), що реалізують функціональні можливості, які неможливо або незручно отримати за допомогою окремих утиліт. Так , наприклад, cd, break, continueі exec) не можуть бути реалізовані поза корпусу , так як вони безпосередньо маніпулювати самої оболонки. history, getopts, kill, Або pwdвбудовані функції , в зокрема, можуть бути реалізовані в вигляді окремих утиліт, але вони більш зручні для використання в якості вбудованих команд. Всі вбудовані оболонки описані в наступних розділах.


29

Для квітня Дурня цього року я написав автономну версіюcd .

Ніхто не отримав жарту. Зітхнути.

Кожен, хто не впевнений, що він cdповинен бути вбудований в оболонку, повинен завантажити його, створити його і спробувати.

Читайте також його довідкову сторінку. :)


Дійсно корисний код! :-)
dschulz

6
Приємно, що ви бачили, хто працює над тим, щоб зробити Gnu / Linux більш сумісним з POSIX. Ваша реалізація - це не лише хороший жарт, але й насправді щось не вистачає у дистрибутивах Linux ...
jlliagre

8
Я думаю, що я спробую повторити наступного року, посилаючись на проблему POSIX. ;)
Воррен Янг

6 років пізніше: ну, ти що?
Пітер А. Шнайдер

@ PeterA.Schneider: Я вважав, що це зрозуміло, що я жартую, тому, щоб було зрозуміло, ні, я насправді не збираюся витрачати купу зусиль, намагаючись увімкнути це в ОС та такі проекти, подібні ОС, як Cygwin, що зараз відсутність /bin/cd. Якщо ви хочете взяти мій код і зробити це своїм особистим квестом, ви можете зробити це.
Warren Young

4

cdКоманди в оболонці не може бути окремим процесом , так як в Unix не існує ніякого механізму для зміни поточного робочого каталогу іншого процесу (навіть не батьківський процес).

Якщо це cdбув інший процес, тоді він повинен був би змінити поточний робочий каталог свого батьківського (оболонки), що неможливо в Unix. Натомість cdспеціальна вбудована команда. Оболонка викликає такі функції, як chdir()і fchdir() зміна власного поточного робочого каталогу.

Примітка: ядро ​​зберігає номер inode поточного робочого каталогу для кожного процесу. Дочірній процес успадковує це cwdвід свого батька.


0

CD - це вбудована команда оболонки. Настільки ж просто. Чоловік CD все це каже. Команда cd змінює робочий каталог для всіх інтерпретаторів і (у потоковому середовищі) для всіх потоків.


Тому що оболонка - це середовище, яке піклується про ваші поточні робочі панове ($ PDW ...) або cdable_vars. Цей вбудований в кінцевому рахунку спосіб, коли всі видимі користувачу команди повинні змінити поточну робочу директорію. Ви можете перевірити це таким чином: компілюйте bash без cd.c і спробуйте написати свій власний скрипт cd, який намагається подбати про все середовище cdable_vars. Це питання також більше стосується розробника. Надіюсь, вони могли відповісти на це запитання більш детально.

2
Є дуже хороша технічна причина, яка cdвбудована. Я б запропонував прочитати відповіді з найвищим рейтингом і подумати, як можна покращити свою відповідь.
Thorbjørn Ravn Andersen

Найвища відповідь була найгіршою, яку я коли-небудь читав! Але так? Хто я!

3
Але це відповідає на питання, чому .
Thorbjørn Ravn Andersen

-1

Я думаю, що одній людині не вистачає відповіді, що поточний каталог - це змінна середовище, яку може змінити кожна програма. Якщо ви використовуєте команду "експортувати" для перегляду поточного списку змінних середовища, у вас буде:

declare -x PWD="/home/erfan"

у ваших результатах. Таким чином, командою 'cd' ми просто хочемо змінити цю внутрішню змінну. Я думаю, якщо ми спробуємо, звичайно, ми можемо змінити змінну PWD будь-якого pty в оболонці. Подібно до:

cder    #change current PTY $PWD variable

Але я думаю, що в нормальних випадках немає потреби. Іншим словом, ми беремо допомогу від bash (або будь-якої оболонки), щоб змінити визначену внутрішню змінну.


3
Хоча це правда, що оболонки Bourne розкривають поточний робочий каталог (CWD) як $ PWD, це не основне місце зберігання; фактичне розташування знаходиться в структурі ядра для кожного процесу. Тому неправильно говорити, що CWD "є змінною середовища". Якби він працював так, як ви запропонували, цей двоярусний C надрукував би ..шлях, а не шлях, з якого ви його розпочали: #include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(До речі, оболонки C розкривають CWD як% cwd.)
Warren Young

дозволяє додавати ще кілька рядків у ваш додаток. #include <stdlib.h> int main (void) {chdir (".."); ставить (getenv ("PWD")); setenv (P "PWD", "/", 1); ставить (getenv ("PWD")); } Що ми матимемо як результати?
Ерфанкам

3
Це просто замінить значення змінної, без побічного впливу на CWD. Це кращий тест, щоб показати, що: #include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }Він покаже каталог, з якого ви запустили програму, а не /.
Воррен Янг

Я думаю, що кожен процес також має робочий каталог і змінну шляху. Таким чином, ви, chdir, просто змінюєте цей атрибут процесу. У Shell є і цей атрибут, і за допомогою cd ми модифікуємо цю сутність.
Ерфанкам

4
Ні, я кажу вам, що $PWDмає значення лише оболонка Борна. Це просто спосіб передавати оболонці щось, що вона знає, для оболонки сценаріїв, тому їм не потрібно телефонувати, pwdщоб знайти її. Будь-яка окрема програма залежно від значення $PWDбуде ненадійною.
Воррен Янг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.