php得到服务器时间(php得到服务器时间数据)「php获取服务器时间」

(点击上方公众号,可快速关注)

  作者:叶剑峰

  链接:www.cnblogs.com/yjf512/p/6092708.html

PHP内核分析(1):sapi_module_struct

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

  ZTS

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

  #ifdefZTS

  #defineCG(v)ZEND_TSRMG(compiler_globals_id,zend_compiler_globals*,v)

  #else

  #defineCG(v)(compiler_globals.v)

  externZEND_APIstruct_zend_compiler_globalscompiler_globals;

  #endif

  这里的ZTS是个什么概念呢。我们常常利用的php都是运行在单进程,单线程环境,比如cgi,都是一个哀求进来,就一个进程为它服务,当哀求竣事了,进程也就竣事了。以是比如像全局变量,php内核就没有思量多线程同时修改获取的时间线程安全题目。厥后,php渐渐也在往单进程多线程服务器方向发展。那么这个时间,就会必要有一个层来专门处理惩罚线程安全题目。这个就是TSRM(ThreadSafeResourceManagement)。

  但是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();

php获得服务器时间(php获得服务器时间数据) php得到
服务器时间(php得到
服务器时间数据)「php获取服务器时间」 行业资讯

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

  {

  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_bufenv;

  voidfoo(){

  printf("beforejmpn");

  intret=setjmp(env);

  if(ret==0){

  return;

  }else{

  printf("return%dn",ret);

  }

  printf("afterjmpn");

  }

  intmain(intargc,char*argv[]){

  foo();

  longjmp(env,999);

  return0;

  }

  //输出:

  /*

  beforejmp

  return999

  afterjmp

  */

php获得服务器时间(php获得服务器时间数据) php得到
服务器时间(php得到
服务器时间数据)「php获取服务器时间」 行业资讯

  上面的这个例子,setjmp的时间相称于程序片断1把主动权交出来,然后实行if(ret==0)下面的程序,直到碰到longjmp,把实行权还给了片断1,而且设置jmp_buf为999,片断1继承实行,发现了ret!=0,就输出return999。

  好了,回到这个程序:

  {

  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实现trycatch的写法。

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

  以是在PHP代码中,假如你实行的函数有大概抛出非常。不妨利用这个方式把你要实行的程序放在内里。

  参考

  https://blog.lucode.net/skills/talk-about-setjmp-and-longjmp.html

关注「PHP开辟者」

看更多精选PHP技能文章

↓↓↓

客户评论

我要评论