From cc348e5648a97219b96e37ee1e0f9ebf51a5b814 Mon Sep 17 00:00:00 2001 From: walu Date: Fri, 16 Nov 2012 14:44:46 +0800 Subject: [PATCH 1/5] unfinished, have sth to do and go out now. --- build.php | 75 +++++++++++-------------------------------------------- 1 file changed, 15 insertions(+), 60 deletions(-) diff --git a/build.php b/build.php index 85de45a..73b87f2 100644 --- a/build.php +++ b/build.php @@ -1,48 +1,10 @@ array( - 'id'=>'1.1', - 'title'=>'', - 'prev'=>'', - 'next', - 'content' - ) - ) -*/ -$c = array(); - //获取文件列表 -$file_list = glob("*.txt"); +$file_list = glob("*.md"); /* 章节号转成key @@ -50,29 +12,22 @@ function page_link($id) */ foreach($file_list as $value) { - $id = basename($value,".txt"); + $id = basename($value,".md"); $key = id2key($id); - - //开始读这篇文章 - $page = file_get_contents($value); - $tmp = strpos($page,"#"); - if($tmp === false) - { - trigger_error("{$value}文件没有meta信息",E_USER_ERROR); - } - - $repeat_count = 1; - - $meta = substr($page,0,strpos($page,"#")+1); - $content = str_replace($meta,"",$page,$repeat_count); - - $meta = trim($meta,"#"); - $meta = preg_split("![\\n\\r]+!",trim($meta)); - if(count($meta)!=3) - { - trigger_error("{$value}文件的meta信息不全",E_USER_ERROR); - } + + $body = file($value); + + $h1 = ''; + + foreach ($body as $k=>$v) { + if (preg_match('!^#([^#])$!', $v, $m)) { + $h1 = $m[1]; + unset($body[$k]); + } elseif (preg_match('!^## links!', $v, $m)) { + //接下来的两行是link + } + } //对content的code部分进行处理 $content = preg_replace_callback( From 7ff4c7f5af94a26e06ecbc6ec6e982f30ab82e59 Mon Sep 17 00:00:00 2001 From: walu Date: Tue, 20 Nov 2012 20:23:44 +0800 Subject: [PATCH 2/5] prepare to transfer from sae to vps. --- 1.1.md | 2 - 1.2.md | 8 +- 1.3.md | 36 ++++++--- 1.4.md | 9 ++- 1.5.md | 2 - 1.md | 3 +- 10.1.md | 2 - 10.2.md | 2 - 10.3.md | 2 - 10.4.md | 2 - 10.5.md | 2 - 10.md | 2 - 11.1.md | 2 - 11.2.md | 2 - 11.3.md | 2 - 11.md | 2 - 12.1.md | 2 - 12.2.md | 2 - 12.3.md | 2 - 12.4.md | 2 - 12.5.md | 2 - 12.6.md | 2 - 12.md | 2 - 2.1.md | 46 +++++++---- 2.2.md | 8 +- 2.3.md | 19 +++-- 2.4.md | 22 ++++-- 2.5.md | 13 +-- 2.6.md | 5 +- 2.7.md | 4 +- 2.md | 21 +++-- 3.1.md | 15 ++-- 3.2.md | 2 - 3.3.md | 2 - 3.md | 2 - 4.1.md | 2 - 4.2.md | 2 - 4.3.md | 2 - 4.4.md | 2 - 4.5.md | 2 - 4.md | 2 - 5.1.md | 2 - 5.2.md | 2 - 5.3.md | 2 - 5.4.md | 2 - 5.5.md | 2 - 5.md | 2 - 6.1.md | 2 - 6.2.md | 2 - 6.3.md | 2 - 6.md | 2 - 7.1.md | 2 - 7.2.md | 2 - 7.3.md | 2 - 7.md | 2 - 8.1.md | 2 - 8.2.md | 2 - 8.3.md | 2 - 8.4.md | 2 - 8.md | 2 - 9.1.md | 2 - 9.2.md | 2 - 9.3.md | 2 - 9.4.md | 2 - 9.md | 2 - build.php | 121 ---------------------------- index.md | 15 ++-- preface.md | 228 ++++++++++++++++++++++++++--------------------------- 68 files changed, 250 insertions(+), 427 deletions(-) delete mode 100644 build.php diff --git a/1.1.md b/1.1.md index 6a5c751..803b341 100644 --- a/1.1.md +++ b/1.1.md @@ -12,5 +12,3 @@ * 上一节: [PHP的生命周期](<1.md>) * 下一节: [PHP的启动与终止](<1.2.md>) -## LastModified - * $Id$ diff --git a/1.2.md b/1.2.md index cfa2f85..4df18e2 100644 --- a/1.2.md +++ b/1.2.md @@ -1,8 +1,11 @@ # 1.2 PHP的启动与终止 PHP程序的启动可以看作有两个概念上的启动,终止也有两个概念上的终止。其中一个是PHP作为Apache(拿它举例,板砖勿扔)的一个模块的启动与终止,这次启动php会初始化一些必要数据,比如与宿主Apache有关的,并且这些数据是常驻内存的!,终止与之相对。还有一个概念上的启动就是当Apache分配过一个页面请求来的时候,PHP会有一次启动与终止,这也是我们最常讨论的一种。 + 现在我们主要来看一个PHP扩展的生命旅程是怎样走完这四个过程的。 + 在最初的初始化时候,就是PHP随着Apache的启动而诞生在内存里的时,它会把自己所有已加载扩展的MINIT方法(俗称Module Initialization,模块初始化?其实是个函数)都执行一遍。在这个时间里,扩展可以定义一些自己的常量、类、资源等所有会被用户端的PHP脚本用到的东西。但你要记住,这里定义的东东都会随着Apache常驻内存,可以被所有请求使用,直到Apache卸载掉PHP模块! + 内核中预置了PHP_MINIT_FUNCTION宏函数,来帮助我们实现这个功能: ````c //抛弃作者那个例子,书才看两页整那样的例子太复杂了! @@ -26,6 +29,7 @@ PHP_RINIT_FUNCTION(walu) ```` 好了,现在这个页面请求执行的差不多了,可能是顺利的走到了自己文件的最后,也可能是出师未捷,半道被用户给die或者exit了,这时候PHP便会启动回收程序,收拾这个请求留下的烂摊子。它这次会执行所有已加载扩展的RSHUTDOWN(俗称Request Shutdown)方法,这时候扩展可以抓紧利用内核中的变量表啊之类的做一些事情,因为一旦PHP把所有扩展的RSHUTDOWN方法执行完,便会释放掉这次请求使用过的所有东西,包括变量表的所有变量、所有在这次请求中申请的内存等等。 + 内核预置了PHP_RSHUTDOWN_FUNCTION宏函数来帮助我们实现这个功能 ````c PHP_RSHUTDOWN_FUNCTION(walu) @@ -38,6 +42,7 @@ PHP_RSHUTDOWN_FUNCTION(walu) ```` 前面该启动的也启动了,该结束的也结束了,现在该Apache老人家歇歇的时候,当Apache通知PHP自己要Stop的时候,PHP便进入MSHUTDOWN(俗称Module Shutdown)阶段。这时候PHP便会给所有扩展下最后通喋,如果哪个扩展还有未了的心愿,就放在自己MSHUTDOWN方法里,这可是最后的机会了,一旦PHP把扩展的MSHUTDOWN执行完,便会进入自毁程序,这里一定要把自己擅自申请的内存给释放掉,否则就杯具了。 + 内核中预置了PHP_MSHUTDOWN_FUNCTION宏函数来帮助我们实现这个功能: ````c PHP_MSHUTDOWN_FUNCTION(walu) @@ -49,6 +54,7 @@ PHP_MSHUTDOWN_FUNCTION(walu) ```` 这四个宏都是在walu.c里完成最终实现的,而他们的则是在/main/php.h里被定义的(其实也是调用的别的宏,本节最后我把这几个宏给展开了,供有需要的人查看)。 + 好了,现在我们本节内容说完了,下面我们把所有的代码合在一起,并预测一下应该出现的结果: ````c //这些代码都在walu.c里面,不再.h里 @@ -107,5 +113,3 @@ PHP_FUNCTION(walu_test) * 上一节: [让我们从SAPI开始](<1.1.md>) * 下一节: [PHP的生命周期](<1.3.md>) -## LastModified - * $Id$ diff --git a/1.3.md b/1.3.md index 9882bd3..8381508 100644 --- a/1.3.md +++ b/1.3.md @@ -7,33 +7,43 @@
  • 多线程模块
  • Embedded(嵌入式,在自己的C程序中调用Zend Engine)
  • + ## 1、CLI/CGI时的周期 + CLI和CGI的SAPI是相当特殊的,因为这时PHP的生命周期完全在一个单独的请求中完成。虽然简单,不过我们以前提过的两种init和两种shutdown仍然都会被执行。图1.1展示了PHP在这种模式下是怎么工作的。 -

    + +

    + ## 2、多进程模式下 [ps:书是2006年出版的,所以你应该理解作者说多进程是主流]PHP最常见的工作方式便是编译成为Apache2 的Pre-fork MPM或者Apache1 的APXS 模式,其它web服务器也大多用相同的方式工作,在本书后面,把这种方式统一叫做多进程方式。给它起这个名字是有原因的,不是随便拍拍屁股拍拍脑袋定下来的。当Apache启动的时候,会立即把自己fork出好几个子进程,每一个进程都有自己独立的内存空间,也就代表了有自己独立的变量、函数等。在每个进程里的PHP的工作方式如下图所示: -

    + 因为是fork出来的,所以各个进程间的数据是无法直接相互影响的,无法读也无法写(ps:fork后可以用管道等方式实现进程间通信)。它允许每个子进程几乎可以做任何事情,玩七十码、躲猫猫都没人管,办公室拿砍刀玩自杀也没事,但是人家不一样的是人家有个前提:不能影响其它进程的稳定!下图展示了从apache的视角来看多进程工作模式下的PHP: -

    + +

    + ## 3、多线程模式下 + 随着时代的进步,PHP越来越多的在多线程模式下工作,就像IIS的isapi和Apache MPM worker(支持混合的多线程多进程的多路处理模块)。在这种模式下,只有一个服务器进程在运行着,但会同时运行很多线程,这样可以减少一些资源开销,向Module init和Module shutdown就只需要运行一遍就行了,一些全局变量也只需要初始化一次,因为线程独具的特质,使得各个请求之间方便的共享一些数据成为可能。下图展示了在这种模式下PHP的工作流程: -

    + +

    + ## 4、Embed Embed SAPI是一种比较特殊的sapi,容许你在C/C++语言中调用PHP/ZE提供的函数。并且这种sapi和上面的三种一样,按Module Init、Request Init、Rshutdown、mshutdown的流程执行着。 当然,这只是其中一种情况。因为特定的应用由自己特殊的需求,只是在处理PHP脚本这个环节基本一致。 + 真正令emebed模式独特的是因为它可能随时嵌入到某个程序里面去(比如你的test.exe里),然后被当作脚本的一部分在一个请求的时候执行。控制权在PHP和原程序间来回传递。关于嵌入式的PHP在第20章会有应用,到时我们再用实例介绍这个不经常使用的sapi。 - + +
    +## 关于Embed SAPI应用的文章 + * [Laruence大哥的使用PHP Embed SAPI实现Opcodes查看器](http://www.laruence.com/2008/09/23/539.html) + + ## links + * [目录]() * 上一节 [PHP的启动与终止](<1.2.md>) * 下一节 [线程安全](<1.4.md>) -## LastModified - * $Id$ diff --git a/1.4.md b/1.4.md index 437bc68..b7ca9ff 100644 --- a/1.4.md +++ b/1.4.md @@ -1,13 +1,20 @@ # 1.4 PHP的生命周期 ## 这一节没有翻译完,而且应该把这一节挪到后面的某一节里去 + 在PHP初期,是作为单进程的CGI来运行的,所以并没有考虑线程安全问题。我们可以随意的在全局作用域中设置变量并在程序中对他进行修改、访问,内核申请的资源如果没有正确的释放,也会在CGI进程结束后自动地被清理干净。 + 然后,php被作为apache多进程模式下的一个模块运行,但是这仍然把php局限在一个进程里,我们设置的全局变量,只要在每个请求之前将其正确的初始化,并在每个请求之后正确的清理干净,便不会带来什么麻烦。由于对于一个进程来说,同一个时间只能处理一个请求,所以这是内核中加入了针对每个请求的内存管理功能,来防止服务器资源利用出现错误。 现在,一个进程多个线程的工作方式被越来越多的采用,所以,php内核中亟需一种新的资源管理方式,其最终在php内核中形成了一个新的抽象层:TSRM(Thread Safe Resource Management)。 + ## 线程安全与非线程安全 + 在一个没有线程的程序中,我们往往倾向于把全局变量声明在源文件的顶部,编辑器会自动的为它分配资源供我们在声明语句之下的程序逻辑中使用。(即使通过fork()出一个子进程,它也会重新申请一段内存,父子进程中的变量从此没有了任何联系) + 但是在一个多线程的程序中,如果我们需要每个线程都用有自己独立的资源的话,便需要为每个线程独立开辟出一个区域来存放它们各自的资源,在线程里使用资源的时候,它便会去自己的那一亩三分地里去找,而不会拔了别人的庄稼。 + ## Thread-Safe Data Pools(线程安全的资源池?) + 在扩展的Module Init里,扩展可以调用ts_allocate_id()来告诉TRSM自己需要多少资源,TRSM接收后更新系统使用的资源,并得到一个指向刚分配的那份资源的id。 ````c typedef struct { @@ -33,5 +40,3 @@ PHP_MINIT_FUNCTION(sample) * 上一节: [PHP的生命周期](<1.3.md>) * 下一节: [小结](<1.5.md>) -## LastModified - * $Id$ diff --git a/1.5.md b/1.5.md index 344d5f6..1c89f04 100644 --- a/1.5.md +++ b/1.5.md @@ -8,5 +8,3 @@ * 上一节: [线程安全](<1.4.md>) * 下一节: [PHP变量在内核中的实现](<2.md>) -## LastModified - * $Id$ diff --git a/1.md b/1.md index 8e6a72e..fa1c6e1 100644 --- a/1.md +++ b/1.md @@ -8,11 +8,10 @@ * 5. [小结](1.5.html) 在平常的Web环境中,我们并不需要单独启动PHP,它一般都会作为一个模块自动加载到web-server里面去,如apache加载的php5.so。只要我们启动了web-server,被一起加载的php便会和服务器一起解析被请求的php脚本。 + 当然,这不是绝对的,当我们以fastcgi模式安装php的时候,往往就需要手动在终端运行php -b 127.0.0.1:9999来启动php,这个命令只是个例子,可能你的和我的并不一样。没记错的话,我的应该是我在fedora15上配置nginx+php时的一条命令。 ## links * [目录]() * 下一节: [让我们从SAPI开始](<1.1.md>) -## LastModified - * $Id$ diff --git a/10.1.md b/10.1.md index 50cb6a5..7510c0d 100644 --- a/10.1.md +++ b/10.1.md @@ -34,5 +34,3 @@ $obj = new myclass(); * 10 [PHP中的面向对象(一)](<10.md>) * 10.2 [定义一个类](<10.2.md>) -## LastModified - * $Id$ diff --git a/10.2.md b/10.2.md index e2fad9c..f2fae64 100644 --- a/10.2.md +++ b/10.2.md @@ -199,5 +199,3 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char * 10.1 [zend_class_entry](<10.1.md>) * 10.3 [定义一个接口](<10.3.md>) -## LastModified - * $Id$ diff --git a/10.3.md b/10.3.md index b2c8590..0fa038d 100644 --- a/10.3.md +++ b/10.3.md @@ -52,5 +52,3 @@ $obj->hello(); * 10.2 [定义一个类](<10.2.md>) * 10.4 [继承与实现接口](<10.4.md>) -## LastModified - * $Id$ diff --git a/10.4.md b/10.4.md index a296d47..e154d9f 100644 --- a/10.4.md +++ b/10.4.md @@ -124,5 +124,3 @@ static zend_function_entry i_myinterface[]= * 10.3 [定义一个接口](<10.3.md>) * 10.5 [小结](<10.5.md>) -## LastModified - * $Id$ diff --git a/10.5.md b/10.5.md index 19f49fd..dc1098b 100644 --- a/10.5.md +++ b/10.5.md @@ -7,5 +7,3 @@ * 10.4 [继承与实现接口](<10.4.md>) * 11 [PHP中的面向对象(二)](<11.md>) -## LastModified - * $Id$ diff --git a/10.md b/10.md index ee9917e..4491ce5 100644 --- a/10.md +++ b/10.md @@ -14,5 +14,3 @@ * 9.4 [第九章小结](<9.4.md>) * 10.1 [zend_class_entry](<10.1.md>) -## LastModified - * $Id$ diff --git a/11.1.md b/11.1.md index df6157f..e48371f 100644 --- a/11.1.md +++ b/11.1.md @@ -98,5 +98,3 @@ ZEND_MINIT_FUNCTION(test) * 11 [PHP中的面向对象(二)](<11.md>) * 11.2 [读写对象的属性](<11.2.md>) -## LastModified - * $Id$ diff --git a/11.2.md b/11.2.md index 6d78d95..176a415 100644 --- a/11.2.md +++ b/11.2.md @@ -92,5 +92,3 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char * * 11.1 [生成对象的实例](<11.1.md>) * 11.3 [小结](<11.3.md>) -## LastModified - * $Id$ diff --git a/11.3.md b/11.3.md index 1c03c4a..4cb2bf1 100644 --- a/11.3.md +++ b/11.3.md @@ -9,5 +9,3 @@ * 11.2 [读写对象的属性](<11.2.md>) * 0 []() -## LastModified - * $Id$ diff --git a/11.md b/11.md index a20406c..5cfff6e 100644 --- a/11.md +++ b/11.md @@ -13,5 +13,3 @@ PHP语言中的面向对象其实是分为三个部分来实现的,class、obj * 10.5 [小结](<10.5.md>) * 11.1 [生成对象的实例](<11.1.md>) -## LastModified - * $Id$ diff --git a/12.1.md b/12.1.md index 3642bc9..489cb61 100644 --- a/12.1.md +++ b/12.1.md @@ -117,5 +117,3 @@ EG( persistent_list ) HashTable中的持久性资源,因为他们往往​ * 上一节: [启动与终止的那点事](<12.md>) * 下一节: [MINFO与phpinfo](<12.2.md>) -## LastModified - * $Id$ diff --git a/12.2.md b/12.2.md index 96487c6..117c2d9 100644 --- a/12.2.md +++ b/12.2.md @@ -83,5 +83,3 @@ PHP_MINFO_FUNCTION(sample4) { * 12.1 [关于生命周期](<12.1.md>) * 12.3 [常量](<12.1.md>) -## LastModified - * $Id$ diff --git a/12.3.md b/12.3.md index 46b84a4..7070b75 100644 --- a/12.3.md +++ b/12.3.md @@ -82,5 +82,3 @@ void php_sample4_register_boolean_constant(char *name, uint len, * 12.2 [MINFO与phpinfo](<12.2.md>) * 12.4 [常量](<12.4.md>) -## LastModified - * $Id$ \ No newline at end of file diff --git a/12.4.md b/12.4.md index 53a9577..1336865 100644 --- a/12.4.md +++ b/12.4.md @@ -157,5 +157,3 @@ FG() | 文件全局变量。大多数文件I/O或相关的全局变量的数据 * 12.3 [常量](<12.3.md>) * 12.5 [PHP语言中的超级全局变量](<12.5.md>) -## LastModified - * $Id$ \ No newline at end of file diff --git a/12.5.md b/12.5.md index 96d2b1f..48cb5b2 100644 --- a/12.5.md +++ b/12.5.md @@ -84,5 +84,3 @@ PHP_RINIT_FUNCTION(sample4) { * 12.4 [PHP扩展中的全局变量](<12.4.md>) * 12.6 [小结](<12.6.md>) -## LastModified - * $Id$ \ No newline at end of file diff --git a/12.6.md b/12.6.md index 0579303..e53a230 100644 --- a/12.6.md +++ b/12.6.md @@ -7,5 +7,3 @@ * 12.5 [PHP语言中的超级全局变量](<12.5.md>) * 13.md [设置INI](<13.md>) -## LastModified - * $Id$ \ No newline at end of file diff --git a/12.md b/12.md index 753d41e..a33dee5 100644 --- a/12.md +++ b/12.md @@ -18,5 +18,3 @@ * 11.3 [小结](<11.3.md>) * 12.1 [关于生命周期](<12.1.md>) -## LastModified - * $Id$ diff --git a/2.1.md b/2.1.md index 0f0007d..a44c815 100644 --- a/2.1.md +++ b/2.1.md @@ -1,6 +1,7 @@ # 2.1 第二章目录 PHP在内核中是通过zval这个结构体来存储变量的,它的定义在Zend/zend.h文件里,简短精炼,只有四个成员组成: + ````c struct _zval_struct { zvalue_value value; /* 变量的值 */ @@ -15,7 +16,10 @@ typedef unsigned int zend_uint; typedef unsigned char zend_uchar; ```` + zval里的refcout__gc是zend_uint类型,也就是unsinged int型,is_ref__gc和type则是unsigned char型的。
    保存变量值的value则是zvalue_value类型(PHP5),它是一个Union,同样定义在了Zend/zend.h文件里: + + ````c typedef union _zvalue_value { long lval; /* long value */ @@ -28,7 +32,8 @@ typedef union _zvalue_value { zend_object_value obj; } zvalue_value; -```` +```` + 在以上实现的基础上,PHP语言得以实现了8种数据类型,这些数据类型在内核中的分别对应于特定的常量,它们分别是: @@ -46,11 +51,13 @@ typedef union _zvalue_value { +echo $a;//会正确的输出 2147483648; +```` + @@ -74,7 +81,9 @@ echo $a;//会正确的输出 2147483648;
    IS_LONG PHP语言中的整型,在内核中是通过所在操作系统的singed long数据类型来表示的。在最常见的32位操作系统中,它可以存储从-2147483648 到 +2147483647范围内的任一整数。有一点需要注意的是,如果PHP语言中的整型变量超出最大值或者最小值,它并不会直接溢出,而是会被内核转换成IS_DOUBLE类型的值然后再参与计算。再者,因为使用了singed long来作为载体,所以这也就解释了为什么PHP语言中的整型数据都是带符号的了。 -
    + +````c $a=2147483647; $a++; -echo $a;//会正确的输出 2147483648; -
    IS_DOUBLE
    zval结构体里的type成员的值便是以上某个IS_*常量之一。内核通过检测变量的这个成员值来知道他是什么类型的数据并做相应的后续处理。 + 如果要我们检测一个变量的类型,最直接的办法便是去读取它的type成员的值: + ````c void describe_zval(zval *foo) { @@ -87,11 +96,13 @@ void describe_zval(zval *foo) php_printf("这个变量的数据类型不是NULL,这种数据类型对应的数字是: %d", foo->type); } } - ```` -

    上述做法看起来没有错误,但它是一种被强烈禁止一种做法! + +**上述做法看起来没有错误,但它是一种被强烈禁止一种做法!** + PHP内核以后可能会修改变量的实现方式,所以检测type的方法可能在以后就不能用了。为了解决这个兼容问题,zend头文件中定义了大量的宏,供我们检测、操作变量使用,使用这些宏不但让我们的程序更易读,还具有更好的兼容性。这里我们用Z_TYPE_P()宏来改写上面那个程序。 -

    +
    +````c
     void describe_zval(zval *foo)
     {
         if ( Z_TYPE_P(foo) == IS_NULL )
    @@ -103,9 +114,12 @@ void describe_zval(zval *foo)
             php_printf("这个变量的数据类型不是NULL,这种数据类型对应的数字是: %d", foo->type);
         }
     }
    -		
    -
    php_printf()函数是内核对printf()函数的一层封装,我们可以像使用printf()函数那样使用它。
    -以_P一个p结尾的宏的参数大多是*zval型变量,此外获取变量类型的宏还有两个,分别是Z_TYPE和Z_TYPE_PP,前者的参数是zval型,而后者的参数则是**zval。 +```` + +**php_printf()函数是内核对printf()函数的一层封装,我们可以像使用printf()函数那样使用它。** + +以_P一个p结尾的宏的参数大多是*zval型变量,此外获取变量类型的宏还有两个,分别是Z_TYPE和Z_TYPE_PP,前者的参数是zval型,而后者的参数则是**zval。 + 这样我们便可以猜测一下php内核是如何实现gettype这个函数了,代码如下: ````c //开始定义php语言中的函数gettype @@ -168,16 +182,14 @@ PHP_FUNCTION(gettype) ```` 以上三个宏的定义在Zend/zend_operators.h里,定义分别是: - +````c #define Z_TYPE(zval) (zval).type #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp) - - +```` ## links - * 2 [第二章目录](<2.md>) - * 2.2 [变量的值](<2.2.md>) + * [目录]() + * 2 [第二章目录](<2.md>) + * 2.2 [变量的值](<2.2.md>) -## LastModified - * $Id$ diff --git a/2.2.md b/2.2.md index 807dacc..e7b78a0 100644 --- a/2.2.md +++ b/2.2.md @@ -1,6 +1,7 @@ # 2.2 第二章目录 PHP内核提供了三个基础宏来方便我们对变量的值进行操作,这几个宏同样以Z_开头,并且P结尾和PP结尾的同上一节中的宏一样,分别代表这参数是指针还是指针的指针。此外,为了进一步方便我们的工作,内核中针对具体的数据类型分别定义了相应的宏。如针对IS_BOOL型的BVAL组合(Z_BVAL、Z_BVAL_P、Z_BVAL_PP)和针对IS_DOUBLE的DVAL组合(Z_DVAL、ZDVAL_P、ZDVAL_PP)等等。我们通过下面这个例子来应用一下这几个宏: + ````c void display_value(zval zv,zval *zv_p,zval **zv_pp) { @@ -35,8 +36,11 @@ void display_string(zval *zstr) ```` Array型变量的值其实是存储在C语言实现的HashTable中的,我们可以用ARRVAL组合宏(Z_ARRVAL, Z_ARRVAL_P, Z_ARRVAL_PP)这三个宏来访问数组的值。如果你看旧版本php的源码或者部分pecl扩展的源码,可能会发现一个HASH_OF()宏,这个宏等价于Z_ARRVAL_P(),但不推荐在新代码中再使用了。 + 对象是一个复杂的结构体(zend_object_value结构体),不仅存储属性的定义、属性的值,还存储着访问权限、方法等信息。内核中定义了以下组合宏让我们方便的操作对象:OBJ_HANDLE, which returns the handle identifier, OBJ_HT for the handler table, OBJCE for the class definition, OBJPROP for the property HashTable, and OBJ_HANDLER for manipulating a specific handler method in the OBJ_HT table. Don't worry about the meaning of these various object macros just yet; they'll be covered in detail in Chapter 10, "PHP4 Objects," and Chapter 11, "PHP5 Objects." + 资源型变量的值其实就是一个整数,可以用RESVAL组合宏来访问它,我们把它的值传给zend_fetch_resource函数,便可以得到这个资源的操作句柄,如mysql的链接句柄等。有关资源的内容我们将在第9章展开叙述。 + 有关值操作的宏都定义在./Zend/zend_operators.h文件里: ````c //操作整数的 @@ -106,10 +110,8 @@ Array型变量的值其实是存储在C语言实现的HashTable中的,我们 ```` - ## links + * [目录]() * 2.1 [变量的类型](<2.1.md>) * 2.3 [创建PHP变量](<2.3.md>) -## LastModified - * $Id$ diff --git a/2.3.md b/2.3.md index 3ad9125..192b778 100644 --- a/2.3.md +++ b/2.3.md @@ -1,11 +1,15 @@ # 2.3 第二章目录 我们已经知道php变量在内核中其实是通过zval结构来实现的,也初步了如果设置一个zval结构的类型和值,这一节我们的目的便是在前两节的基础上,彻底掌握对zval结构的操控,其间将引入很多超棒的新的宏。 + 在code的时候,我们很希望在内核中创建的zval可以让用户在PHP语言里以变量的形式使用,为了实现这个功能,我们首先要创建一个zval。最容易想到的办法便是创建一个zval指针,然后申请一块内存并让指针指向它。如果你脑海里浮现出了malloc(sizeof(zval))的影子,那么请你立即刹车,不要用malloc来做这件事情,内核给我们提供了相应的宏来处理这件事,理由和以前一样:为了代码漂亮并保持版本升级时的兼容性。这个宏的是:MAKE_STD_ZVAL(pzv)。这个宏会用内核的方式来申请一块内存并将其地址付给pzv,并初始化它的refcount和is_ref连个属性,更棒的是,它不但会自动的处理内存不足问题,还会在内存中选个最优的位置来申请。 -

    除了MAKE_STD_ZVAL()宏函数,ALLOC_INIT_ZVAL()宏函数也是用来干这件事的,唯一的不同便是它会将pzv所指的zval的类型设置为IS_NULL; + +> 除了MAKE_STD_ZVAL()宏函数,ALLOC_INIT_ZVAL()宏函数也是用来干这件事的,唯一的不同便是它会将pzv所指的zval的类型设置为IS_NULL; + 申请完空间后,我们便可以给这个zval赋值了。基于咱已经介绍的宏,也许我们需要Z_TYPE_P(p) = IS_NULL来设置其是null类型,并过Z_SOMEVAL形式的宏来为它赋值,但是现在你有了更好更短的选择! + 内核中提供一些宏来简化我们的操作,可以只用一步便设置好zval的类型和值。 - +
    @@ -47,20 +51,23 @@ - - +
    新宏 其它宏的实现方法
    ZVAL_RESOURCE(pzv, res); Z_TYPE_P(pzv) = IS_RESOURCE;
    Z_RESVAL_P(pzv) = res;
    + + ### ZVAL_STRINGL(pzv,str,len,dup)中的dup参数 + 先阐述一下ZVAL_STRINGL(pzv,str,len,dup); str和len两个参数很好理解,因为我们知道内核中保存了字符串的地址和它的长度,后面的dup的意思其实很简单,它指明了该字符串是否需要被复制。值为 1 将先申请一块新内存并赋值该字符串,然后把新内存的地址复制给pzv,为 0 时则是直接把str的地址赋值给zval。《抚琴居》上的一篇文章说这项特性将会在你仅仅需要创建一个变量并将其指向一个已经由 Zend 内部数据内存时变得很有用。 + ### ZVAL_STRINGL与ZVAL_STRING的区别 如果你想在某一位置截取该字符串或已经知道了这个字符串的长度,那么可以使用宏 ZVAL_STRINGL(zval, string, length, duplicate) ,它显示的指定字符串长度,而不是使用strlen()。这个宏该字符串长度作为参数。但它是二进制安全的,而且速度也比ZVAL_STRING快,因为少了个strlen。 + ### ZVAL_RESOURCE约等于ZVAL_LONG 上一节中我们说过PHP中的资源类型的值其实就是一个整数,所以ZVAL_RESOURCE和ZVAL_LONG的工作差不多,只不过它会把zval的类型设置为 IS_RESOURCE. ## links + * [目录]() * 2.2 [变量的值](<2.2.md>) * 2.4 [变量的存储方式](<2.4.md>) -## LastModified - * $Id$ diff --git a/2.4.md b/2.4.md index 0e90a59..09a0223 100644 --- a/2.4.md +++ b/2.4.md @@ -1,9 +1,13 @@ # 2.4 第二章目录 我们在前两节已经了解了PHP中变量的类型和值是怎样在内核中用C语言实现的,这一节我们将看一下内核是怎样来组织用户在PHP中定义的变量的。 + 有一点对我们扩展开发者来说非常棒,那就是用户在PHP中定义的变量我们都可以在一个HashTable中找到,当PHP中定义了一个变量,内核会自动的把它的信息储存到一个用HashTable实现的符号表里。 + 全局作用域的符号表是在调用扩展的RINIT方法(一般都是MINIT方法里)前创建的,并在RSHUTDOWN方法执行后自动销毁。 + 当用户在PHP中调用一个函数或者类的方法时,内核会创建一个新的符号表并激活之,这也就是为什么我们无法在函数中使用在函数外定义的变量的原因(因为它们分属两个符号表,一个当前作用域的,一个全局作用域的)。如果不是在一个函数里,则全局作用域的符号表处于激活状态。 + 我们现在打开Zend/zend_globals.h文件,看一下_zend_execution_globals结构体,会在其中发现这么两个element: ````c struct _zend_executor_globals { @@ -16,7 +20,10 @@ struct _zend_executor_globals { ```` 其中的 symbol_table元素可以通过EG宏来访问,它代表着PHP的全局变量,如$GLOBALS,其实从根本上来讲,$GLOBALS不过是EG(symbol_table)的一层封装而已。 与之对应,下面的active_symbol_table元素也可以通过EG(active_symbol_table)的方法来访问,它代表的是处于当前作用域的变量符号表。 -我们上边也看到了,其实这两个成员在_zend_executor_globals里虽然都代表HashTable,但一个是真正的HashTable,而另一个是一个指针。当我们在对HashTable进行操作的时候,往往是把它的地址传递给一些函数。所以,如果我们要对EG(symbol_table)的结果进行操作,往往需要对它进行求址操作然后用它的地址作为被调用函数的参数。

    下面我们用一段例子来解释下上面说的理论: + +我们上边也看到了,其实这两个成员在_zend_executor_globals里虽然都代表HashTable,但一个是真正的HashTable,而另一个是一个指针。当我们在对HashTable进行操作的时候,往往是把它的地址传递给一些函数。所以,如果我们要对EG(symbol_table)的结果进行操作,往往需要对它进行求址操作然后用它的地址作为被调用函数的参数。 + +下面我们用一段例子来解释下上面说的理论: ````php -

  • 创建一个zval结构,并设置其类型。
  • -
  • 设置值为'bar'。
  • -
  • 将其加入当前作用域的符号表,只有这样用户才能在PHP里使用这个变量。
  • - 具体的代码为: + + * 创建一个zval结构,并设置其类型。 + * 设置值为'bar'。 + * 将其加入当前作用域的符号表,只有这样用户才能在PHP里使用这个变量。 + * 具体的代码为: ````c { zval *fooval; @@ -43,8 +50,7 @@ $foo = 'bar'; ## links + * [目录]() * 2.3 [创建PHP变量](<2.3.md>) * 2.5 [变量的检索](<2.5.md>) -## LastModified - * $Id$ diff --git a/2.5.md b/2.5.md index 9204f3d..51f2008 100644 --- a/2.5.md +++ b/2.5.md @@ -22,16 +22,19 @@ } ```` -首先我们定义了一个指向指针的指针,然后通过zend_hash_find去EG(active_symbol_table)作用域下寻找名称为foo($foo)的变量,如果成功找到,此函数将返回SUCCESS。看完代码,你肯定有很多疑问。为什么还要进行sizeof("foo")运算,fooval明明是zval**型的,为什么转成void**的?而且为什么还要进行&fooval运算,fooval本身不就已经是指向指针的指针了吗?:-),该回答的问题确实很多,不要过于担心,让我们带着这些问题继续往下走。 -首先要说明的是,内核定义HashTable这个结构,并不是单单用来储存PHP语言里的变量的,其它很多地方都在应用HashTable(这就是个神器)。一个HashTable有很多元素,在内核里叫做bucket。然而每个bucket的大小是固定的,所以如果我们想在bucket里存储任意数据时,最好的办法便是申请一块内存保存数据,然后在bucket里保存它的指针。以zval *foo为例,内核会先申请一块足够保存指针内存来保存foo,比如这块内存的地址是p,也就是p=&foo,并在bucket里保存p,这时我们便明白了,p其实就是zval**类型的。至于bucket为什么保存zval**类型的指针,而不是直接保存zval*类型的指针,我们到下一章在详细叙述。 -所以当我们去HashTable里寻找变量的时候,得到的值其实是一个zval的指针。In order to populate that pointer into a calling function's local storage, the calling function will naturally dereference the local pointer, resulting in a variable of indeterminate type with two levels of indirection (such as void**). Knowing that your "indeterminate type" in this case is zval*, you can see where the type being passed into zend_hash_find() will look different to the compiler, having three levels of indirection rather than two. This is done on purpose here so a simple typecast is added to the function call to silence compiler warnings. +首先我们定义了一个指向指针的指针,然后通过zend_hash_find去EG(active_symbol_table)作用域下寻找名称为foo($foo)的变量,如果成功找到,此函数将返回SUCCESS。看完代码,你肯定有很多疑问。为什么还要进行`sizeof("foo")`运算,fooval明明是`zval**`型的,为什么转成`void**`的?而且为什么还要进行&fooval运算,fooval本身不就已经是指向指针的指针了吗?:-),该回答的问题确实很多,不要过于担心,让我们带着这些问题继续往下走。 + +首先要说明的是,内核定义HashTable这个结构,并不是单单用来储存PHP语言里的变量的,其它很多地方都在应用HashTable**(这就是个神器)**。一个HashTable有很多元素,在内核里叫做bucket。然而每个bucket的大小是固定的,所以如果我们想在bucket里存储任意数据时,最好的办法便是申请一块内存保存数据,然后在bucket里保存它的指针。以zval *foo为例,内核会先申请一块足够保存指针内存来保存foo,比如这块内存的地址是p,也就是p=&foo,并在bucket里保存p,这时我们便明白了,p其实就是`zval**`类型的。至于bucket为什么保存`zval**`类型的指针,而不是直接保存`zval*`类型的指针,我们到下一章在详细叙述。 + +所以当我们去HashTable里寻找变量的时候,得到的值其实是一个zval的指针。In order to populate that pointer into a calling function's local storage, the calling function will naturally dereference the local pointer, resulting in a variable of indeterminate type with two levels of indirection (such as `void**`). Knowing that your "indeterminate type" in this case is `zval*`, you can see where the type being passed into zend_hash_find() will look different to the compiler, having three levels of indirection rather than two. This is done on purpose here so a simple typecast is added to the function call to silence compiler warnings. + 如果zend_hash_find()函数找到了我们需要的数据,它将返回SUCCESS常量,并把它的地址赋给我们在调用zend_hash_find()函数传递的fooval参数,也就是说此时fooval就指向了我们要找的数据。如果没有找到,那它不会对我们fooval参数做任何修改,并返回FAILURE常量。 + 就去符号表里找变量而言,SUCCESS和FAILURE仅代表这个变量是否存在而已。 ## links + * [目录]() * 2.4 [变量的存储方式](<2.4.md>) * 2.6 [类型转换](<2.6.md>) -## LastModified - * $Id$ diff --git a/2.6.md b/2.6.md index 943f90a..ad1242e 100644 --- a/2.6.md +++ b/2.6.md @@ -69,12 +69,11 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC); ```` 这里面有两个比较特殊,一个就是convert_to_string其实是一个宏函数,调用的另外一个函数;第二个便是没有convert_to_resource()的转换函数,因为资源的值在用户层面上,根本就没有意义,内核不会对它的值(不是指那个数字)进行转换。 -好了,我们用php的echo的时候会先把变量转换成字符串,但是我们看见convert_to_string的参数是zval*的,你是不是开始担心在进行数据转换时破坏了原来数据的值?而我们<?php $a=intval($b);?>并不会破坏$b的值。把原来的值破坏掉的做法绝对不是一个好主意,内核中在echo一个变量的时候也不是这样做的。在下一章,我们将知道怎样便可以在不损坏原变量值的情况下,进行convert_to_类操作。 +好了,我们用php的echo的时候会先把变量转换成字符串,但是我们看见convert_to_string的参数是zval*的,你是不是开始担心在进行数据转换时破坏了原来数据的值?而我们`) * 2.5 [变量的检索](<2.5.md>) * 2.7 [第二章小结](<2.7.md>) -## LastModified - * $Id$ diff --git a/2.7.md b/2.7.md index c1ffeb0..cb596c3 100644 --- a/2.7.md +++ b/2.7.md @@ -1,12 +1,12 @@ # 2.7 第二章目录 在这一章我们了解了php变量在内核中是如何实现的,我们已经可以识别出一个变量的类型,把它加到符号表去或者从符号表中找出等等等等。在下一章我们的目光开始转向内存,顺道研究下怎样复制已经存在的zval,以及如何在它们没用的时候及时的清理掉,还有最重要的,怎么不使用copy,而使用引用! + 我们已经了解到zend引擎中针对一个请求的内存管理层,了解了常驻内存与非常驻内存的概念与区别。在读完下一章后,我们便有了比较完整的理论基础来在我们自己的扩展中灵活的操作各个变量。 ## links + * [目录]() * 2.6 [类型转换](<2.6.md>) * 3 [内存管理](<3.md>) -## LastModified - * $Id$ diff --git a/2.md b/2.md index 7cae44e..1b5d25f 100644 --- a/2.md +++ b/2.md @@ -1,21 +1,20 @@ # 2 PHP变量在内核中的实现 -
      -
    • [1. 变量的类型](ch2.1.html)
    • -
    • [2. 变量的值](ch2.2.html)
    • -
    • [3. 创建PHP变量](ch2.3.html)
    • -
    • [4. 变量的存储方式](ch2.4.html)
    • -
    • [5. 变量的检索](ch2.5.html)
    • -
    • [6. 类型转换](ch2.6.html)
    • -
    • [7. 小结](ch2.7.html)
    • -
    + * [1. 变量的类型](2.1.md) + * [2. 变量的值](2.2.md) + * [3. 创建PHP变量](2.3.md) + * [4. 变量的存储方式](2.4.md) + * [5. 变量的检索](2.5.md) + * [6. 类型转换](2.6.md) + * [7. 小结](2.7.md) + 所有的编程语言都要提供一种数据的存储与检索机制,PHP也不例外。其它语言大都需要在使用变量之前先定义,并且它的类型也是无法再次改变的,而PHP却允许程序猿自由的使用变量而无须提前定义,甚至可以随时随意的对已存在的变量转换成其它任何PHP支持的数据类型。在程序在运行的时候,PHP还会自动的根据需求转换变量的类型。 + 我认为阅读本书的人都已经是标准的PHP程序猿了,所以你们也肯定体验过PHP的弱类型的变量体系。众所周知,PHP引擎是用C写的,而C确实一种强类型的编程语言,PHP内核中是如何用C来实现自己的这种弱类型特性的,你将在本章中找到答案! ## links + * [目录]() * 1.5 [小结](<1.5.md>) * 2.1 [变量的类型](<2.1.md>) -## LastModified - * $Id$ diff --git a/3.1.md b/3.1.md index dbfbada..764f2c5 100644 --- a/3.1.md +++ b/3.1.md @@ -115,10 +115,15 @@ void *safe_emalloc(size_t size, size_t count, size_t addtl); void *safe_pemalloc(size_t size, size_t count, size_t addtl, char persistent); ```` -这些函数分配的内存空间最终大小都是((size*count)+addtl)。你可以会问:"为什么还要提供额外函数呢?为什么不使用一个emalloc/pemalloc呢?"原因很简单:为了安全,以防万一。尽管有时候可能性相当小,但是,正是这一"可能性相当小"的结果导致宿主平台的内存溢出。这可能会导致分配负数个数的字节空间,或更有甚者,会导致分配一个小于调用程序要求大小的字节空间。而safe_emalloc()能够避免这种类型的陷井-通过检查整数溢出并且在发生这样的溢出时显式地预以结束。 -

    注意,并不是所有的内存分配例程都有一个相应的p*对等实现。例如,不存在pestrndup(),并且在PHP 5.1版本前也不存在safe_pemalloc()。 - -


    +这些函数分配的内存空间最终大小都是((size*count)+addtl)。 +你可以会问:"为什么还要提供额外函数呢?为什么不使用一个emalloc/pemalloc呢?"。 +原因很简单:为了安全,以防万一。尽管有时候可能性相当小,但是,正是这一"可能性相当小"的结果导致宿主平台的内存溢出。 +这可能会导致分配负数个数的字节空间,或更有甚者,会导致分配一个小于调用程序要求大小的字节空间。 +而safe_emalloc()能够避免这种类型的陷井-通过检查整数溢出并且在发生这样的溢出时显式地预以结束。 + +> 注意,并不是所有的内存分配例程都有一个相应的p*对等实现。例如,不存在pestrndup(),并且在PHP 5.1版本前也不存在safe_pemalloc()。 + +
    贡献者名单
    绊大象的蚂蚁{eaglevean#163.com},注1
    @@ -129,5 +134,3 @@ void *safe_pemalloc(size_t size, size_t count, size_t addtl, char persistent); * 3 [内存管理](<3.md>) * 3.2 [引用计数](<3.2.md>) -## LastModified - * $Id$ diff --git a/3.2.md b/3.2.md index e60ad19..a546c43 100644 --- a/3.2.md +++ b/3.2.md @@ -128,5 +128,3 @@ The answer is: 不可能!在这种情况下,变量的值必须分离成两 * 3.1 [内存管理](<3.1.md>) * 3.3 [3.3 第三章总结](<3.3.md>) -## LastModified - * $Id$ diff --git a/3.3.md b/3.3.md index 20fc963..42f4a5d 100644 --- a/3.3.md +++ b/3.3.md @@ -8,5 +8,3 @@ PHP是一种解释型的语言,对于用户而言,我们精心的控制内 * 3.2 [引用计数](<3.2.md>) * 4 [动手编译PHP](<4.md>) -## LastModified - * $Id$ diff --git a/3.md b/3.md index 82435d1..812a8c1 100644 --- a/3.md +++ b/3.md @@ -14,5 +14,3 @@ * 2.7 [第二章小结](<2.7.md>) * 3.1 [内存管理](<3.1.md>) -## LastModified - * $Id$ diff --git a/4.1.md b/4.1.md index 50543a6..ff8071d 100644 --- a/4.1.md +++ b/4.1.md @@ -71,5 +71,3 @@ Once installation is complete you'll have a new item on your Start menuMicrosoft * 4 [动手编译PHP](<4.md>) * 4.2 [PHP编译前的config配置](<4.2.md>) -## LastModified - * $Id$ diff --git a/4.2.md b/4.2.md index caf58b4..7f5a41d 100644 --- a/4.2.md +++ b/4.2.md @@ -44,5 +44,3 @@ p = strchr(str, ','); * 4.1 [编译前的准备](<4.1.md>) * 4.3 [Unix/Linux平台下的编译](<4.3.md>) -## LastModified - * $Id$ diff --git a/4.3.md b/4.3.md index 7da6d71..6f5e489 100644 --- a/4.3.md +++ b/4.3.md @@ -16,5 +16,3 @@ make,尤其是make test命令是个耗时大户,具体执行时间的长短 * 4.2 [PHP编译前的config配置](<4.2.md>) * 4.4 [在Win32平台上编译PHP](<4.4.md>) -## LastModified - * $Id$ diff --git a/4.4.md b/4.4.md index 75d4592..3fd22ed 100644 --- a/4.4.md +++ b/4.4.md @@ -48,5 +48,3 @@ Finally, a working build of PHP compiled for the Win32 platform. * 4.3 [Unix/Linux平台下的编译](<4.3.md>) * 4.5 [第四章小结](<4.5.md>) -## LastModified - * $Id$ diff --git a/4.5.md b/4.5.md index 9b793af..abe8d15 100644 --- a/4.5.md +++ b/4.5.md @@ -9,5 +9,3 @@ * 4.4 [在Win32平台上编译PHP](<4.4.md>) * 5 [Your First Extension](<5.md>) -## LastModified - * $Id$ diff --git a/4.md b/4.md index b5d96f5..909d3fe 100644 --- a/4.md +++ b/4.md @@ -17,5 +17,3 @@ * 3.3 [3.3 第三章总结](<3.3.md>) * 4.1 [编译前的准备](<4.1.md>) -## LastModified - * $Id$ diff --git a/5.1.md b/5.1.md index 60cb17b..f7a943a 100644 --- a/5.1.md +++ b/5.1.md @@ -120,5 +120,3 @@ ZEND_GET_MODULE(walu) * 5 [Your First Extension](<5.md>) * 5.2 [编译我们的扩展](<5.2.md>) -## LastModified - * $Id$ diff --git a/5.2.md b/5.2.md index bd70c55..bcea080 100644 --- a/5.2.md +++ b/5.2.md @@ -80,5 +80,3 @@ extension=walu.so * 5.1 [一个扩展的基本结构](<5.1.md>) * 5.3 [静态编译](<5.3.md>) -## LastModified - * $Id$ diff --git a/5.3.md b/5.3.md index 790191c..79e8554 100644 --- a/5.3.md +++ b/5.3.md @@ -17,5 +17,3 @@ The PHP build system will scan for config.w32 files, including the one you just * 5.2 [编译我们的扩展](<5.2.md>) * 5.4 [编写函数](<5.4.md>) -## LastModified - * $Id$ diff --git a/5.4.md b/5.4.md index 27e85d8..28bc503 100644 --- a/5.4.md +++ b/5.4.md @@ -131,5 +131,3 @@ walu_hello(); * 5.3 [静态编译](<5.3.md>) * 5.5 [第五章小结](<5.5.md>) -## LastModified - * $Id$ diff --git a/5.5.md b/5.5.md index 4b67b11..0e4227e 100644 --- a/5.5.md +++ b/5.5.md @@ -8,5 +8,3 @@ * 5.4 [编写函数](<5.4.md>) * 6 [函数返回值](<6.md>) -## LastModified - * $Id$ diff --git a/5.md b/5.md index e851258..41fc427 100644 --- a/5.md +++ b/5.md @@ -16,5 +16,3 @@ * 4.5 [第四章小结](<4.5.md>) * 5.1 [一个扩展的基本结构](<5.1.md>) -## LastModified - * $Id$ diff --git a/6.1.md b/6.1.md index df0b6a7..a4edc99 100644 --- a/6.1.md +++ b/6.1.md @@ -250,5 +250,3 @@ arginfo是一种特殊的结构体,用来提前向内核告知此函数具有 * 6 [函数返回值](<6.md>) * 6.2 [引用与函数的执行结果](<6.2.md>) -## LastModified - * $Id$ diff --git a/6.2.md b/6.2.md index 9ebda84..6229285 100644 --- a/6.2.md +++ b/6.2.md @@ -152,5 +152,3 @@ ZEND_FE(byref_compiletime,byref_calltime,byref_compiletime_arginfo) * 6.1 [一个特殊的参数:return_value](<6.1.md>) * 6.3 [第六章小结](<6.3.md>) -## LastModified - * $Id$ diff --git a/6.3.md b/6.3.md index 595abf1..29dc433 100644 --- a/6.3.md +++ b/6.3.md @@ -8,5 +8,3 @@ * 6.2 [引用与函数的执行结果](<6.2.md>) * 7 [函数的参数](<7.md>) -## LastModified - * $Id$ diff --git a/6.md b/6.md index 9e415df..a7c6bc4 100644 --- a/6.md +++ b/6.md @@ -32,5 +32,3 @@ int main(void) { * 5.5 [第五章小结](<5.5.md>) * 6.1 [一个特殊的参数:return_value](<6.1.md>) -## LastModified - * $Id$ diff --git a/7.1.md b/7.1.md index 12fdee0..aed6d74 100644 --- a/7.1.md +++ b/7.1.md @@ -250,5 +250,3 @@ ZEND_FUNCTION(var_dump) * 6.3 [第六章小结](<6.3.md>) * 7.2 [Arg Info 与类型绑定](<7.2.md>) -## LastModified - * $Id$ diff --git a/7.2.md b/7.2.md index 9225775..f40f032 100644 --- a/7.2.md +++ b/7.2.md @@ -44,5 +44,3 @@ zend_parse_parameters()本身可以保证传递过来的参数是一个数组。 * 7.1 [zend_parse_parameters](<7.1.md>) * 7.3 [第七章小结](<7.3.md>) -## LastModified - * $Id$ diff --git a/7.3.md b/7.3.md index 587ed81..5f365bc 100644 --- a/7.3.md +++ b/7.3.md @@ -10,5 +10,3 @@ * 7.2 [Arg Info 与类型绑定](<7.2.md>) * 8 [使用HashTable与{数组}](<8.md>) -## LastModified - * $Id$ diff --git a/7.md b/7.md index 850326e..86deb95 100644 --- a/7.md +++ b/7.md @@ -14,5 +14,3 @@ * 6.3 [第六章小结](<6.3.md>) * 7.1 [zend_parse_parameters](<7.1.md>) -## LastModified - * $Id$ diff --git a/8.1.md b/8.1.md index 8a6c54a..0c322b0 100644 --- a/8.1.md +++ b/8.1.md @@ -167,5 +167,3 @@ Zend Engine中HashTable的元素其实是指针,对其的这个改进使得Has * 8 [使用HashTable与{数组}](<8.md>) * 8.2 [操作HashTable的API](<8.2.md>) -## LastModified - * $Id$ diff --git a/8.2.md b/8.2.md index b084a14..964a15e 100644 --- a/8.2.md +++ b/8.2.md @@ -675,5 +675,3 @@ array_data_compare是一个返回compare_func_t类型数据的函数,它将按 * 8.1 [数组(C中的)与链表](<8.1.md>) * 8.3 [在内核中操作PHP语言中数组](<8.3.md>) -## LastModified - * $Id$ diff --git a/8.3.md b/8.3.md index f7b74ce..c196b5d 100644 --- a/8.3.md +++ b/8.3.md @@ -123,5 +123,3 @@ array(6) * 8.2 [操作HashTable的API](<8.2.md>) * 8.4 [第8章小结](<8.4.md>) -## LastModified - * $Id$ diff --git a/8.4.md b/8.4.md index b89c1fe..dba91d5 100644 --- a/8.4.md +++ b/8.4.md @@ -9,5 +9,3 @@ * 8.3 [在内核中操作PHP语言中数组](<8.3.md>) * 9 [PHP中的资源类型](<9.md>) -## LastModified - * $Id$ diff --git a/8.md b/8.md index a5fcd25..c5e9505 100644 --- a/8.md +++ b/8.md @@ -13,5 +13,3 @@ * 7.3 [第七章小结](<7.3.md>) * 8.1 [数组(C中的)与链表](<8.1.md>) -## LastModified - * $Id$ diff --git a/9.1.md b/9.1.md index ac325e9..6750bc8 100644 --- a/9.1.md +++ b/9.1.md @@ -238,5 +238,3 @@ PHP_FUNCTION(sample_fclose) * 9 [PHP中的资源类型](<9.md>) * 9.2 [Persistent Resources](<9.2.md>) -## LastModified - * $Id$ diff --git a/9.2.md b/9.2.md index 3effd9f..32416a1 100644 --- a/9.2.md +++ b/9.2.md @@ -346,5 +346,3 @@ ZEND_VERIFY_RESOURCE(fp); * 9.1 [复合类型的数据——{资源}](<9.1.md>) * 9.3 [{资源}自有的引用计数](<9.3.md>) -## LastModified - * $Id$ diff --git a/9.3.md b/9.3.md index a65999d..1d236e3 100644 --- a/9.3.md +++ b/9.3.md @@ -39,5 +39,3 @@ $c = &$a; * 9.2 [Persistent Resources](<9.2.md>) * 9.4 [第九章小结](<9.4.md>) -## LastModified - * $Id$ diff --git a/9.4.md b/9.4.md index ea634b5..fe899d2 100644 --- a/9.4.md +++ b/9.4.md @@ -8,5 +8,3 @@ * 9.3 [{资源}自有的引用计数](<9.3.md>) * 10 [PHP中的面向对象(一)](<10.md>) -## LastModified - * $Id$ diff --git a/9.md b/9.md index e89e643..ff61dee 100644 --- a/9.md +++ b/9.md @@ -15,5 +15,3 @@ * 8.4 [第8章小结](<8.4.md>) * 9.1 [复合类型的数据——{资源}](<9.1.md>) -## LastModified - * $Id$ diff --git a/build.php b/build.php deleted file mode 100644 index 73b87f2..0000000 --- a/build.php +++ /dev/null @@ -1,121 +0,0 @@ -$v) { - if (preg_match('!^#([^#])$!', $v, $m)) { - $h1 = $m[1]; - unset($body[$k]); - } elseif (preg_match('!^## links!', $v, $m)) { - //接下来的两行是link - } - } - - //对content的code部分进行处理 - $content = preg_replace_callback( - "!(.*?)!ism", - create_function('$m','return "
    ".htmlspecialchars($m[2],ENT_QUOTES)."
    ";'), - $content - ); - - clearstatcache(); - - $c[$key]=array( - 'id'=>$id, - 'title'=>$meta[0], - 'prev'=>$meta[1], - 'next'=>$meta[2], - 'content'=>$content, - 'last_modified'=>date("Y-m-d",filemtime($value)) - ); -} - -function chapter_id($id) -{ - $id = explode(".",$id); - return $id[0]; -} - - -function page_title($id) -{ - global $c; - $key = id2key($id); - if(isset($c[$key])) - { - return $c[$key]['title']; - } -} - -function create($value) -{ - global $c; - extract($value); - $chapter_id = chapter_id($value['id']); - $chapter_title = page_title($chapter_id); - $chapter_link = page_link($chapter_id); - - if($value['prev']) - { - $prev_link = page_link($value['prev']); - $prev_title = page_title($value['prev']); - } - - if($value['next']) - { - $next_link = page_link($value['next']); - $next_title = page_title($value['next']); - } - - ob_start(); - require('tpl.html'); - $content = ob_get_contents(); - ob_end_clean(); - file_put_contents("html/".page_link($id),$content); -} - -//生成文章 -foreach($c as $value) -{ - create($value); -} - -//生成站点地图 - -$content = ' - - '; -foreach($c as $value) -{ - $link = page_link($value['id']); -$content .= << - http://phpbook.sinaapp.com/{$link} - {$value['last_modified']} - daily - 0.6 - -eot; -} -$content .= ''; - -file_put_contents("html/sitemap.xml",$content); diff --git a/index.md b/index.md index 7009293..e5065c2 100644 --- a/index.md +++ b/index.md @@ -7,15 +7,18 @@ * 我希望你能在Linux上来实践这个项目里的东西,那会比较容易一些,当然win也没关系。 本项目不是一个翻译工作,而是以翻译为起点的一个系统的、持续的跟踪介绍PHP内核相关知识的系统,相对于原书来讲,本项目的内容有以下不同 + * 基准PHP版本由5.1改为了5.3.6,也就是说本书的例子默认都是以PHP5.3.6为例的。 * 改写了大部分例子,方便像我一样的初学者。 * 会根据PHP的发展与自身的进步不断添加新的内容、优化原有内容。 现在项目的第一期的工作(初译)已经完成了,正在进入后续发布工作,每校正完一节就发布一节,期间如果朋友你发现了错误,还请帮忙斧正,我将在项目日志里声明以示感谢。此外还希望你能持续关注本项目,让我们一起为中国PHP事业的发展奉献一份力量。这个项目每一次的修正日志都将以以下方式公布,还请大家予以关注: - * *微博: [http://weibo.com/walu](http://weibo.com/walu)* - * *博客: [http://walu.sinaapp.com](http://walu.sinaapp.com)* + + * 微博: [http://weibo.com/walu](http://weibo.com/walu) + * 博客: [http://walu.sinaapp.com](http://walu.sinaapp.com) 本人不才,这个项目刚刚起步,我就已经碰到了很多的困难,期间得到了许多帮助,这里记录下来,以示感谢: + * 感谢Sara在2005年创作了[本书](http://www.amazon.com/Extending-Embedding-PHP-Sara-Golemon/dp/067232704X)。 * 感谢小胖姜。 * 感谢laruence大牛与你的[博客](http://www.laruence.com)。 @@ -23,6 +26,7 @@ * .... ## About Me + * 网名:Walu * 曾用名:Cnan * 身份:一个爱骑bike的Coder @@ -30,15 +34,14 @@ * 关注:安全、性能 * 联系:imcnanΘgmail.com * Blog:http://walu.sinaapp.com - * 11年末拿到了百度的船票。 + 10年一月份踏出学校进入所谓的社会混迹于当时的青岛普加。 + 当前主要使用PHP进行Web开发,研究PHP内核和扩展开发,偶尔前端缺人,我也会顶上去写Js和css。PS就算了,我不会。 + 我不是DBA,也不会难得一见的db种类,我只是mysql普通用户与mongodb的低度用户。 ## links * [目录]() - -## LastModified - * $Id$ diff --git a/preface.md b/preface.md index ec3d1df..013278f 100644 --- a/preface.md +++ b/preface.md @@ -1,120 +1,116 @@ # 《PHP扩展开发及内核应用》目录 + + > 上一节: [《PHP扩展开发及内核应用》]() + > 下一节: [PHP的生命周期](<1.md>) 目录中汉字部分代表已经翻译完成的章节,带链接的表示已经发布的,未待链接的表示正在校正即将发布的。 - * 1. [PHP的生命周期](1.md) - * 1. [让我们从SAPI开始](1.1.md) - * 2. [PHP的启动与终止](1.2.md) - * 3. [PHP的生命周期](1.3.md) - * 4. [线程安全](1.4.md) - * 5. [小结](1.5.md) - * 2. [PHP变量在内核中的实现](2.md) - * 1. [变量的类型](2.1.md) - * 2. [变量的值](2.2.md) - * 3. [创建PHP变量](2.3.md) - * 4. [变量的存储方式](2.4.md) - * 5. [变量的检索](2.5.md) - * 6. [类型转换](2.6.md) - * 7. [小结](2.7.md) - * 3. [内存管理](3.md) - * 1. [内存管理](3.1.md) - * 2. [引用计数](3.2.md) - * 3. [总结](3.3.md) - * 4. [配置编译环境](4.md) - * 1. [编译前的准备](4.1.md) - * 2. [PHP编译前的config配置](4.2.md) - * 3. [Unix/Linux平台下的编译](4.3.md) - * 4. [在Win32平台上编译PHP](4.4.md) - * 5. [小结](4.5.md) - * 5. [第一个扩展](5.md) - * 1. [一个扩展的基本结构](5.1.md) - * 2. [编译我们的扩展](5.2.md) - * 3. [静态编译](5.3.md) - * 4. [编写函数](5.4.md) - * 5. [小结](5.5.md) - * 6. [函数的返回值](6.md) - * 1. [一个特殊的参数:return_value](6.1.md) - * 2. [引用与函数的执行结果](6.2.md) - * 3. [小结](6.3.md) - * 7. [函数的参数](7.md) - * 1. [zend_parse_parameters](7.1.md) - * 2. [Arg Info 与类型绑定](7.2.md) - * 3. [小结](7.3.md) - * 8. [Array与HashTable](8.md) - * 1. [数组(C中的)与链表](8.1.md) - * 2. [操作HashTable的API](8.2.md) - * 3. [在内核中操作PHP语言中数组](8.3.md) - * 3. [小结](8.4.md) - * 9. [PHP中的资源类型](9.md) - * 1. [复合类型的数据——资源](9.1.md) - * 2. [Persistent Resources](9.2.md) - * 3. [资源自有的引用计数](9.3.md) - * 4. [小结](9.4.md) - * 10. [PHP中的面向对象(一)](10.md) - * 1. [zend_class_entry](10.1.md) - * 2. [定义一个类](10.2.md) - * 3. [定义一个接口](10.3.md) - * 4. [类的继承与接口的实现](10.4.md) - * 5. [小结](10.5.md) - * 11. [PHP中的面向对象(二)](11.md) - * 1. [生成对象的实例与调用方法](11.1.md) - * 2. [读写对象的属性](11.2.md) - * 3. [小结](11.3.md) - * 12. [启动与终止的那点事](12.md) - * 1. [关于生命周期](12.1.md) - * 2. [MINFO与phpinfo](12.2.md) - * 3. [常量](12.3.md) - * 4. [PHP扩展中的全局变量](12.4.md) - * 5. [PHP语言中的超级全局变量](12.5.md) - * 6. [小结](12.6.md) - * 13. INI Settings - * 1. Declaring and Accessing INI Settings - * 2. Summary - * 14. Accessing Streams - * 1. Streams Overview - * 2. Opening Streams - * 3. Accessing Streams - * 4. Static Stream Operations - * 5. Summary - * 15. Implementing Streams - * 1. PHP Streams Below the Surface - * 2. Wrapper Operations - * 3. Implementing a Wrapper - * 4. Manipulation - * 5. Inspection - * 6. Summary - * 16. Diverting the Stream - * 1. Contexts - * 2. Filters - * 3. Summary - * 17. Configuration and Linking - * 1. Autoconf - * 2. Looking for Libraries - * 3. Enforcing Module Dependencies - * 4. Speaking the Windows Dialect - * 5. Summary - * 18. 扩展生成器 - * 1. ext_skel生成器 - * 2. PECL_Gen生成器 - * 3. 小结 - * 19. Setting Up a Host Environment - * 1. The Embed SAPI - * 2. Building and Compiling a Host Application - * 3. Re-creating CLI by Wrapping Embed - * 4. Reusing Old Tricks - * 5. Summary - * 20. Advanced Embedding - * 1. Calling Back into PHP - * 2. Dealing with Errors - * 3. Initializing PHP - * 4. Overriding INI_SYSTEM and INI_PERDIR Options - * 5. Capturing Output - * 6. Extending and Embedding at Once - * 7. Summary - -## links - * [《PHP扩展开发及内核应用》]() - * 下一节: [PHP的生命周期](<1.md>) - -## LastModified - * $Id$ + 1. [PHP的生命周期](1.md) + 1. [让我们从SAPI开始](1.1.md) + 2. [PHP的启动与终止](1.2.md) + 3. [PHP的生命周期](1.3.md) + 4. [线程安全](1.4.md) + 5. [小结](1.5.md) + 2. [PHP变量在内核中的实现](2.md) + 1. [变量的类型](2.1.md) + 2. [变量的值](2.2.md) + 3. [创建PHP变量](2.3.md) + 4. [变量的存储方式](2.4.md) + 5. [变量的检索](2.5.md) + 6. [类型转换](2.6.md) + 7. [小结](2.7.md) + 3. [内存管理](3.md) + 1. [内存管理](3.1.md) + 2. [引用计数](3.2.md) + 3. [总结](3.3.md) + 4. [配置编译环境](4.md) + 1. [编译前的准备](4.1.md) + 2. [PHP编译前的config配置](4.2.md) + 3. [Unix/Linux平台下的编译](4.3.md) + 4. [在Win32平台上编译PHP](4.4.md) + 5. [小结](4.5.md) + 5. [第一个扩展](5.md) + 1. [一个扩展的基本结构](5.1.md) + 2. [编译我们的扩展](5.2.md) + 3. [静态编译](5.3.md) + 4. [编写函数](5.4.md) + 5. [小结](5.5.md) + 6. [函数的返回值](6.md) + 1. [一个特殊的参数:return_value](6.1.md) + 2. [引用与函数的执行结果](6.2.md) + 3. [小结](6.3.md) + 7. [函数的参数](7.md) + 1. [zend_parse_parameters](7.1.md) + 2. [Arg Info 与类型绑定](7.2.md) + 3. [小结](7.3.md) + 8. [Array与HashTable](8.md) + 1. [数组(C中的)与链表](8.1.md) + 2. [操作HashTable的API](8.2.md) + 3. [在内核中操作PHP语言中数组](8.3.md) + 3. [小结](8.4.md) + 9. [PHP中的资源类型](9.md) + 1. [复合类型的数据——资源](9.1.md) + 2. [Persistent Resources](9.2.md) + 3. [资源自有的引用计数](9.3.md) + 4. [小结](9.4.md) + 10. [PHP中的面向对象(一)](10.md) + 1. [zend_class_entry](10.1.md) + 2. [定义一个类](10.2.md) + 3. [定义一个接口](10.3.md) + 4. [类的继承与接口的实现](10.4.md) + 5. [小结](10.5.md) + 11. [PHP中的面向对象(二)](11.md) + 1. [生成对象的实例与调用方法](11.1.md) + 2. [读写对象的属性](11.2.md) + 3. [小结](11.3.md) + 12. [启动与终止的那点事](12.md) + 1. [关于生命周期](12.1.md) + 2. [MINFO与phpinfo](12.2.md) + 3. [常量](12.3.md) + 4. [PHP扩展中的全局变量](12.4.md) + 5. [PHP语言中的超级全局变量](12.5.md) + 6. [小结](12.6.md) + 13. INI Settings + 1. Declaring and Accessing INI Settings + 2. Summary + 14. Accessing Streams + 1. Streams Overview + 2. Opening Streams + 3. Accessing Streams + 4. Static Stream Operations + 5. Summary + 15. Implementing Streams + 1. PHP Streams Below the Surface + 2. Wrapper Operations + 3. Implementing a Wrapper + 4. Manipulation + 5. Inspection + 6. Summary + 16. Diverting the Stream + 1. Contexts + 2. Filters + 3. Summary + 17. Configuration and Linking + 1. Autoconf + 2. Looking for Libraries + 3. Enforcing Module Dependencies + 4. Speaking the Windows Dialect + 5. Summary + 18. 扩展生成器 + 1. ext_skel生成器 + 2. PECL_Gen生成器 + 3. 小结 + 19. Setting Up a Host Environment + 1. The Embed SAPI + 2. Building and Compiling a Host Application + 3. Re-creating CLI by Wrapping Embed + 4. Reusing Old Tricks + 5. Summary + 20. Advanced Embedding + 1. Calling Back into PHP + 2. Dealing with Errors + 3. Initializing PHP + 4. Overriding INI_SYSTEM and INI_PERDIR Options + 5. Capturing Output + 6. Extending and Embedding at Once + 7. Summary From 1d41768ea57514bec2fad8a6cc2aabc20dca45ef Mon Sep 17 00:00:00 2001 From: nkysg Date: Wed, 12 Dec 2012 11:15:01 +0800 Subject: [PATCH 3/5] Update 5.1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 少了一个头文件宏 --- 5.1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/5.1.md b/5.1.md index f7a943a..688e74a 100644 --- a/5.1.md +++ b/5.1.md @@ -72,6 +72,7 @@ ZEND_GET_MODULE(walu) 根据我们平时的开发习惯,应该不会把所有代码都写在这一个文件里的,我们需要把上述代码放在两个文件里,一个头文件,一个c文件。 ````c //php_walu.h +#ifndef WALU_H #define WALU_H //加载config.h,如果配置了的话 From 31d2cc7918a1f07c20a8fb7b6afe2a9d2c49432d Mon Sep 17 00:00:00 2001 From: nkysg Date: Wed, 12 Dec 2012 11:18:33 +0800 Subject: [PATCH 4/5] Update 8.1.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C语言编译错误 --- 8.1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/8.1.md b/8.1.md index 0c322b0..2296839 100644 --- a/8.1.md +++ b/8.1.md @@ -20,11 +20,11 @@ zval ***args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval**), 0); 链表也是一种经常被使用的一种数据结构。链表中的每一个元素都至少有两个元素,一个指向它的下一个元素,一个用来存放它自己的数据,就像下面定义的那样: ````c typedef struct _namelist namelist; -struct +struct _namelist { struct _namelist *next; char *name; -}_namelist; +}; ```` 我们可以声明一个其类型的元素: From 7826efeca875ee99cadd2e2ff5e7b0ea5823feff Mon Sep 17 00:00:00 2001 From: walu Date: Sun, 23 Dec 2012 19:26:25 +0800 Subject: [PATCH 5/5] fix links. --- 1.md | 10 +++++----- 10.md | 13 ++++++------- 11.md | 10 +++++----- 3.md | 11 ++++------- 4.md | 15 ++++++--------- 5.md | 14 +++++--------- 6.md | 11 ++++++----- 7.md | 9 ++++----- 8.md | 11 +++++------ 9.md | 11 +++++------ 10 files changed, 51 insertions(+), 64 deletions(-) diff --git a/1.md b/1.md index fa1c6e1..3a808fa 100644 --- a/1.md +++ b/1.md @@ -1,11 +1,11 @@ # 1 PHP的生命周期 ## 目录 - * 1. [让我们从SAPI开始](1.1.html) - * 2. [PHP的启动与终止](1.2.html) - * 3. [PHP的生命周期](1.3.html) - * 4. [线程安全](1.4.html) - * 5. [小结](1.5.html) + * 1. [让我们从SAPI开始](1.1.md) + * 2. [PHP的启动与终止](1.2.md) + * 3. [PHP的生命周期](1.3.md) + * 4. [线程安全](1.4.md) + * 5. [小结](1.5.md) 在平常的Web环境中,我们并不需要单独启动PHP,它一般都会作为一个模块自动加载到web-server里面去,如apache加载的php5.so。只要我们启动了web-server,被一起加载的php便会和服务器一起解析被请求的php脚本。 diff --git a/10.md b/10.md index 4491ce5..44c287d 100644 --- a/10.md +++ b/10.md @@ -1,12 +1,11 @@ # 10 PHP中的面向对象(一) -
      -
    • [1. zend_class_entry](ch10.1.html)
    • -
    • [2. 定义一个类](ch10.2.html)
    • -
    • [3. 定义一个接口](ch10.3.html)
    • -
    • [4. 类的继承与接口的实现](ch10.4.html)
    • -
    • [5. 小结](ch10.5.html)
    • -
    + * [1. zend_class_entry](10.1.md) + * [2. 定义一个类](10.2.md) + * [3. 定义一个接口](10.3.md) + * [4. 类的继承与接口的实现](10.4.md) + * [5. 小结](10.5.md) + 面向对象的概念这里就不再叙述了。原书中把这一部分的知识分开到PHP4和PHP5中来讲的,这里我做了大幅的调整,几乎是进行了重写。前一部分主要介绍了如何定义类、接口等一些声明类的操作。后一部分主要介绍了对象的使用等一些对实例的操作。 diff --git a/11.md b/11.md index 5cfff6e..0eddb5a 100644 --- a/11.md +++ b/11.md @@ -1,10 +1,10 @@ # 11 PHP中的面向对象(二) -
      -
    • [1. 生成对象的实例与调用方法](ch11.1.html)
    • -
    • [2. 读写对象的属性](ch11.2.html)
    • -
    • [3. 小结](ch11.3.html)
    • -
    + + * [1. 生成对象的实例与调用方法](11.1.md) + * [2. 读写对象的属性](11.2.md) + * [3. 小结](11.3.md) + 上一章里,我们看了一下如何在PHP扩展里定义类与接口,那这一章里我们将入手一下如何在PHP扩展中操作类的实例————对象。 PHP语言中的面向对象其实是分为三个部分来实现的,class、object、refrence。class就是我们所说的类,可以直观的理解为前面章节中所描述的zend_class_entry。object就是实际的对象。每一个zval并不直接包含具体的object,而是通过一个索引--refrence与其联系。也就是说,每个class都有很多个object实例,并把他们统一的放在一个数组里,每个zval只要记住自己相应的key就行了。如此一来,我们在传递zval时候,实际上传递的是一个索引,而不是内存中具体的对象数据。 diff --git a/3.md b/3.md index 812a8c1..74b9520 100644 --- a/3.md +++ b/3.md @@ -1,12 +1,9 @@ # 3 内存管理 -
      -
      • -
      • [1. 内存管理](ch3.1.html)
      • -
      • [2. 引用计数](ch3.2.html)
      • -
      • [3. 总结](ch3.3.html)
      • -
    • -
    + * [1. 内存管理](3.1.md) + * [2. 引用计数](3.2.md) + * [3. 总结](3.3.md) + 脚本语言与编译型语言最根本的区别可能就在内存管理上。但这并不限于脚本语言,现在越来越多的语言不再允许用户直接操作内存,而由虚拟机来代替用户负责内存的分配及回收,如C#、Java、PHP等。 diff --git a/4.md b/4.md index 909d3fe..7a65982 100644 --- a/4.md +++ b/4.md @@ -1,14 +1,11 @@ # 4 动手编译PHP -
      -
      • -
      • [1. 编译前的准备](ch4.1.html)
      • -
      • [2. PHP编译前的config配置](ch4.2.html)
      • -
      • [3. Unix/Linux平台下的编译](ch4.3.html)
      • -
      • [4. 在Win32平台上编译PHP](ch4.4.html)
      • -
      • [5. 小结](ch4.5.html)
      • -
    • -
    + * [1. 编译前的准备](4.1.md) + * [2. PHP编译前的config配置](4.2.md) + * [3. Unix/Linux平台下的编译](4.3.md) + * [4. 在Win32平台上编译PHP](4.4.md) + * [5. 小结](4.5.md) + 到现在为止,你肯定应该在至少一种平台上安装过PHP,并用它来开发你的web程序了。你可能下载的win32平台下的iis或者apache对应的安装包,也可能使用了由第三方提供的linux、bsd等平台下的二进制包。而现在,则是我们动手自己编译PHP的时候了。这也是我们动手开发第一个扩展的最后一项准备知识了。 强烈推荐你在Linux下调试本章的程序,因为win部分我还没有翻译,:-) diff --git a/5.md b/5.md index 41fc427..d228575 100644 --- a/5.md +++ b/5.md @@ -1,14 +1,10 @@ # 5 Your First Extension -
      -
      • -
      • [1. 一个扩展的基本结构](ch5.1.html)
      • -
      • [2. 编译我们的扩展](ch5.2.html)
      • -
      • [3. 静态编译](ch5.3.html)
      • -
      • [4. 编写函数](ch5.4.html)
      • -
      • [5. 小结](ch5.5.html)
      • -
    • -
    + * [1. 一个扩展的基本结构](5.1.md) + * [2. 编译我们的扩展](5.2.md) + * [3. 静态编译](5.3.md) + * [4. 编写函数](5.4.md) + * [5. 小结](5.5.md) 每一个PHP扩展都至少需要两个文件:一个配置文件和一个源文件。配置文件用来告诉编译器应该编译哪几个文件,以及编译本扩展是否需要的其它lib。 diff --git a/6.md b/6.md index a7c6bc4..2ca8cd3 100644 --- a/6.md +++ b/6.md @@ -1,10 +1,11 @@ # 6 函数返回值 -本章目录:
      -
    • [1. 一个特殊的参数:return_value](ch6.1.html)
    • -
    • [2. 引用与函数的执行结果](ch6.2.html)
    • -
    • [3. 小结](ch6.3.html)
    • -
    +本章目录 + + * [1. 一个特殊的参数:return_value](6.1.md) + * [2. 引用与函数的执行结果](6.2.md) + * [3. 小结](6.3.md) + PHP语言中函数的返回值是通过return来完成了,就像下面的程序: ````php -
  • [1. zend_parse_parameters](ch7.1.html)
  • -
  • [2. Arg Info 与类型绑定](ch7.2.html)
  • -
  • [3. 小结](ch7.3.html)
  • - + * [1. zend_parse_parameters](7.1.md) + * [2. Arg Info 与类型绑定](7.2.md) + * [3. 小结](7.3.md) + 前面的章节我们look了一下如何在扩展中定义函数,它们的实现大都比较简单,但是在实际工作中,肯定会碰到函数接收参数的问题,而它就是我们这一章要讲解的内容。 diff --git a/8.md b/8.md index c5e9505..40d6a45 100644 --- a/8.md +++ b/8.md @@ -1,11 +1,10 @@ # 8 使用HashTable与{数组} -
      -
    • [1. 数组(C中的)与链表](ch8.1.html)
    • -
    • [2. 操作HashTable的API](ch8.2.html)
    • -
    • [3. 在内核中操作PHP语言中数组](ch8.3.html)
    • -
    • [3. 小结](ch8.4.html)
    • -
    + * [1. 数组(C中的)与链表](8.1.md) + * [2. 操作HashTable的API](8.2.md) + * [3. 在内核中操作PHP语言中数组](8.3.md) + * [3. 小结](8.4.md) + 在C语言中,我们可以自定义各种各样的数据结构,用来把很多数据保存在一个变量里面,但是每种数据结构都有自己的优缺点,PHP内核规模如此庞大,是否已经找到了一些非常棒的解决方法呢? diff --git a/9.md b/9.md index ff61dee..800d527 100644 --- a/9.md +++ b/9.md @@ -1,11 +1,10 @@ # 9 PHP中的资源类型 -
      -
    • [1. 复合类型的数据——{资源}](ch9.1.html)
    • -
    • [2. Persistent Resources](ch9.2.html)
    • -
    • [3. {资源}自有的引用计数](ch9.3.html)
    • -
    • [4. 小结](ch9.4.html)
    • -
    + * [1. 复合类型的数据——{资源}](9.1.md) + * [2. Persistent Resources](9.2.md) + * [3. {资源}自有的引用计数](9.3.md) + * [4. 小结](9.4.md) + 截止到现在,我们已经熟悉了PHP语言中的字符串、数字、布尔以及数组类型的数据类型了,接下来,我们将接触另外一种PHP独特的数据类型——资源(Resource)。