Skip to content

Commit

Permalink
Merge pull request walu#131 from xuwenzhi/master
Browse files Browse the repository at this point in the history
结合这些天的学习,修改一些格式、错别字
  • Loading branch information
walu committed Mar 8, 2016
2 parents d1d6c58 + 4e69963 commit a0aa664
Show file tree
Hide file tree
Showing 8 changed files with 16 additions and 11 deletions.
2 changes: 1 addition & 1 deletion 2.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
然后申请一块内存并让指针指向它。如果你脑海里浮现出了malloc(sizeof(zval))的影子,
那么请你立即刹车,不要用malloc来做这件事情,内核给我们提供了相应的宏来处理这件事,
理由和以前一样:为了代码漂亮并保持版本升级时的兼容性。
这个宏的是:MAKE_STD_ZVAL(pzv)。这个宏会用内核的方式来申请一块内存并将其地址付给pzv,
这个宏是:MAKE_STD_ZVAL(pzv)。这个宏会用内核的方式来申请一块内存并将其地址付给pzv,
并初始化它的refcount和is_ref两个属性,更棒的是,它不但会自动的处理内存不足问题,
还会在内存中选个最优的位置来申请。

Expand Down
2 changes: 1 addition & 1 deletion 2.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ zend_hash_find()函数是内核提供的操作HashTable的API之一,如果你
其它很多地方都在应用HashTable**(这就是个神器)**
一个HashTable有很多元素,在内核里叫做bucket。然而每个bucket的大小是固定的,
所以如果我们想在bucket里存储任意数据时,最好的办法便是申请一块内存保存数据,
然后在bucket里保存它的指针。以zval *foo为例
然后在bucket里保存它的指针。`zval *foo`为例
内核会先申请一块足够保存指针内存来保存foo,比如这块内存的地址是p,也就是p=&foo,
并在bucket里保存p,这时我们便明白了,p其实就是`zval**`类型的。
至于bucket为什么保存`zval**`类型的指针,而不是直接保存`zval*`类型的指针,我们到下一章在详细叙述。
Expand Down
2 changes: 1 addition & 1 deletion 3.2.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 3.2 内存管理
# 3.2 引用计数

对于PHP这种需要同时处理多个请求的程序来说,申请和释放内存的时候应该慎之又慎,一不小心便会酿成大错。另一方面,除了要安全的申请和释放内存外,还应该做到内存的最小化使用,因为它可能要处理每秒钟数以千计的请求,为了提高系统整体的性能,每一次操作都应该只使用最少的内存,对于不必要的相同数据的复制则应该能免则免。我们来看下面这段PHP代码:
````php
Expand Down
2 changes: 1 addition & 1 deletion 5.1.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 5.1 Your First Extension

### 配置文件
才开始,我们先用最快的(不是最标准的)的方式来建立一个代码最少的扩展。在php源码文件夹的ext目录下创建一个新的文件,这里我取的名字叫做walu,它往往就是我们扩展的名字。其实这个文件夹可以放在任何一个位置,但是为了我们在后面介绍win32的编译与静态编译,我们还是把它放在php源码的ext目录下。
才开始,我们先用最快的(不是最标准的)的方式来建立一个代码最少的扩展。在php源码文件夹的ext目录下创建一个新的文件夹,这里我取的名字叫做walu,它往往就是我们扩展的名字。其实这个文件夹可以放在任何一个位置,但是为了我们在后面介绍win32的编译与静态编译,我们还是把它放在php源码的ext目录下。
现在,我们在这个目录下创建一个config.m4文件,并输入以下内容:

