2016-04-14 3 views
4

Как работает процесс (например, в Bash), реализованный в терминах системных вызовов Linux?Каким образом выполняется процесс, реализованный в терминах системных вызовов Linux?


Цель моего вопроса в том, что я не понимаю, почему Баш руководство говорит

асинхронные команды вызываются в среде подоболочки,

(если я правильно, «асинхронные команды» означают запуск команд в фоновом режиме), , а с помощью strace я обнаружил, что процесс родительской оболочки сначала вызывает clone(), чтобы создать подоболочку, которая является копией самой, и то подоболочка вызывает execve(), чтобы заменить сам подоболочку командой для запуска в фоновом режиме.

Это похоже на работу переднего плана. Я не вижу, что команда вызывается в подоболочке. Если я прав, вызов команды в подоболочке означает, что подоболочка вызывает clone() для создания подпункта, а затем subsubshell вызывает execve(), чтобы заменить сам subsubshell командой для запуска в фоновом режиме. Но на самом деле подоболочка не вызывает clone().

Например,

В Ubuntu, я бегу date в интерактивном Баш оболочки, ИЗОДРОМНЫЙ 6913, и в то же время, проследить Баш оболочку из другого интерактивного Баш оболочки strace.

При запуске date, выход трассировки первой оболочки 6913 во второй оболочке:

$ sudo strace -f -e trace=process -p 6913 
[sudo] password for t: 
Process 6913 attached 
clone(Process 12918 attached 
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 12918 
[pid 6913] wait4(-1, <unfinished ...> 
[pid 12918] execve("/bin/date", ["date"], [/* 66 vars */]) = 0 
[pid 12918] arch_prctl(ARCH_SET_FS, 0x7ff00c632740) = 0 
[pid 12918] exit_group(0)    = ? 
[pid 12918] +++ exited with 0 +++ 
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 12918 
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12918, si_status=0, si_utime=0, si_stime=0} --- 
wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes) 

При запуске date &, выход трассировки первой оболочки 6913 во второй оболочке:

$ sudo strace -f -e trace=process -p 6913 
Process 6913 attached 
clone(Process 12931 attached 
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 12931 
[pid 12931] execve("/bin/date", ["date"], [/* 66 vars */]) = 0 
[pid 12931] arch_prctl(ARCH_SET_FS, 0x7f530c5ee740) = 0 
[pid 12931] exit_group(0)    = ? 
[pid 12931] +++ exited with 0 +++ 
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12931, si_status=0, si_utime=0, si_stime=0} --- 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 12931 
wait4(-1, 0x7ffea6780718, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes) 

ответ

1

подоболочка не вызывает клон()

Это явная оптимизация. bash понимает, что нет смысла делать другую дорогостоящую fork, если единственным заданием подоболочки является одновременное выполнение одной внешней команды. От execute_cmd.c:

/* If this is a simple command, tell execute_disk_command that it 
    might be able to get away without forking and simply exec. 
    This means things like (sleep 10) will only cause one fork. 
    If we're timing the command or inverting its return value, however, 
    we cannot do this optimization. */ 

Реальная разница только между date системных вызовов и date & поэтому в том, что последний не следует wait.

Более интересный случай, о котором упоминается в руководстве bash, - это когда вы запускаете не внешние команды. Разница между let i++ и let i++ & заключается в том, что первая оценивается самим bash, а последняя оценивается подоболочкой, которая затем выходит и, следовательно, не имеет никакого эффекта.

+0

Функция glibc 'fork' не использует _not_ для использования sysall' fork' [больше]. Эта функция является [несколько сложной] оболочкой вокруг «клона». 'bash' может вызвать' clone' напрямую, если он пожелает. Но в любом случае настройка [накладные расходы] одинакова. Функция 'fork' делает' clone' с опцией, которая говорит, что хочет отдельное адресное пространство, но 'pthread_create' вызывает' clone' с опцией, говорящей, что хочет иметь общее адресное пространство. –

+0

