Конструкция () всегда запускает подоболочку? - PullRequest
6 голосов
/ 08 мая 2011

Текущая оболочка

$ echo $$
23173

Обратите внимание, что родительский элемент ps - текущая оболочка

$ ( ps -o pid,ppid,cmd )
  PID  PPID CMD
 8952 23173 ps -o pid,ppid,cmd
23173 23169 bash

Но здесь родительский элемент ps - это подоболочка (bash)

$ ( echo hello ; ps -o pid,ppid,cmd )
hello
  PID  PPID CMD
 8953 23173 bash
 8954  8953 ps -o pid,ppid,cmd
23173 23169 bash

Оптимизирует ли Bash?Как получилось, что дополнительное эхо изменило ситуацию и породило подоболочку в третьем случае?

Ответы [ 2 ]

6 голосов
/ 08 мая 2011

Да, вы видите оптимизацию. Технически, конструкция (…) всегда запускает подоболочку по определению. В большинстве случаев подоболочка запускается в отдельном подпроцессе. Это гарантирует, что все, что делается в подоболочке, остается в подоболочке. Если bash может гарантировать это свойство изоляции, он может свободно использовать любую технику реализации, которая ему нравится.

Во фрагменте ( ps -o pid,ppid,cmd ) очевидно, что ничто не может повлиять на родительскую оболочку, поэтому в bash есть оптимизация, которая не позволяет создавать отдельный процесс для подоболочки. Фрагмент ( echo hello ; ps -o pid,ppid,cmd ) слишком сложен, чтобы оптимизатор мог распознать, что подоболочка не нужна.

Если вы поэкспериментируете с ksh, вы заметите, что его оптимизатор более агрессивен. Например, он также не разветвляет подпроцесс для ( echo hello ; ps -o pid,ppid,cmd ).

1 голос
/ 08 мая 2011

Подоболочка, состоящая из одной простой команды вместо списка или конвейера из более чем одной команды, может быть реализована простым «выполнением» команды, то есть заменой подоболочки на процесс для вызываемой команды.Если подоболочка более сложна, чем простой exec, то она невозможна, для управления последовательностью команд подоболочка должна оставаться рядом.

Из вашей диагностики невозможно определить разницу между оптимизацией bash, когда подоболочка, состоящая изПростая команда оптимизирована для «прямого» форка и exec вызываемой команды или для ветки subshell, за которой следует exec команды вызываемого.Это не удивительно, поскольку разница (почти?) Полностью академическая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...