Как работает процесс (например, в 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)
Функция glibc 'fork' не использует _not_ для использования sysall' fork' [больше]. Эта функция является [несколько сложной] оболочкой вокруг «клона». 'bash' может вызвать' clone' напрямую, если он пожелает. Но в любом случае настройка [накладные расходы] одинакова. Функция 'fork' делает' clone' с опцией, которая говорит, что хочет отдельное адресное пространство, но 'pthread_create' вызывает' clone' с опцией, говорящей, что хочет иметь общее адресное пространство. –
Возможно, вы имеете в виду «если единственная работа подоболочки состоит в том, чтобы выполнять внутреннюю команду синхронно "(и эта внутренняя команда не управляет состоянием). – Kaz
'clone' [nee' fork'] на самом деле довольно легкий. Он не делает копию родительской памяти.Он устанавливает таблицы дочерних страниц в соответствии с родительским (относительно быстрым). Для любой доступной для записи страницы в родительской записи запись PTB помечена как R/O как в родительском, так и в дочернем. Когда один из них записывает на заданную страницу, возникает ошибка страницы, и затем процессу присваивается частная копия общей страницы, а PTB обоих параметров настраиваются [на R/W]. Это «fork on demand» или «copy-on-write». Таким образом, если ребенок только попадает на страницу или две, прежде чем выполнять «execve», накладные расходы довольно низки. –