Прежде всего, немного терминологии.
Исполняемый файл - это простой файл в вашей системе. Процесс - это оболочка, которая выполняет программу, встроенную в исполняемый файл.
Вы правы относительно способа запуска исполняемого файла:
- Сам родительский процесс (уже живущий)
fork
s, ведущий в два потока выполнения от этой точки. Один живет в родительском процессе, а другой - в новом новом процессе.
- Новый (дочерний) процесс отключает себя, чтобы выполнить программу исполняемого файла для запуска. Это делается с помощью системного вызова из семейства
exec
.
На примере графического интерфейса, в котором вы дважды щелкаете значок исполняемого файла, ваш исполняемый файл разветвляется из процесса, показывая значок, на который вы щелкнули, в основном с этим исходным кодом:
const char *exe_path = taken_from_icon();
int pid = fork();
if(pid == 0)
{
// I am the new child
execl(exe_path, exe_path, NULL);
// exec only return in case of failure
exit(EXIT_FAILURE);
}
// I am the graphical interface,
// Continue and wait for another clic
Но смерть и родительство ребенка не совсем так, как вы говорите.
В основном - и когда родительский процесс еще жив - дочерний процесс является дочерним по отношению к своему отцу (да! -). У него есть свой PPID (идентификатор родительского процесса), установленный на еще живой процесс, который его разветвил.
Все меняется, когда родительский процесс умирает. Дочерний процесс продолжает жить, но его PPID установлен на еще живущий процесс gran-parent. Всегда есть один, так как процесс init
никогда не умирает.
Тот факт, что дочерние оболочки умирают, когда умирает сама оболочка, является чем-то конкретным. Я вижу две причины для этого:
Первый: оболочка обычно поддерживает список PID, которые она разветвляет. И когда оболочка умирает, она убивает их всех. Основные оболочки имеют встроенную команду disown
чтобы удалить дочернего элемента из этого списка и оставить его в живых после смерти оболочки. Смотрите страницу руководства bash:
Оболочка выходит по умолчанию при получении SIGHUP. Перед выходом интерактивная оболочка отправляет SIGHUP всем работам, запущенным или остановленным. Остановленные задания отправляются SIGCONT, чтобы гарантировать получение SIGHUP. Чтобы командная оболочка не отправляла сигнал на конкретное задание, его следует удалить из таблицы заданий с помощью встроенной команды disown (см. Ниже КОМАНДЫ СОСТАВЛЕНИЯ ОБОЛОЧКИ) или отметить, чтобы она не получала SIGHUP с помощью команды disown -h.
Второй: у дочерних оболочек обычно stdin, stdout и stderr связаны с самой оболочкой через каналы. Если оболочка перестает использовать дочерний стандартный вывод (часто для его печати) или закрывает конец канала, дочерний процесс может иметь ошибки при записи в стандартный вывод, которые могут заблокировать или уничтожить его.