Linux: разница между разветвлением дважды и демоном (ise)
Я пытался написать базовый многопроцессорный tcp-сервер, который разветвляет процесс для каждого нового accept().
Мне не нужен родительский процесс для ожидания дочерних процессов. Я сталкивался с двумя решениями - дважды раздваивать и демонизировать.
- Какая разница между этими двумя?
- Что больше подходит в этом сценарии?
- Какие факторы следует учитывать при выборе одного из них?
2 ответа
Есть небольшая разница.
Форкинг дважды: промежуточный дочерний процесс не может стать зомби при условии, что он завершился и его ожидал родительский процесс. Внук не может стать зомби, так как его родитель (промежуточный дочерний процесс) вышел, поэтому внук - сирота. Сирота (внука) наследуется init, и если она выходит сейчас, ответственность за ее очистку лежит на системе. Таким образом, родительский процесс освобождается от обязанности ожидания получения сигнала состояния выхода от дочернего процесса, а также родитель может быть занят выполнением какой-либо другой работы. Это также позволяет ребенку бегать в течение длительного времени, так что краткосрочному родителю не нужно ждать этого времени.
Демон: предназначен для программ, желающих отсоединиться от управляющего терминала и работать в фоновом режиме в качестве системных демонов. Не имеет управляющего терминала.
Решение подхода зависит от требования / сценария в руке.
Вам нужен родительский процесс, чтобы (в конце концов) wait()
для каждого из его дочерних процессов, иначе дети будут зависать, пока родитель не выйдет. Это форма утечки ресурсов.
Двойное форкирование с промежуточным процессом, выходящим сразу после разветвления, позволяет первоначальному процессу немедленно забрать ребенка (через wait()
) и превращает процесс внука в сироту, которого система несет ответственность за очистку. Это один из способов избежать накопления зомби-процессов. Внук остается в той же группе процессов (и, следовательно, в том же сеансе), что и исходный процесс.
Демонизация служит несколько иной цели. Он помещает полученный (дочерний) процесс в новый сеанс (и новую группу процессов) без управляющего терминала. Тот же самый эффект может быть достигнут путем разветвления, когда родитель немедленно вызывает _exit()
и ребенок зовет setsid()
,
Системная служба демонтируется, чтобы выйти из сеанса, в котором она была запущена, чтобы не закрываться по окончании этого сеанса. Это имеет мало общего с многопроцессорностью, но во многом связано с управлением процессами. Процесс удваивается, чтобы избежать обязанностей по управлению процессами для (больших) дочерних процессов; это имеет как многопроцессорность, так и аспекты управления процессами.
Также обратите внимание, что двойное разветвление не только выдает ответственность за управление процессами, но также лишает возможности управления процессами. Является ли это хорошим компромиссом, зависит от ситуации.