Почему команда оболочки «{command1; command2:} & "открыть подоболочку?

Как мы все знаем, размещение списка команд между фигурными скобками приводит к тому, что список выполняется в текущем контексте оболочки. Подоболочка не создается. Но почему при использовании "&" после "{}" создаются две подоболочки? pid 1002 и 1003.

{
    ./a.out
} &

sleep 19

введите здесь описание изображения

при использовании "./a.out &" создается только подоболочка. пид 17358.

./a.out &
sleep 19

введите здесь описание изображения

Почему ?


person Pengcheng    schedule 14.05.2016    source источник
comment
Вы хотели сказать, что при использовании ./a.out & подоболочка НЕ ​​создается?   -  person Dave Schweisguth    schedule 14.05.2016
comment
создается только подоболочка. pid - 17358. Но, {./a.out} &, создаются две подоболочки. pid 1003 и 1002.   -  person Pengcheng    schedule 14.05.2016


Ответы (2)


Фоновое выполнение списка использует подоболочку, потому что что-то должно ждать каждого члена этого списка и запускать следующий. После создания списка исходная оболочка должна быть доступна для новых команд; он также не может управлять фоновым списком. bash не может делать больше одной задачи за раз. Итак, чтобы фоновый список работал, он запускает подоболочку.

Обратите внимание, что вы можете отказаться от фонового списка, и он продолжит работу, показывая, что подоболочка выполняет свою работу:

$ {
> sleep 1; sleep 2; sleep 3; sleep 4; sleep 5
> } &
$ disown
$ ps -f | grep sleep
dave     31845 31842  0 03:50 pts/1    00:00:00 sleep 3 
dave     31849 31771  0 03:50 pts/1    00:00:00 grep sleep

Вы даже можете выйти из системы, и подоболочка продолжит запускать процессы из списка.

Когда вы выполняете одну команду в фоновом режиме, в подоболочке нет необходимости, потому что оболочке больше не нужно выполнять какую-либо работу после того, как она выполнила команду.

В вашем примере второй дополнительный подпроцесс bash, PID 1002, выглядит как сценарий, который вы выполняете. Это не связано (по крайней мере, концептуально) с механизмом создания списка; любой скрипт в отдельном файле имеет свой собственный процесс bash.

person Dave Schweisguth    schedule 14.05.2016
comment
Дэйв, спасибо. Но я не знаю, почему commond ”{./a.out} & вызывает создание двух подоболочек? - person Pengcheng; 14.05.2016
comment
Это не так; он создает только одну дополнительную оболочку (PID 1003 в вашем примере) для управления конвейером. В вашем примере PID 1002 выглядит как сценарий, содержащий {./a.out} &, который является его собственной оболочкой по другой причине. - person Dave Schweisguth; 14.05.2016
comment
с помощью оболочки (PID 1003) для управления конвейером? Подскажите подробнее, пожалуйста - person Pengcheng; 14.05.2016
comment
Вот что я объяснил в своем ответе: подоболочка ждет завершения каждой команды и запускает следующую. Однако мне не следовало говорить о конвейере, поскольку команды не передаются друг другу по конвейеру. Это последовательность отдельных команд. - person Dave Schweisguth; 14.05.2016
comment
Дэйв, я понял. Спасибо за вашу помощь. - person Pengcheng; 14.05.2016

Если команда завершается управляющим оператором &, оболочка выполняет команду (или список команд, заключенных в {...}) в фоновом режиме (или асинхронно) в подоболочке .

Оболочка не ждет завершения команды, и статус возврата равен 0.

В программе C это делается fork(), за которым следуют execvp() системные вызовы.


Обновление: на основе комментариев ниже и обновленного вопроса. Вот что происходит.

Когда вы бежите:

./a.out &

BASH напрямую просто запускает a.out в фоновом режиме, поскольку для запуска двоичного файла a.out не требуется отдельный процесс оболочки.

Когда вы бежите:

{ ./a.out; } &

BASH должен сначала выполнить ответвление и создать подоболочку, поскольку вы можете иметь ряд команд внутри {...}, а затем вновь созданная подоболочка запускается a.out в отдельном процессе. Так что дело не в том, что BASH создает для этого 2 подоболочки. Создается только одна подоболочка, а второй pid, который вы видите, предназначен для a.out.

person anubhava    schedule 14.05.2016
comment
Но при использовании ./a.out & создается только подоболочка. в то время как, {./a.out} & указывает команду, выполняемую в подоболочке подоболочки. - person Pengcheng; 14.05.2016
comment
& перед любой командой заставит эту команду выполняться во вспомогательной оболочке - person anubhava; 14.05.2016
comment
а.выход int main() { sleep(100); return 0; } - person Pengcheng; 14.05.2016