《PHP扩展开发及内核应用》学习笔记(一)
2018-03-16 16:19
429 查看
教程地址:PHP扩展开发及内核应用
PHP架构图
简单来说,就是Apache/Nginx启动后,PHP解释程序也随之启动(初始化一些环境变量用于整个SAPI生命周期,以及初始化只针对当前请求的一些变量设置),随着页面执行到页面执行完毕,PHP会自动unset掉各个变量,当请求结束后,关闭各个扩展,从而释放各个模块的内存。
接下来,就跟着教程,痛并快乐的学习下,PHP的生命周期到底是怎么样的。
PS:该文件一般位置/.local/share/Trash/files/php-7.1.11/sapi/cgi/
time_of_minit的值每次请求都不变。
time_of_rinit的值每次请求都改变。
每次页面请求都会往time_rshutdown.txt中写入数据。
只有在apache结束后time_mshutdown.txt才写入有数据。
1. 直接以CLI/CGI模式调用
2. 多进程模块
3. 多线程模
4. Embedded(嵌入式,在自己的C程序中调用Zend Engine)
3.1. 单进程SAPI生命周期
3.2. 多进程模式 & 多线程模式
多进程SPAI生命周期
多线程SAPI生命周期
简单解释下,多进程和多线程:
进程(process)是资源分配的最小单位,线程(thread)是处理机调度的最小单位。
一个进程可以有很多线程,每条线程并行执行不同的任务。
PHP是单进程执行的,但是当数据量比较大(例如:队列处理、日志分析、文件处理等)或者运行守护进程的时候,就需要依赖服务器或PHP-FPM的多进程及它们进程的复用。
通常PHP是编译为apache的一个模块来处理PHP请求。Apache一般会采用多进程模式,Apache启动后会fork出多个子进程,每个进程的内存空间独立,每个子进程都会经过开始和结束环节,不过每个进程的开始阶段只在进程fork出来以来后进行,在整个进程的生命周期内可能会处理多个请求。
只有在Apache关闭或者进程被结束之后才会进行关闭阶段,在这两个阶段之间会随着每个请求重复请求开始-请求关闭的环节。
多线程模式和多进程中的某个进程类似,不同的是在整个进程的生命周期内会并行的重复着 请求开始-请求关闭的环节。
全局变量,所有函数共享,因此所有的线程共享,不同线程中出现的不同变量都是这同一个变量。
静态全局变量,所有函数共享,也是所有线程共享。
局部变量,此函数的各次执行中涉及的这个变量没有联系,因此,也是各个线程间也是不共享的。
静态局部变量,本函数间共享,函数的每次执行涉及的这个变量都是同一个变量,因此,各个线程是共享的。
一、PHP的生命周期
PHP架构图
简单来说,就是Apache/Nginx启动后,PHP解释程序也随之启动(初始化一些环境变量用于整个SAPI生命周期,以及初始化只针对当前请求的一些变量设置),随着页面执行到页面执行完毕,PHP会自动unset掉各个变量,当请求结束后,关闭各个扩展,从而释放各个模块的内存。
接下来,就跟着教程,痛并快乐的学习下,PHP的生命周期到底是怎么样的。
1. SAPI
static sapi_module_struct cgi_sapi_module = { #if PHP_FASTCGI "cgi-fcgi", /* name */ "CGI/FastCGI", /* pretty name */ #else "cgi", /* name */ "CGI", /* pretty name */ #endif php_cgi_startup, /* startup,调用了PHP的初始化函数 */ php_module_shutdown_wrapper, /* shutdown,PHP关闭函数的简单封装 */ sapi_cgi_activate, /* activate,处理一些初始化,资源分配的事务 */ sapi_cgi_deactivate, /* deactivate,提供一个handler, 用来处理收尾工作 */ sapi_cgibin_ub_write, /* unbuffered write,这个hanlder告诉了Zend,如何输出数据 */ sapi_cgibin_flush, /* flush,提供给Zend的刷新缓存的函数句柄 */ NULL, /* get uid,让Zend可以验证一个要执行脚本文件的state,从而判断文件是否据有执行权限等等 */ sapi_cgibin_getenv, /* getenv,为Zend提供了一个根据name来查找环境变量的接口 */ php_error, /* error handler,错误处理函数 */ NULL, /* header handler,会在调用PHP的header()函数的时候被调用 */ sapi_cgi_send_headers, /* send headers handler,会在要真正发送header的时候被调用 */ NULL, /* send header handler,用来单独发送每一个header */ sapi_cgi_read_post, /* read POST data,这个句柄指明了如何获取post的数据 */ sapi_cgi_read_cookies, /* read Cookies,这个句柄指明了如何获取cookie的数据 */ sapi_cgi_register_variables, /* register server variables,用以给$_SERVER变量中添加变量 */ sapi_cgi_log_message, /* Log message,用来输出错误信息 */ NULL, /* Get request time */ NULL, /* Child terminate */ STANDARD_SAPI_MODULE_PROPERTIES };
PS:该文件一般位置/.local/share/Trash/files/php-7.1.11/sapi/cgi/
2. PHP的启动与终止
下面直接引用原文中的代码,简单明了,清晰易懂。//这些代码都在walu.c里面,不再.h里 int time_of_minit;//在MINIT中初始化,在每次页面请求中输出,看看是否变化 PHP_MINIT_FUNCTION(walu) { time_of_minit=time(NULL);//我们在MINIT启动中对他初始化 return SUCCESS; } int time_of_rinit;//在RINIT里初始化,看看每次页面请求的时候变不。 PHP_RINIT_FUNCTION(walu) { time_of_rinit=time(NULL); return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(walu) { FILE *fp=fopen("/cnan/www/erzha/time_rshutdown.txt","a+");//请确保文件可写,否则apache会莫名崩溃 fprintf(fp,"%d\n",time(NULL));//让我们看看是不是每次请求结束都会在这个文件里追加数据 fclose(fp); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(walu) { FILE *fp=fopen("/cnan/www/erzha/time_mshutdown.txt","a+");//请确保文件可写,否则apache会莫名崩溃 fprintf(fp,"%d\n",time(NULL)); return SUCCESS; } //我们在页面里输出time_of_minit和time_of_rinit的值 PHP_FUNCTION(walu_test) { php_printf("%d<br />",time_of_minit); php_printf("%d<br />",time_of_rinit); return; }
time_of_minit的值每次请求都不变。
time_of_rinit的值每次请求都改变。
每次页面请求都会往time_rshutdown.txt中写入数据。
只有在apache结束后time_mshutdown.txt才写入有数据。
3. PHP的生命周期
一个PHP实例,无论是从init脚本中调用的,还是从命令行启动的,都会向我们上一节说的那样, 依次进行Module init、Request init、Request Shutdown、Module shutdown四个过程, 当然之间还会执行脚本自己的逻辑。 那么两种init和两种shutdown各会执行多少次、各自的执行频率有多少呢? 这取决与PHP是用什么sapi与宿主通信的。最常见的四种方式如下所列:1. 直接以CLI/CGI模式调用
2. 多进程模块
3. 多线程模
4. Embedded(嵌入式,在自己的C程序中调用Zend Engine)
3.1. 单进程SAPI生命周期
3.2. 多进程模式 & 多线程模式
多进程SPAI生命周期
多线程SAPI生命周期
简单解释下,多进程和多线程:
进程(process)是资源分配的最小单位,线程(thread)是处理机调度的最小单位。
一个进程可以有很多线程,每条线程并行执行不同的任务。
PHP是单进程执行的,但是当数据量比较大(例如:队列处理、日志分析、文件处理等)或者运行守护进程的时候,就需要依赖服务器或PHP-FPM的多进程及它们进程的复用。
通常PHP是编译为apache的一个模块来处理PHP请求。Apache一般会采用多进程模式,Apache启动后会fork出多个子进程,每个进程的内存空间独立,每个子进程都会经过开始和结束环节,不过每个进程的开始阶段只在进程fork出来以来后进行,在整个进程的生命周期内可能会处理多个请求。
只有在Apache关闭或者进程被结束之后才会进行关闭阶段,在这两个阶段之间会随着每个请求重复请求开始-请求关闭的环节。
多线程模式和多进程中的某个进程类似,不同的是在整个进程的生命周期内会并行的重复着 请求开始-请求关闭的环节。
4. 线性安全
在多线程中,多个线程共享除函数调用栈之外的其他资源。 各种变量的作用域从定义来看如下:全局变量,所有函数共享,因此所有的线程共享,不同线程中出现的不同变量都是这同一个变量。
静态全局变量,所有函数共享,也是所有线程共享。
局部变量,此函数的各次执行中涉及的这个变量没有联系,因此,也是各个线程间也是不共享的。
静态局部变量,本函数间共享,函数的每次执行涉及的这个变量都是同一个变量,因此,各个线程是共享的。
相关文章推荐
- 推广一下《PHP扩展开发及内核应用》,经典好书,翻译完成。
- 《PHP扩展开发及内核应用》
- php扩展开发与内核应用
- 《PHP扩展开发及内核应用》目录
- PHP扩展开发与内核应用阅读笔记---php的生命周
- 《PHP扩展开发及内核应用》目录
- 《PHP扩展开发及内核应用》学习笔记(二)
- PHP7扩展开发及内核应用开发发布中
- 编写php扩展(二)构建扩展中的函数的说明之PHP扩展开发及内核应用之阅读笔记(一)
- 《PHP扩展开发及内核应用》读书笔记(更新到第3章)
- PHPER必读电子书推荐-《PHP扩展开发及内核应用》
- PHP扩展开发与内核应用阅读笔记---php的作用域以及如何在扩展中定义,查找php变量
- PHP扩展开发及内核应用
- 《PHP扩展开发及内核应用》
- PHP扩展开发与内核应用阅读笔记---php的内存管理
- PHP扩展开发及内核应用
- PHP扩展开发及内核应用
- PHP扩展开发与内核应用
- PHP内核介绍及扩展开发指南—Extensions 的编写
- PHP扩展开发-内核执行流程与扩展结构