Ваша программа foo
, запустит какой-нибудь дочерний процесс для запуска другой программы, bar
,
и вы хотите сделать это с помощью основных системных вызовов fork
и execve
Давайте назовем ваш начальный foo
процесс p1 . (Это означает: pid .)
Сначала вы позвоните fork .
Это создает дочерний процесс p1 , который выполняет другой экземпляр из foo
Вызовите этот дочерний процесс p1.1 .
p1.1 работает foo
. Но вы хотите запустить bar
. Так что сразу в p1.1 , foo
звонит execve(path/to/bar ...)
.
Это заменяет экземпляр foo
, который p1.1 работает, с экземпляром bar
. Тогда ваш
дочерний процесс p1.1 выполняется bar
, как вы хотите.
Будьте ясны об этом : -
execve(path/to/bar ...)
делает не началом bar
в новом подпроцессе
p1.1 и оставьте p1.1 все еще работающим после пост-форка экземпляра foo
. Вместо этого execve(path/to/bar ...)
заменяет
тот экземпляр foo
с экземпляром bar
в процессе p1.1 . После fork
, но до execve
,
у нас есть:
p1[foo] -> p1.1[foo]
А после execve
имеем:
p1[foo] -> p1.1[bar]
не
p1[foo] -> p1.1[foo] -> p1.1.1[bar]
Вы можете видеть, что execve
не может вернуть success вызывающему, p1.1 [foo],
потому что если execve
успешно, то p1.1 [foo] больше не существует .
И, конечно же, execve
не может вернуть успех p1 [foo], потому что p1 [foo] не вызывал его .
поскольку execve никогда не возвращается, он всегда будет выполнять что-то, если все в порядке
Нет. execve
заменяет p1.1 [foo] на p1.1 [bar] и не возвращает, потому что вызывающий абонент больше не существует. Затем p1.1 [bar] работает, пока не завершится.
p1.1 [bar] рано или поздно завершится одним из способов
что любая программа завершает свою работу: она будет работать до нормального exit
или
быть убитым сигналом, или это может вызвать abort
по собственному желанию.
Как родительский процесс ( p1 ) может пожинать этот дочерний процесс ( p1.1 )?
Во-первых, это не обязательно . Как только p1 [foo] запустится p1.1 , он может
если ты этого хочешь, просто забудь о p1.1 , займись другими делами
если есть, и в конечном итоге exit
. Если p1 завершается раньше p1.1 , тогда p1.1
становится бесхозным процессом .
Процесс-сирота сразу же принимается в качестве ребенка процессом init
. Так
если ничего не прервется за это время, p1.1 будет получено после завершения init
при выключении системы.
Но, скорее всего, вы не хотите оставлять сирот, и вы делаете хотите foo
узнать статус выхода ребенка bar
. В таком случае,
p1 [foo] рано или поздно должен позвонить wait / waitpid чтобы узнать сейчас p1.1
закончили, а затем действуйте соответственно.
Между тем, p1 [foo] вполне может связываться с p1.1 [bar], используя некоторые
форма межпроцессное взаимодействие . И / или p1 [foo] может
отметить прошедшее время, пока p1.1 [bar] еще не закончилось. Одним из этих или других способов p1 [foo] может определить
что p1.1 [bar] попал в беду, слишком долго и решил убить p1.1 .
Когда p1.1 будет убит - кто бы это ни сделал - или закончит по собственному желанию, wait/waitpid
вернет эту информацию p1 [foo], а затем
может покинуть себя или продолжать заниматься чем-то другим.
В комментарии вы задали вопрос:
не можем ли мы спроектировать [execve
] как: вернуть 1, если дочерний процесс завершен?
Такой системный вызов, безусловно, может быть спроектирован и уже существует, но он не может
быть неблокирующим системным вызовом, который заменяет вызывающий процесс , вот что execve
является. Это был бы системный вызов , который запускает подпроцесс вызова
process и возвращает статус завершения подпроцесса родительскому элементу . Тот, который делает это system