邢栋博客
邢栋博客,Action博客,记录工作和生活中的点点滴滴
php7内核读书笔记-第二章 SAPI
php-fpm的worker进程和master进程
worker进程-处理请求
每个worker进程会竞争地Accept请求,接收成功后解析fastcgi,然后执行相应的脚本,处理完成后关闭请求,继续等待新的连接,这个就是一个worker进程的生命周期。
1.等待请求
2.解析请求
fastcgi请求到达后被worker接收,然后开始接收并解析请求数据,知道request数据完全到达
3.请求初始化
4.执行php脚本
5.关闭请求
master进程-管理进程
三种不同的进程管理模式
1.静态模式static
2.动态模式dynamic 默认
3.按需模式ondemand
信号
1.SIGINT/SIGTERM/SIGQUIT
退出fpm在master收到退出信号后将向所有的worker进程发布退出信号,通知worker退出,然后master退出
2.SIGUSR1
重新加载日志文件
3.SIGUSR2
重启fpm,首先master也是回向所有的worker进行发出退出信号,等全部worker成功退出后,master会调用execvp()重新启动一个新的fpm,最后旧的master退出
4.SIGCHLD
worker进程-处理请求
每个worker进程会竞争地Accept请求,接收成功后解析fastcgi,然后执行相应的脚本,处理完成后关闭请求,继续等待新的连接,这个就是一个worker进程的生命周期。
1.等待请求
2.解析请求
fastcgi请求到达后被worker接收,然后开始接收并解析请求数据,知道request数据完全到达
3.请求初始化
4.执行php脚本
5.关闭请求
master进程-管理进程
三种不同的进程管理模式
1.静态模式static
2.动态模式dynamic 默认
3.按需模式ondemand
信号
1.SIGINT/SIGTERM/SIGQUIT
退出fpm在master收到退出信号后将向所有的worker进程发布退出信号,通知worker退出,然后master退出
2.SIGUSR1
重新加载日志文件
3.SIGUSR2
重启fpm,首先master也是回向所有的worker进行发出退出信号,等全部worker成功退出后,master会调用execvp()重新启动一个新的fpm,最后旧的master退出
4.SIGCHLD
php7的生命周期
标签:
php生命周期
1.模块初始化阶段(module startup)
这个阶段主要进行php框架、zend引擎的初始化操作。该阶段的入口函数为php_module_startup(),这个阶段一般是在SAPI启动时执行一次,对于FPM而言,就是在fpm的master进行启动时执行的。该阶段的几个主要处理如下所诉:
1.激活SAPI:sapi_activate(),初始化请求信息SG(request_info)、设置读取POST请求的handel等,在module_startup阶段处理完成后将调用sapi_activate()
2.启动php输出 php_output_startup
3.初始化垃圾回收期:gc_globals_ctor(),分配zend_gc_globals内存
4.启动Zedn引擎 zend_startup,主要操作包括:
a.启动内存池 start_memory_manager()
b.设置一些util函数句柄(如zend_error_cb.zend_printf.zend_write)
c.设置Zend虚拟机编译、执行器的函数句柄zend_compile_file,zend_execute_ex,以及垃圾回收的函数句柄gc_collect_cycles
d.分配函数符号表(CG(function_table))、类符号表(CG(class_table))、常量符号表(EG(zend_constants))等,如果是多线程的话,还会分配编译器、执行器的全局变量
e.注册zend核心扩展:zend_startup_builtin_functions(),这个扩展是内核提供的,该过程将注册zend核心扩展提供的函数,比如strlen.define.func_get_args.class_exists等
f.注册zend定义的标准常量:zend_register_standard_constants(),比如E_ERROR.E_WARNING.E_ALL.TRUE.FALSE等
g.注册$GLOBALS超全局变量的获取handler
h.分配php.ini配置的存储符号表 EG(ini_directives)
5.注册php定义的常量,PHP_VERSION.PHP_ZTS.PHP_SAPI等
6.解析php.ini,解析完成后所有的php.ini配置保存在configuration_hash哈希表中。
7.映射php、zend核心的php.ini配置:根据解析出的php.ini,获取对应的配置值,将最终的配置插入EG(ini_directives) 哈希表
8.注册用户获取$_GET.$_POST.$_COOKIE.$_SERVER.$_ENV.$_REQUEST.$_FILES变量的handler
9.注册静态编译的扩展:php_register_internal_extensions_func()
10.注册动态加载的扩展:php_ini_register_extensions(),将php.ini中配置的扩展加载到php中
11.回调各扩展定义的module startup钩子函数,即通过PHP_MINT_FUNCTION()定义的函数
12.注册php.ini中禁用的函数、类,disable_functions.disbale_classes.
2.请求初始化阶段(request startup)
该阶段是在请求处理前每一个请求都会经历的一个阶段,对于fpm而言,是在worker进程accept一个请求并读取、解析完请求数据后的一个阶段。该阶段的处理函数为php_request_startup()
主要的处理有以下几个:
1.激活输出:php_output_activate()
2.激活zend引擎 zend_activate,主要操作如下所述
a.重置垃圾回收器 gc_reset()
b.初始化编译器:init_compiler()
c.初始化执行器:init_executor,将EG(function_table)、EG(clas_table)分配指向CG(function_table)、CG(class_table),所以在php的编译、执行同期,EG(function_table)与CG(function_table)、EG(clas_table)与CG(class_table)是同一个值;另外还会初始化全局变量符号表EG(symbol_table)、include过的文件符号表EG(included_files);
d.初始化词法扫描器:startup_scanner()
f.激活SAPI:sapi_activate()
g.回调各扩展定义的request startup钩子函数 zend_activate_modules()
3.执行脚本阶段(execute script)
该极端包括php代码的编译、执行两个核心阶段,这也是zend引擎最重要的功能。在编译阶段,php脚本将经历从php源代码抽象语法树再到opline指令的转化过程,最终生成的opline指令就是zend引擎可识别的执行指令,这些指令接着被执行器执行,这就是php代码解释执行的过程。这个接口的入口函数为php_execute_script()
4.请求关闭阶段(request shutdown)
在php脚本执行解释器执行完成后将进入请求关闭阶段,这个阶段将flush输出内容、发送http应答header头、清理全局变量、关闭编译器、关闭执行器等。另外,在该阶段将回调各扩展的request shutdown钩子函数。该阶段是请求初始化阶段的相反操作,与请求初始化时的处理一一对应
5.模块关闭阶段(module shutdown)
该阶段在SAPI关闭时执行,与模块初始化阶段对应,这个阶段主要是进行资源的清理、php各模块的关闭操作,同时,将回调各扩展的module shutdown钩子函数。具体的处理函数为 php_module_shutdown()
php7内核读书笔记-第一章 php基础架构
标签:
php7
php7的变化
1.抽象语法树
2.Native TLS(线程局部存储)
使用Native TLS来保存线程的资源池,线程独享。
3.指定函数参数、返回值类型
4.zval结构的变化
php7将引用计数转移到了具体的value中。zval结构大小从24字节减少到了16字节
5.异常处理
6.HashTable变化
php中数组类型的内部实现结构。HashTable结构的大小从72字节减小到了56字节,数组元素Bucket结构也从72字节减小到了32字节
7.新的参数解析方式
1.抽象语法树
2.Native TLS(线程局部存储)
使用Native TLS来保存线程的资源池,线程独享。
3.指定函数参数、返回值类型
4.zval结构的变化
php7将引用计数转移到了具体的value中。zval结构大小从24字节减少到了16字节
5.异常处理
6.HashTable变化
php中数组类型的内部实现结构。HashTable结构的大小从72字节减小到了56字节,数组元素Bucket结构也从72字节减小到了32字节
7.新的参数解析方式
创建一个简单的php7扩展
Php版本:7.0.0
首先进入php源码 ext 目录下
执行./ext_skel --extname=foobar //foobar为我要创建的扩展模块
执行完毕后
cd ext/foobar/
vim config.m4
16 dnl PHP_ARG_ENABLE(foobar, whether to enable foobar support, 17 dnl Make sure that the comment is aligned: 18 dn1 [ --enable-foobar Enable foobar support])
把16、17、18行的dn1去掉,修改为
16 PHP_ARG_ENABLE(foobar, whether to enable foobar support, 17 Make sure that the comment is aligned: 18 [ --enable-foobar Enable foobar support])
然后 vim foobar.c
找到
PHP_FUNCTION(confirm_foobar_compiled)
{
..............
}
在后面添加
PHP_FUNCTION(flyhello) { zend_string *strg; strg = strpprintf(0, "hello world."); RETURN_STR(strg); }
然后找到
const zend_function_entry foobar_functions[] = { PHP_FE(confirm_foobar_compiled, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in foobar_functions[] */ };
修改为
const zend_function_entry foobar_functions[] = { PHP_FE(flyhello,NULL) PHP_FE(confirm_foobar_compiled, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in foobar_functions[] */ };
然后重新编译执行后,执行php -m 就可以看到foobar模块
新建php文件,内容<?Php echo flyhello();?> 执行后输出hello world.
关于php的JIT
关于php的JIT
php是解释执行的,它的编译过程是属于动态编译,也就是在运行的时候进行编译,与之相对的事运行前编译的静态编译。动态编译与静态编译除了编译时机的不同,还有一个不同之的地方,那就是静态编译是将代码编译成了机器指令,而动态编译并没有编译为机器指令,而是编译成了解释器可识别的指令。即时编译,即just-in-time complication,简称JIT。JIT是动态编译中的一种技术,简单的讲,就是在某段代码第一次执行前进行编译,所以称为即时编译。
与解释执行不同的事,JIT是将源代码编译为机器指令执行,但JIT又与静态编译不同,它是在运行时实时进行的编译,而且JIT并不会把所有代码全部编译为机器码,它只会编译频繁执行的代码。说JIT比解释快,其实说的是"执行编译后的代码"比"解释器解释执行"要快,并不是说编译比解释的过程快,而且JIT编译通常比解释执行要慢一些,如果对执行一次的代码进行即时编译,其效率反而要比解释执行慢,JIT之所以快是因为多次执行抵消了编译所占的世界,显得平均效果高而已。
php的mcrypt加密类
<?php class McryptModel { protected $td = ''; protected $iv = ''; protected $key = ''; private static $instance = null; private function __construct($cipher,$mode,$key) { $this->cipher = $cipher; $this->mode = $mode; $this->key = $key; } public static function getInstance($cipher=MCRYPT_RIJNDAEL_128,$mode=MCRYPT_MODE_CBC,$key='xingdong365') { if(self::$instance === null){ self::$instance = new self($cipher,$mode,$key); } return self::$instance; } public function encrypt($str) { $td = mcrypt_module_open($this->cipher,'',$this->mode,'');//打开算法模块 $this->td = $td; $iv_size = mcrypt_enc_get_iv_size($td);//获取向量大小 $iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);//初始化向量 $this->iv = $iv; $num = mcrypt_generic_init($td,$this->key,$iv);//初始化加密空间 $encrypt = mcrypt_generic($td,$str);//执行加密 mcrypt_generic_deinit($td);//结束加密,执行清理工作 return base64_encode($encrypt); } public function decrypt($str) { $str = base64_decode($str); $td = $this->td; mcrypt_generic_init($td,$this->key,$this->iv); $decrypt = mdecrypt_generic($td,$str); mcrypt_generic_deinit($td); mcrypt_module_close($td);//关闭算法模块 return $decrypt; } } $m = McryptModel::getInstance(); echo $e = $m->encrypt('hello'); echo "<hr>"; echo $m->decrypt($e); //des加密 function des_encrypt($encrypt, $key='xingdong365'){ $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB),MCRYPT_RAND); $passcrypt = mcrypt_encrypt(MCRYPT_DES ,$key, $encrypt, MCRYPT_MODE_ECB, $iv); $resturn = base64_encode($passcrypt); return $resturn; } //des解密 function des_decrypt($decrypt, $key='xingdong365'){ $decoded = base64_decode($decrypt); $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB),MCRYPT_RAND); $resturn = mcrypt_decrypt(MCRYPT_DES ,$key, $decoded, MCRYPT_MODE_ECB, $iv); return $resturn; }
php使用redis替换文件存储session(session_set_save_handler)
<?php class MySessionHandler implements SessionHandlerInterface { private $redis; private $sessionsavepath; private $sessionname; public function __construct() { $this->redis = new Redis(); $this->redis->connect('127.0.0.1',6379); } public function close() { return true; } public function destroy($session_id) { if($this->redis->delete($session_id)){ return true; } return false; } public function gc($maxlifetime) { return true; } public function open($sessionsavepath, $name) { return true; } public function read($session_id) { if($value = $this->redis->get($session_id)){ return $value; }else{ return false; } } public function write($session_id, $session_data) { if($this->redis->set($session_id,$session_data,60)){ return true; }else{ return false; } } } $handler = new MySessionHandler(); session_set_save_handler($handler, true); session_start(); //$_SESSION['sess_name'] = 'xd'; var_dump($_SESSION);
php生成随机验证码
<?php function getVerifyCode($num){ $content = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $content = str_shuffle($content); return substr($content,-$num); } echo getVerifyCode(4);