php tsrmg,php内核分析(二)-ZTS和zend_try

这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux

ZTS

我们会看到文章中有很多地方是:

#ifdef ZTS

# define CG(v) ZEND_TSRMG(compiler_globals_id, zend_compiler_globals *, v)

#else

# define CG(v) (compiler_globals.v)

extern ZEND_API struct _zend_compiler_globals compiler_globals;

#endif

这里的ZTS是个什么概念呢。我们经常使用的php都是运行在单进程,单线程环境,比如cgi,都是一个请求进来,就一个进程为它服务,当请求结束了,进程也就结束了。所以比如像全局变量,php内核就没有考虑多线程同时修改获取的时候线程安全问题。后来,php渐渐也在往单进程多线程服务器方向发展。那么这个时候,就会需要有一个层来专门处理线程安全问题。这个就是TSRM(Thread Safe Resource Management)。

但是php默认是关闭线程安全的。在编译的时候,你可以指定参数开启编译一个线程安全版本的php。(--enable-maintainer-zts 选项, Windows 平台为 --enable-zts)这个就是这里的ZTS的由来。

比如上面的例子,CG(V) 在非线程安全下获取的是全局结构compiler_globals结构的v属性,在线程安全下获取的是通过ZEND_TSREMG方法来获取。

zend_try

我们会看到zend_try_catch相关的代码如下:

zend_try {

...exec_try

} zend_catch {

...exec_catch

} zend_end_try();

把宏展开,我们可以看到大概代码如下:

{ \

JMP_BUF *__orig_bailout = EG(bailout); \

JMP_BUF __bailout; \

\

EG(bailout) = &__bailout; \

if (SETJMP(__bailout)==0) {

{

...exec_try

}

} else { \

EG(bailout) = __orig_bailout;

{

...exec_catch

}

} \

EG(bailout) = __orig_bailout; \

}

这个是什么意思呢,需要先理解下setjmp和longjmp,这两个函数是linux提供的方法。他们是组合起来使用的,达到协同程序的功能

#include

#include

jmp_buf env;

void foo() {

printf("before jmp\n");

int ret = setjmp(env);

if(ret == 0) {

return;

} else {

printf("return %d\n", ret);

}

printf("after jmp\n");

}

int main(int argc, char* argv[]) {

foo();

longjmp(env, 999);

return 0;

}

// 输出:

/*

before jmp

return 999

after jmp

*/

上面的这个例子,setjmp的时候相当于程序片段1把主动权交出来,然后执行if(ret == 0)下面的程序,直到遇到longjmp,把执行权还给了片段1,并且设置jmp_buf为999,片段1继续执行,发现了ret!=0,就输出return 999。

好了,回到这个程序:

{ \

JMP_BUF *__orig_bailout = EG(bailout); \

JMP_BUF __bailout; \

\

EG(bailout) = &__bailout; \

if (SETJMP(__bailout)==0) {

{

...exec_try

}

} else { \

EG(bailout) = __orig_bailout;

{

...exec_catch

}

} \

EG(bailout) = __orig_bailout; \

}

这个程序里面的exec_try代码段里面,在遇到错误的时候,需要返回的时候,就会包含一个longjmp函数的调用。这样,就形成了我们平时调用try...catch...finnal的功能:

1 先保存全局变量里面的bailout

2 使用setjmp来做跳转执行下面的程序

3 执行exec_try

4 如果exec_try这个代码段里面有longjmp,并且longjmp返回非0(一般也确实非0),就执行exec_catch

5 最后,把全局变量里面的bailout恢复

这里可能会有两个疑惑,如果exec_try里面没有longjmp怎么办,那就直接只执行了exec_try,就跳过exec_catch了。这个也是标准的用setjmp和longjmp实现try catch的写法。

这两个的实现弥补了goto关键字只能在函数内部进行跳转的限制。这个叫做“长跳转”。

所以在PHP代码中,如果你执行的函数有可能抛出异常。不妨使用这个方式把你要执行的程序放在里面。

