Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > mod_perl и глобальные переменные


Автор: Ramirez 4.8.2007, 02:00
Кто знаком с сабжем, помогите расставить все по местам.

mod_perl-скрипты компилируются 1 раз на этапе загрузки веб-сервера (при условии что они грузятся через perlrequire в конфиге апача).
значит, если некий пакет создает глобальную переменную при иннициализации, она будет жива от начала запуска апача до его останова.
и доступна видимо будет всем процессам апача? эдакий "shared memory" получается?

из этого следует, видимо, что если я открою подключение к бд, например, и привяжу его к этой переменной, то оно тоже будет одно, на все процессы апача?

Я правильно себе представляю механизм?

С мод_перл я, скорее, на "вы", поэтому извиняюсь за сумбурное изложение...

Спасибо.

Автор: djkostya 4.8.2007, 08:08
Да с shared memory так и получиться....
Коннект постоянный лучше используйте Apache::DBI

Автор: Ramirez 6.8.2007, 17:15
Я такой фокус пытаюсь с Net::Telnet проделать. И получается, что он все равно плодит подключения на каждый процесс веб сервера. А мне хочется одного на всех добиться. Код примерно такой:

Код

package MyPack;

use strict;

use Apache2::Upload;
use Apache2::Request;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => qw(OK DECLINED NOT_FOUND DIR_MAGIC_TYPE);
use Apache2::ServerUtil ();

use Net::Telnet;

our $telnet;

sub somesub {
    .....
    unless ($telnet) {
        $telnet = Net::Telnet->new
        $telnet->open();
    }
    ....
}


В конфиге апача следующее:
Код

SetHandler perl-script
PerlInitHandler MyPack
PerlRequire /..../preload.perl


В preload.perl прописано: use MyPack;


Собственно, чего я ожидаю: при старте апача компилируется и загружается MyPack, в нем создается переменная $telnet, которая должна быть общая на все копии апача. Потом, при обработке запроса от клиента, вызывается процедура somesub и (при первом вызове) к этой переменой аттачится обьект Net::Telnet. Так как он глобальный, все последующие вызовы (в том числе и от других клиентов, других копий апача) не должны плодить новых коннектов (новых копий Net::Telnet).... а они плодят. Почему?

Вообще, проблема к Net::Telnet отношения не имеет, т.к. также ведет себя любая переменная: она всегда пустая при инициализации нового запроса. Т.е. модуль может и компилируется при старте апача, но инициализируется он каждый раз как-бы "с нуля". Видимо это происходит в тот момент когда отпочковывается новая копия апача, хотя больше похоже что вообще на каждый новый запрос.

PS: хотя вцелом - вполне логично... апач ведь копированием себя размножается.... поэтому сколько апачей - столько и коннектов =(
обкурился уже исходниками Apache::DBI, как оно работает?! обьясните кто нибудь "на пальцах" =) 

Автор: Ramirez 7.8.2007, 12:19
Вобщем, я заставил его работать так как мне хотелось, но несколько неожиданным способом:

в файле preload.perl, который указан в конфиге апача в директиве PerlRequire, сделал так:

Код

use MyPack;
use Net::Telnet;
$MyPack::telnet = Net::Telnet->new();
$MyPack::telnet->open();


и тогда, действительно, подключение создается одно, при старте апача, и оно общее для всех копий апача. Но почему это работает именно так, я что-то не до конца понимаю. Так что вопрос всетаки остается открытым.

Автор: ginnie 31.3.2008, 11:51
Уважаемый Ramirez, дело в том, что созданная Вами глобальная переменная является глобальной для всех процессов только на чтение, если какой-то процесс пишет в нее, то происходит COW (копирование при записи) и новое значение становится глобальным для этого процесса, остальные процессы видят первоначальное значение.
В последнем примере, значение глобальной переменной присваивается при компиляции, поэтому оно доступно всем процессам. 

Автор: Ramirez 31.3.2008, 12:08
Про копирование при записи я не занл, спасибо! Но непонятен мне несколько другой момент: почему пространство имен скомпилированое при старте внутри мастер-процесса "расшаривается" между потомками, именно расшаривается (может я плохо тестил?) т.е. потомки могут туда и писать и при этом все изменения видны. т.е. копирования не происходит. Это баг или фича? =) Опять-же повторюсь, может я плохо тестил. Сейчас попробую еще ряд экспериментов поставить.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)