PHP_ARG_ENABLE(walu,
Expand Down
10 changes: 8 additions & 2 deletions 6.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ ZEND_FUNCTION(sample_array_range)
````
### 以引用的形式返回值
你肯定已经在手册中看到过有关将函数的返回值以引用的形式的返回的技术了。但是因为某些历史原因,在为扩展编写函数时候如果想让返回值以引用的形式返回时一定要慎之又慎,因为在php5.1之前,根本就没法真正的实现这个功能,look一下下面的代码:
````php
<?php
//关于PHP语言中引用形式返回值的详述,请参考PHP手册。
$a = 'china';
Expand All @@ -183,9 +185,12 @@ $b = &return_by_ref();
$b = "php";
echo $a;
//此时程序输出php
</php>
````

在上面的代码中,$b其实是$a的一个引用,当最后一行代码执行后,$a和$b都开始寻找‘bar’这个字符串对应的zval,让我们以内核的角度重新观察这一切:
<code c>

````c
#if (PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
ZEND_FUNCTION(return_by_ref)
{
Expand Down Expand Up @@ -224,6 +229,7 @@ ZEND_FUNCTION(return_by_ref)
#endif /* PHP >= 5.1.0 */

````

return_value_ptr是定义zend internal function时的另外一个重要参数,他是一个zval**类型的指针,并且指向函数的返回值。我们调用zval_ptr_dtor()函数后,默认的return_value便被废弃了。这里的$a变量如果是与某个非引用形式的变量共用一个zval的话,便要进行分离。
不幸的是,如果你编译上面的代码,使用的时候便会得到一个段错误。为了使它能够正常的工作,需要在源文件中加一些东西:
````c
Expand Down
2 changes: 1 addition & 1 deletion 6.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ZEND_FUNCTION(byref_calltime)
{
zval *a;

//我们我接收的参数传给zval *a;
//将我们接收的参数传给zval *a;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a) == FAILURE)
{
RETURN_NULL();
Expand Down
5 changes: 2 additions & 3 deletions 7.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ ZEND_FUNCTION(sample_hello_world) {

````
如果你不传递第二个参数,则扩展函数会被认为默认而不去修改载体。所以,我们需要自己来预先设置有载体的值,它往往是是NULL,或者一个与函数逻辑有关的值。
每个zval,包括IS_NULL型的zval,都需要占用一定的内存空间,并且需要cpu的计算资源来为它申请内存、初始化,并在它们完成工作后释放掉。但是很多代码都都没有意识到这一点。有很多代码都会把一个null型的值包裹成zval的IS_NULL类型,在扩展开发里这种操作是可以优化的,我们可以把参数接收城C语言里的NULL。我们就这一个问题看以下代码:
每个zval,包括IS_NULL型的zval,都需要占用一定的内存空间,并且需要cpu的计算资源来为它申请内存、初始化,并在它们完成工作后释放掉。但是很多代码都都没有意识到这一点。有很多代码都会把一个null型的值包裹成zval的IS_NULL类型,在扩展开发里这种操作是可以优化的,我们可以把参数接收成C语言里的NULL。我们就这一个问题看以下代码:
````c
ZEND_FUNCTION(sample_arg_fullnull) {
zval *val;
Expand All @@ -161,8 +161,7 @@ ZEND_FUNCTION(sample_arg_fullnull) {
}
ZEND_FUNCTION(sample_arg_nullok) {
zval *val;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!",
&val) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!",&val) == FAILURE) {
RETURN_NULL();
}
if (!val) {
Expand Down
2 changes: 1 addition & 1 deletion 7.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ zend_parse_parameters()本身可以保证传递过来的参数是一个数组。
````
需要注意的是,此时第一个参数的值是数字1,代表着以引用的方式传递。其实这个参数对于对象来说几乎没用,因为ZE2中所有的对象在当作函数参数的时候都是默认以引用的形式传递的。但是我们又必须把这个参数设置为数字1,除非你不想让你的扩展与PHP4兼容。在PHP4中,对象是传递的一个完整Copy,而非通过引用。
<div class="tip-common">对于数组和对象参数,不要忘记最后的允许为NULL的参数。更多的信息请参考第6章最后一节的有关叙述。</code>
对于数组和对象参数,不要忘记最后的允许为NULL的参数。更多的信息请参考第6章最后一节的有关叙述。
通过arg info的方式来实现类型绑定的功能只对ZE2有效,也就是PHP5+。如果你想在PHP4上实现相应的功能,那需要用 zend_get_parameters()函数来接收参数,然后通过Z_TYPE_P()宏函数来检测参数的类型或者通过convert_to_type()函数进行类型转换。
Expand Down

0 comments on commit a0aa664

Please sign in to comment.