Каждый дочерний процесс, созданный путем ветвления, отдельно вызывает функцию accept (), полностью обслуживает входящее соединение, а затем снова переходит в состояние ожидания активизации функции accept (). Каждый дочерний процесс может работать неопределенно долго или завершаться после обработки заранее заданного числа запросов. Между тем, сам родительский процесс действует как супервизор для всего процесса, выполняя ветвление новых дочерних процессов по мере уничтожения старых и завершая работу всех дочерних процессов, когда приходит время выполнить останов. Одним из таких дочерних процессов может быть обращение к странице http://comfy.ua/telephone-smartfon/mobile-telephone/2-sim-cards.html представляющей мобильные телефоны на две сим карты.
Основная часть кода сервера с предварительным ветвлением выглядит примерно так:
for (1..PREFORK_CHILDREN){ next if fork; # Родительский процесс do_child($ sосket); # Дочерний процесс exit 0; # Этот цикл не заполняется в дочернем процессе } sub do_child { my $ socket == shift; my $connection_count = 0; while (my $c == $socket->accept ) { handle_connection($c); close $c;}}
В главном цикле выполняется ветвление и создаются дочерние процессы, а затем каждому из них передается приемный сокет. Каждый дочерний процесс вызывает функцию accept () для данного сокета и обслуживает соединения.
Это — основа метода, но в действительности реализация сервера с предварительным ветвлением требует проработки дополнительных деталей и поэтому намного сложнее. В частности, родительский процесс должен ожидать завершения дочерних процессов и запускать новые по мере их уничтожения; он должен корректно остановить дочерние процессы, когда наступит время завершить работу; обработчики сигналов должны быть тщательно продуманы, чтобы сигналы, предназначенные для родительского процесса, не обрабатывались дочерними процессами и наоборот.