int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules);
一、PHP_OS 操作系统类型名字
php_os = PHP_OS;
PHP_OS是由configure生成的,其生成代码如下
PHP_OS=`uname | xargs`
cat >>confdefs.h <<_ACEOF
#define PHP_OS "$PHP_OS"
_ACEOF
也即执行linux命令: uname | xargs
执行结果如下
[root@localhost ~]# uname | xargs
Linux
module_shutdown = 0;
module_startup = 1;
sapi_initialize_empty_request();
sapi_activate();
二、sapi_initialize_empty_request 初始化本次请求的结构。
这个函数其实很简单,给一些变量初始化赋值
# define SG(v) (sapi_globals.v)
extern SAPI_API sapi_globals_struct sapi_globals;
SAPI_API void sapi_initialize_empty_request(void)
{
SG(server_context) = NULL;
SG(request_info).request_method = NULL;
SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
}
在之后的源码中,会大量看到类似这种SG的宏,这个其实就是各种全局结构的缩写。
三、sapi_activate 读取本次请求
由于我们是以cli方式启动的,所以这个函数调用,内部其实不会有什么变化, 内部的逻辑都不会调用。
四、php_output_startup 初始化输出
PHPAPI void php_output_startup(void)
{
ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL);
zend_hash_init(&php_output_handler_aliases, 8, NULL, NULL, 1);
zend_hash_init(&php_output_handler_conflicts, 8, NULL, NULL, 1);
zend_hash_init(&php_output_handler_reverse_conflicts, 8, NULL, reverse_conflict_dtor, 1);
php_output_direct = php_output_stdout;
}
第一行是初始化output_globals这个全局变量,这个变量的类型是zend_output_globals
#define ZEND_BEGIN_MODULE_GLOBALS(module_name) \
typedef struct _zend_##module_name##_globals {
#define ZEND_END_MODULE_GLOBALS(module_name) \
} zend_##module_name##_globals;
ZEND_BEGIN_MODULE_GLOBALS(output)
zend_stack handlers;
php_output_handler *active;
php_output_handler *running;
const char *output_start_filename;
int output_start_lineno;
int flags;
ZEND_END_MODULE_GLOBALS(output)
后面三行初始化三个array:
1. php_output_handler_aliases: 自定义输出函数列表
2. php_output_handler_conflicts:用来检查“自定义输出接口”重复的工具
3. php_output_handler_reverse_conflicts:目前内核未使用
最后一行将标准输出作为直接输出的方法。
static size_t php_output_stdout(const char *str, size_t str_len)
{
fwrite(str, 1, str_len, stdout);
return str_len;
}
五、php_startup_ticks 初始化定时器
struct st_tick_function
{
void (*func)(int, void *);
void *arg;
};
int php_startup_ticks(void)
{
zend_llist_init(&PG(tick_functions), sizeof(struct st_tick_function), NULL, 1);
return SUCCESS;
}
此定时器不同于通常意义的定时器,这个没有时间间隔的概念,每次只要调用,列表里面的成员都将调用一遍。
ZEND_API void zend_llist_apply_with_argument(zend_llist *l, llist_apply_with_arg_func_t func, void *arg)
{
zend_llist_element *element;
for (element=l->head; element; element=element->next) {
func(element->data, arg);
}
}
static void php_tick_iterator(void *d, void *arg)
{
struct st_tick_function *data = (struct st_tick_function *)d;
data->func(*((int *)arg), data->arg);
}
void php_run_ticks(int count)
{
zend_llist_apply_with_argument(&PG(tick_functions), (llist_apply_with_arg_func_t) php_tick_iterator, &count);
}
六、gc_globals_ctor 全局gc初始化,关于gc又是一个大话题,这里不展开。
void gc_globals_ctor(void)
{
gc_globals_ctor_ex(&gc_globals);
}
static void gc_globals_ctor_ex(zend_gc_globals *gc_globals)
{
gc_globals->gc_enabled = 0;
gc_globals->gc_active = 0;
gc_globals->gc_protected = 1;
gc_globals->gc_full = 0;
gc_globals->buf = NULL;
gc_globals->unused = GC_INVALID;
gc_globals->first_unused = GC_INVALID;
gc_globals->gc_threshold = GC_INVALID;
gc_globals->buf_size = GC_INVALID;
gc_globals->num_roots = 0;
gc_globals->gc_runs = 0;
gc_globals->collected = 0;
}
七、zend_startup 系统核心部分的初始化下一次再写。
本文深入解析PHP启动过程,包括操作系统的识别、初始化请求结构、激活SAPI、输出初始化、定时器初始化、GC全局初始化等关键步骤,为理解PHP运行机制提供详实资料。
&spm=1001.2101.3001.5002&articleId=89393699&d=1&t=3&u=f66f916b5a214e0f9b9da065e4c5d627)
923

被折叠的 条评论
为什么被折叠?



