Последовательность инициализации и сброса в расширениях PHP
Хозяйке на заметку
Я сейчас занимаюсь написанием расширения PHP, которое меняет UID/EUID (а также GID/EGID) процесса PHP-интерпретатора на UID/GID владельца DocumentRoot сайта. При этом по замыслу расширение должно отключаться, если SAPI не используется (например, запущена CLI-версия интерпретатора).
Для этой задачи оказалось важным знать точную последовательность инициализации и финализации.
Те, кто разрабатывал расширения для PHP, знают, что функции инициализации/финализации задаются структурой zend_module_entry, например:
STANDARD_MODULE_HEADER_EX,
NULL,
NULL,
PHP_CHUID_EXTNAME,
NULL,
PHP_MINIT(chuid), /* Module init*/
PHP_MSHUTDOWN(chuid), /* Module shutdown */
PHP_RINIT(chuid), /* Request init */
PHP_RSHUTDOWN(chuid), /* Request shutdown */
PHP_MINFO(chuid),
PHP_CHUID_EXTVER,
PHP_MODULE_GLOBALS(chuid),
PHP_GINIT(chuid), /* Globals init */
PHP_GSHUTDOWN(chuid), /* Globals shutdown */
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
Инициализация происходит при этом в таком порядке:
GINIT— инициализация глобальных переменных;MINIT— инициализация расширения;RINIT— инициализация перед обработкой запроса.
Разрушение, соответственно, происходит в обратном порядке: RSHUTDOWN, MSHUTDOWN, GSHUTDOWN. Всё просто.
Однако у программиста есть возможность установить свой обработчик для фазы SAPI Activate/SAPI Deactivate (обычно это делается во время MINIT):
int (*php_cgi_sapi_deactivate)(TSRMLS_D) = NULL;
static int sapi_cgi_activate(TSRMLS_D)
{
printf("SAPI activate\n");
if (php_cgi_sapi_activate) {
return php_cgi_sapi_activate(TSRMLS_C);
}
return SUCCESS;
}
static int sapi_cgi_deactivate(TSRMLS_D)
{
printf("SAPI deactivate\n");
if (php_cgi_sapi_deactivate) {
return php_cgi_sapi_deactivate(TSRMLS_C);
}
return SUCCESS;
}
static PHP_MINIT_FUNCTION(chuid)
{
REGISTER_INI_ENTRIES();
php_cgi_sapi_activate = sapi_module.activate;
php_cgi_sapi_deactivate = sapi_module.deactivate;
sapi_module.activate = sapi_cgi_activate;
sapi_module.deactivate = sapi_cgi_deactivate;
return SUCCESS;
}
printf() всё же лучше не использовать, но в качестве примера сойдёт
И вот тут-то начинается самое интересное.
При запуске PHP (я использовал php-cgi) получается такая картина:
GINIT;MINIT;SAPI deactivate— вот оно!
Получается, что SAPI Deactivate вызывается до SAPI Activate, что не вполне очевидно, особенно для новичка
Последовательность обработки запросов остаётся практически той же:
SAPI activate;RINIT;RSHUTDOWN;SAPI deactivate.
При завершении процесса (именно процесса, а не запроса — ибо один процесс может обработать несколько запросов — это зависит от значения переменной окружения PHP_FCGI_MAX_REQUESTS) будут вызваны MSHUTDOWN и RSHUTDOWN — и никаких лишних SAPI (De)activate.
Авг
2009
Комментарии к статье «Последовательность инициализации и сброса в расширениях PHP» »
Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.
Оставить комментарий к записи «Последовательность инициализации и сброса в расширениях PHP»
गते गते पारगते पारसंगते बोधि स्वाहा
Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.