参考

Linux内核启动代码分析二之开发板相关驱动程序加载分析

Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

Linux内核分析(二)----内核模块简介|简单内核模块实现

原文:Linux内核分析(二)----内核模块简介|简单内核模块实现 Linux内核分析(二) 昨天我们开始了内核的分析,网上有很多人是用用源码直接分析,这样造成的问题是,大家觉得很枯燥很难理解,从某 ...

“Linux内核分析”实验二报告

张文俊 + 原创作品转载请注明出处 + MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.第二周学习内 ...

Linux内核分析 笔记二 操作系统是如何工作的 ——by王玥

一.知识要点 1.计算机是如何工作的?(总结)——三个法宝 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算 ...

Linux内核分析作业二

贾瑗 + 原创作品转载请注明出处 + MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一.操作系统是如 ...

【MOOC EXP】Linux内核分析实验二报告

程涵  原创博客 MOOC课程http://mooc.study.163.com/course/USTC-1000029000  [操作系统是如何工作的]   教学内 ...

《Linux及安全》期中总结&《Linux内核分析》期终总结

[5216 原创作品转载请注明出处 MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK NINE ...

Linux内核分析 第二周

Linux内核分析——完成一个简单的时间片轮转多道程序内核代码 张潇月+MOOC课程http://mooc.study.163.com/course/USTC-100 ...

Linux内核分析——汇编代码执行及堆栈变化

张潇月MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验步骤 首先借助实验楼这个平台进入Linux ...

《Linux内核分析》期中总结

两个月Linux内核的学习,让我理解了Linux内核的基本工作原理,包括进程管理.内存管理.设备驱动.文件系统,从分析内核到了解整个系统是如何工作的.如何控制管理资源分配.进程切换并执行.各种策略和结 ...

随机推荐

搭建属于自己的VIP积分系统(1)

很久没写博客了,如果有写得不好的地方,还请多多见谅. 架构设计 需求分析 这篇文章主要是介绍此VIP系统的基础架构.说实在的,我其实对 架构方面也不是很懂,我这套框架 还是拿别人的东西改过来的,并不是 ...

QT操作EXCEL

介绍一下最基本的QT对EXCEL的读写操作. 声明:转载于:http://blog.csdn.net/czyt1988/article/details/52121360 在使用QT的操作数据库的时候, ...

hdu4273Rescue(三维凸包重心)

链接 模板题已不叫题.. 三维凸包+凸包重心+点到平面距离(体积/点积)  体积-->混合积(先点乘再叉乘) #include #include

ionic环境搭建及新建项目中的各种问题

具体流程可见http://bbs.ionic-china.com/read-7.html 问题1.安装ionic cordova失败 解决方法:修改npm的源,npm config set regis ...

JS中关于比较运算符的问题(a===b)

之前也会碰到a===b和a==b的表达式,但都没有仔细的看资料,今天看canvas有关的书中提到了,就mark一下: a == b    说明:a与b相等: a ===b  说明:a与b相同,并且类型 ...

用iPhone查看pc电脑上写的html(Mac电脑Charles)简单版

对于客户端同学开发来说,写一段代码想在真机上看看,是非常容易的. 那么在这么一个大前端的环境下,客户端开发想写点html和js代码,又想在手机上看看效果,怎么办呢? 需要以下几个步骤: 大体流程:1. ...

2015-10-27 C#3

三.字符串拼凑stringbuilder stringbuilder sb= new stringbuilder(); sb.append("aaa"); sb.append(&q ...

__new__方法和pop方法(判断)

new方法(构造方法)是在函数一加载的时候就被执行,在init方法执行之前被执行 def __new__(cls,*args,**kwargs): if kwargs.pop('many',False ...

Windows下安装Python模块时环境配置

“Win +R”打开cmd终端,如果直接在里面使用pip命令的时候,要么出现“syntax invalid”,要么出现: 'pip' is not recognized as an internal ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值