Почему компакт-диск не программа?


129

Я всегда удивлялся, почему cdэто не программа, но так и не смог найти ответ.

Кто-нибудь знает, почему это так?



1
Я помню, как читал (не могу найти где), что исходная cdкоманда unix была отдельной программой. Оболочка обращалась с ним специально тем, чего нет fork, просто exec. И когда cdэто будет сделано, это будет exec sh. Я не знаю, правда ли это.
Camh

Какой в ​​этом смысл? Если он собирается добавить специальную обработку, он может просто вызвать chdirсистемный вызов. источники: v1 v5 v7 (первая версия с оболочкой Bourne)
Mikel

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

@Mikel: Я согласен, что это кажется бессмысленным, но я просто рассказывал историю о cdтом, что прочитал. Я был явно не прав насчет этого, теперь, когда @jlliagre заполнил детали.
Camh

Ответы:


172

Команда 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

И вот ответ на ваш вопрос « Почему компакт-диск не является программой? » Одного из оригинальных соавторов Unix. В очень ранней реализации Unix cd(написанной chdirв то время) была внешняя программа. Он просто неожиданно перестал работать после того, как forkбыл впервые реализован.

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

В разгар нашего ликования было обнаружено, что команда chdir (изменить текущий каталог) перестала работать. Было много чтения кода и тревожного самоанализа о том, как добавление fork могло сломать вызов chdir. Наконец дошла правда: в старой системе чдир был обычной командой; он корректировал текущий каталог (уникального) процесса, подключенного к терминалу. В новой системе команда chdir правильно изменила текущий каталог процесса, созданного для его выполнения, но этот процесс быстро завершился и никак не повлиял на его родительскую оболочку! Необходимо было сделать chdir специальной командой, выполняемой внутри оболочки. Оказывается, что несколько командоподобных функций имеют одно и то же свойство, например, login.

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

Unix Версия 1 (март 1971 г.) содержит следующую страницу руководства chdir :

Поскольку для выполнения каждой команды создается новый процесс, chdir будет неэффективным, если он будет записан как обычная команда. Поэтому он распознается и исполняется Shell.


10
... так что, очевидно, POSIX требует, чтобы существовал независимый cdисполняемый файл, но он ничего не должен делать (за исключением, возможно, выдачи сообщений об ошибках при вызове с неверными аргументами). Weird.
Ильмари Каронен

4
О, хорошо, если это правда, это не было бы самой глупой вещью в POSIX.
Каз

5
На странице cd POSIX также написано: «Поскольку cd влияет на текущую среду выполнения оболочки, он всегда предоставляется как обычная встроенная оболочка».
Микель

6
@ Каз, они не совсем разные вещи. Они делают то же самое, но только встроенный влияет на текущую оболочку.
Jlliagre

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

47

Из введения Bash ( Что такое оболочка? ):

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


29

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

Никто не получил шутку. Вздох.

Любой, кто не уверен, что cdдолжен быть встроен в оболочку, должен скачать ее, собрать и попробовать.

Читайте также его справочную страницу. :)


Действительно полезный код! :-)
dschulz

6
Рад видеть кого-то, кто работает над тем, чтобы сделать Gnu / Linux более совместимым с POSIX. Ваша реализация - это не только хорошая шутка, но на самом деле чего-то не хватает в дистрибутивах Linux ...
jlliagre

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

6 лет спустя: хорошо, а ты?
Питер А. Шнайдер

@ PeterA.Schneider: Я думал, что было ясно, что я шучу, поэтому, чтобы быть ясным, нет, на самом деле я не собираюсь тратить кучу усилий, пытаясь внедрить это в ОС и подобные OS проекты, такие как Cygwin, которые в настоящее время отсутствие /bin/cd. Если вы хотите взять мой код и сделать его своим собственным квестом, вы можете это сделать.
Уоррен Янг

4

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

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

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


0

CD - это встроенная команда оболочки. Так легко, как есть. Человек CD говорит все это. команда cd изменяет рабочий каталог для всех интерпретаторов и (в поточной среде) всех потоков.


Потому что оболочка - это среда, которая заботится о ваших текущих рабочих каталогах ($ PDW ...) или cdable_vars. В конечном счете, это встроенный способ, которым все видимые пользователем команды должны изменять текущий рабочий каталог. Вы можете проверить это таким образом: скомпилируйте bash без cd.c и попытайтесь написать свой собственный cd-скрипт, который пытается позаботиться обо всей среде cdable_vars. Этот вопрос также больше связан с разработчиком. Могу поспорить, что они могли бы ответить на этот вопрос более подробно.

2
Существует очень хорошая техническая причина, которая cdвстроена. Я бы посоветовал вам прочитать ответы с самым высоким рейтингом и подумать, как можно улучшить свой ответ.
Турбьерн Равн Андерсен

Ответ с самым высоким рейтингом был худшим, что я когда-либо читал! Но да? Кто я!

3
Но это отвечает на вопрос почему .
Турбьёрн Равн Андерсен

-1

Я думаю, что в ответах людей отсутствует одна вещь: текущий каталог - это переменная среды, которую может изменить каждая программа. Если вы используете команду «export» для просмотра текущего списка переменных среды, у вас будет:

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.)
Уоррен Янг

давайте добавим еще несколько строк в ваше приложение. #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.