Возможно, вы имеете в виду «если единственная работа подоболочки состоит в том, чтобы выполнять внутреннюю команду синхронно "(и эта внутренняя команда не управляет состоянием). – Kaz

+0

'clone' [nee' fork'] на самом деле довольно легкий. Он не делает копию родительской памяти.Он устанавливает таблицы дочерних страниц в соответствии с родительским (относительно быстрым). Для любой доступной для записи страницы в родительской записи запись PTB помечена как R/O как в родительском, так и в дочернем. Когда один из них записывает на заданную страницу, возникает ошибка страницы, и затем процессу присваивается частная копия общей страницы, а PTB обоих параметров настраиваются [на R/W]. Это «fork on demand» или «copy-on-write». Таким образом, если ребенок только попадает на страницу или две, прежде чем выполнять «execve», накладные расходы довольно низки. –

1

Текст «» «Асинхронные команды вызывают в среде подклассов». конкретно не ссылается на фоновые рисунки, поскольку фоновое представление представляет собой интерактивную концепцию из «Управление заданиями POSIX». В то время как асинхронные команды происходят интерактивно или не интерактивно.

«Вызванный в подоболочек среды» просто оболочка терминологии, что означает, что fork происходит, и эти команды выполняются в дочернем процессе, который не может изменять переменные в родительском и другом состоянии:

$ VAR=value & 
[1] 15479 
[1]+ Done     VAR=value 
$ echo $VAR 
$ 

Поскольку назначение переменной выполняется в подоболочке, оно не влияет на родительскую оболочку.

Как работает работа с точки зрения системных вызовов, это то, что управление заданиями POSIX вращается вокруг набора процессов, которые организованы в группы процессов, которые относятся к сеансу, который подключен к управляющему терминалу. Только одна группа за раз в сеансе - это группа процессов переднего плана.

Причина, по которой дизайн вращается вокруг групп, а не отдельных процессов, состоит в том, что задания состоят из нескольких процессов при использовании трубопроводов. Например, sort -u file | grep foo создает группу процессов с двумя процессами.

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

Когда вы отправляете Ctrl-Z в TTY, он генерирует сигнал SIGTSTP для каждого процесса в группе процессов переднего плана. Оболочка обнаруживает это изменение в статусе ребенка (через waitpid или некоторые из таких), а затем перетасовывает эту группу на задний план, снова помещаясь на передний план, чтобы получить вход TTY.

Когда вы разговариваете с оболочкой, все задания находятся в фоновом режиме, независимо от того, запущены они или нет: оболочка - это группа процессов переднего плана, поэтому все остальные задания отсутствуют. С помощью команды bg вы просто меняете текущее состояние приостановленного фонового задания. Ctrl-Z отправил SIGTSTP, который приостановил его, и оболочка переместила его на задний план. bg возобновит его, что позволит ему выполнить. Тем не менее, если фоновая работа возобновляется, и пытается получить ввод с терминала, он получает SIGTTIN сигнал и снова приостановлено:

$ cat & 
[1] 12620 
$ bg 
[1]+ cat & 
$  # hit Enter 
[1]+ Stopped     cat 
$ bg 
[1]+ cat & 
$  # hit Enter 
[1]+ Stopped     cat 

cat хочет читать с терминала, поэтому, когда мы помещаем его в фоновом режиме , он получает SIGTTIN из подсистемы TTY ядра, которая останавливает ее. Оболочка обнаруживает это изменение сигнала в статусе аналогично Ctrl-Z/SIGTSTP и выводит сообщение о том, что работа остановлена. Каждый раз, когда мы bg, он (возобновляет) то же самое происходит. Оболочка отправляет cat (возможно, с SIGCONT), и cat немедленно возобновляет попытку получить входной сигнал от TTY, который отвечает «вы не являетесь участником группы процессов переднего плана, плохой котенок: SIGTTIN для вас». Все это время, cat никогда не покидает фон.

+0

«Фоновый рисунок» - это не концепция управления заданиями. Мы назвали это еще в дни раковины Борна, до того, как был изобретен контроль над работой (оригинал был в 'csh' в BSD). – Barmar

Смежные вопросы