Я работаю над некоторым кодом Python, смоделированным на сервере Prefork Apache MPM. Я больше программист приложений, чем сетевой программист, и прошло уже 10 лет с тех пор, как я прочитал "Стивенс", поэтому я стараюсь ускорить понимание кода.
Я нашел краткое описание как работает код предпродажа Apache, Sander Temme.
Родительский процесс, который обычно запускается как root, привязывается к сокету (обычно порт 80 или 443). Он порождает детей, которые наследуют открытый файловый дескриптор для сокета и изменить uid и gid на непривилегированный пользователь и группа. Дети строят опрос дескрипторов файла прослушивателя (если имеется более одного слушателя) и следите за действиями на нем/их. Если действие найдено, ребенок вызывает accept() в активном сокете и обрабатывает соединение. Когда он является с этим, он возвращается к просмотру pollset (или файла прослушивателя дескриптор).
Поскольку несколько детей активны, и все они унаследованы одинаково дескриптор файла сокета, они будут наблюдать за тем же самым опросом. Мьютекс accept позволяет только одному ребенку фактически наблюдать за опросом, и как только он найдет активный сокет, он откроет мьютекс, чтобы следующий ребенок может начать наблюдать за опросом. Если есть только один слушатель, который принимает мьютекс, не используется, и все дети будут принимаем().
Это в значительной степени способ, которым я смотрю на работу, но я не понимаю нескольких вещей.
1) В чем разница между "ребенком" и "слушателем"? Я думал, что каждый ребенок является слушателем, что верно для кода, на который я смотрю, но в описании Temme может быть "один слушатель" и "дети". Когда у ребенка будет несколько слушателей?
2) (Связано с 1) Является ли это мьютексом для каждого процесса или мьютексом системы? В этом отношении, почему есть мьютекс? Не принимает (2) делать свои собственные мьютексы для всех слушателей? Мои исследования говорят, что мне нужен мьютекс и что мьютекс должен быть через всю систему. (стадо, семафор и т.д.)
Далее Temme говорит:
Запись детей в общей памяти (табло), когда они в последний раз подал запрос. Неработающие дети могут быть убитым родительским процессом до удовлетворяют требованиям MaxSpareServers. Если слишком мало дети простаивают, родитель порождать детей, чтобы удовлетворить MinSpareServers.
3) Есть ли хороший код для этой реализации (желательно на Python)? Я нашел Perl Net:: Server:: Prefork, в котором вместо таковой используются каналы вместо общей памяти. Я нашел статью Рэндала Шварца, которая только делает предпродак, но не делает табло.
Пример pre-fork из Perl Cookbook не имеет какой-либо блокировки для выбора и Пример Python Chris Siebenmann говорит, что он основан на Apache, но использует парные сокеты для табло, а не разделяемую память, и использует сокеты для элементов управления, включая элемент управления для данного дочернего элемента 'a' ccept. Это совсем не совпадает с описанием Apache.