<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[用C写memcache 扩展]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Mon, 27 Sep 2010 15:40:04 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	<br/>最新memcache 扩展（教大家开始PHP扩展之旅）<br/>今天花了点时间把扩展又重新写了一遍。去掉了旧的ZEND API 启用了新的API&nbsp;&nbsp;。而且已经支持了数组和对象等存储。 支持：<br/><br/>mc_connect()&nbsp;&nbsp;<br/><br/>mc_set()<br/><br/>mc_get()<br/><br/>mc_delete()<br/><br/>mc_flush()<br/><br/>mc_quit()<br/><br/>mc_close()<br/><br/>等基本函数。<br/><br/>先上包包：&nbsp;&nbsp;mc.tar.gz (508.09 KB) <br/> mc.tar.gz (508.09 KB)<br/>下载次数: 114<br/><br/>2008-5-5 21:30<br/><br/><br/>安装前需要先安装libmemcached 库&nbsp;&nbsp;，因为这个扩展是基于最新的libmemcached 库开发的。<br/><br/>代码后面慢慢讲解!!!!!<br/><br/>最后要实现的就是压缩算法。&nbsp;&nbsp;算法已经选好。&nbsp;&nbsp;gzlib 算法。 有空了就加上去。<br/><br/>同时在这里谢谢6间房网的toplee大哥对我的指点。忠心感谢。<br/><br/>[ 本帖最后由 逆雪寒 于 2008-5-6 14:33 编辑 ]<br/>本帖最近评分记录<br/>PHPChina 开源币 +10 原创内容 2008-5-28 10:03 <br/> <br/>学海无崖，回头是岸http://laoniphp.com&nbsp;&nbsp;<br/> <br/>UID<br/>24549 <br/>帖子<br/>2335 <br/>精华<br/>7 <br/>积分<br/>5845 <br/>开源币<br/>272&nbsp;&nbsp;<br/>阅读权限<br/>100 <br/>在线时间<br/>1118 小时 <br/>注册时间<br/>2007-1-24 <br/>最后登录<br/>2008-7-21 <br/>查看详细资料<br/><br/> 引用 使用道具 报告 回复 TOP <br/><br/>第二周获奖名单公布 <br/><br/>逆雪寒 <br/><br/>版主<br/><br/><br/><br/>&nbsp;&nbsp;<br/><br/>个人空间 <br/>发短消息 <br/>加为好友 <br/>当前离线 <br/> 2# 大 中 小 发表于 2008-5-5 21:31&nbsp;&nbsp;只看该作者 <br/> 扩展的环境安装。放到最后再说吧。想讲解代码先<br/><br/>我写扩展的环境是 linux ,&nbsp;&nbsp;php5.2.5&nbsp;&nbsp;apache2&nbsp;&nbsp;,vim 就这么简单<br/><br/>我们生成扩展环境后。就可以看到mc.c文件。这里主要是我们写扩展的文件。首先我们必须定义我们自己的扩展函数名。需要用PHP_FE() 来定义。如果不定义PHP会认不出我们的函数。<br/><br/>看图。我的这个memcache 扩展。写了几个简单的函数 :<br/><br/>&nbsp;&nbsp;<br/> 1.jpg (24.67 KB)<br/><br/>2008-5-6 09:38<br/><br/><br/><br/>上面定义了&nbsp;&nbsp;mc_connect()连接mc的函数&nbsp;&nbsp; mc_set() 把对象或数组或字符等存到memcache 内存的函数。&nbsp;&nbsp;mc_get() 从memcache 内存获取数值&nbsp;&nbsp;mc_delete() 干掉内存中我们保存的东西。&nbsp;&nbsp;mc_flush() 清楚内存中我们保存的数据。 mc_quit() 断开mc连接。&nbsp;&nbsp; mc_close() 关闭 mc资源<br/><br/><br/>下面我们先讲解第一个函数&nbsp;&nbsp;mc_connect() 连接函数。这个函数可能是最难的一个了。因为涉及到资源。<br/><br/>&nbsp;&nbsp;<br/> 2.jpg (32.16 KB)<br/><br/>2008-5-6 09:41<br/><br/><br/>我们先自定义一个我们自己的函数。这个还不是PHP意义上的函数。只是我们的一个在C文件里自定义的一个函数。要想成为PHP的函数。那还需要这样：<br/><br/>&nbsp;&nbsp;<br/> 3.jpg (6.94 KB)<br/><br/>2008-5-6 09:42<br/><br/><br/>PHP扩展中。PHP的函数需要用 PHP_FUNCTION&nbsp;&nbsp;这个宏函数来定义声明。其实所有的逻辑多可以在 PHP_FUNCTION(mc_connect)&#123;&#125; 里面实现。但这样做是为了以后更好的扩展。<br/><br/><br/>看 _mc_connect() 这个函数&nbsp;&nbsp;的&nbsp;&nbsp; INTERNAL_FUNCTION_PARAMETERS&nbsp;&nbsp; 宏参数。这个参数是PHP 里面给我们定义的宏。因为我们函数 _mc_connect() 需要接受 PHP层 的参数。 但这个函数又不属于PHP 的函数。所以我们需要使用 INTERNAL_FUNCTION_PARAMETERS 宏来创建 PHP函数的环境。 <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>_mc_connect(INTERNAL_FUNCTION_PARAMETERS)&#123;&nbsp;&nbsp;&#125;<br/><br/><br/>继续我们再看一个。PHP扩展中用得最多的东西： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>ZEND_NUM_ARGS()<br/><br/><br/>这个宏是用来获取我们输入的参数个数，比如：&nbsp;&nbsp;xnijiji(&#039;s&#039;,&#039;e&#039;)&nbsp;&nbsp;&nbsp;&nbsp;那么我们的&nbsp;&nbsp;ZEND_NUM_ARGS() 就会得到2&nbsp;&nbsp;，因为这个函数有两个参数。写扩展的时候我们十分需要知道用户输入的参数个数。因为下个接参函数十分需要这个，看： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);<br/><br/><br/>这个是函数原形。我们看下MC扩展中实际的是这样： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>char *hostname;<br/>long port;<br/>int s_len;<br/>int args = ZEND_NUM_ARGS();<br/>zend_parse_parameters(args TSRMLS_CC,&quot;sl&quot;, &amp;hostname,&amp;s_len,&amp;port)==FAILURE<br/><br/><br/>我们先用整形变量 args 来获取 参数的个数。&nbsp;&nbsp;然后使用&nbsp;&nbsp;zend_parse_parameters() 来接收我们的参数值。&nbsp;&nbsp;<br/><br/>参数： 字符指针&nbsp;&nbsp;hostname&nbsp;&nbsp;是 MC服务器地址&nbsp;&nbsp;.&nbsp;&nbsp;s_len 当然是字符长度拉。不废话。&nbsp;&nbsp;port 很简单是&nbsp;&nbsp;MC服务器端口拉。<br/>OK。这个讲解完了继续<br/><br/>TSRMLS_CC&nbsp;&nbsp;这个鸟是在多线程的服务器上。为了线程安全的宏。太高级了。我们不鸟。跳过。&nbsp;&nbsp;<br/><br/>&quot;sl&quot;&nbsp;&nbsp; 这个又是什么东西呢。&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;&nbsp;代表我们接受的第一个参数是字符形的&nbsp;&nbsp;l&nbsp;&nbsp;当表我们接受长整形的。&nbsp;&nbsp; C语言就是类型很严格。还是PHP爽。那里还管你什么鸟类型。 类型一定要对哦。要不会出现错误。<br/><br/>如果用户输入参数过多。或是类型不对。那么我们就用宏&nbsp;&nbsp;：<br/><br/>WRONG_PARAM_COUNT;<br/><br/>来发出一个错误。看E文就知道。就是说 参数个数太多了。<br/><br/>如果用户输入参数正确。那么我们就可以 做进一步的处理了。就是拿那些参数的值做我们想做的事。<br/><br/>我们拿什么操作memcache 呢？&nbsp;&nbsp;我选择了比较新的libmemcached 库。 所以我们也要懂这个库。这个是C语言中操作memcache 的一个库。下面我们来简单的看下这个库 <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>memcached_st *yhm_memc;<br/>memcached_return yhm_rc;<br/><br/><br/>memcached_st 是&nbsp;&nbsp;libmemcached 库自己定义的数据类型。是接受MC资源或是说句柄或是说字符描述符的。 <br/>memcached_return 呢 这个是来接受返回结果的。结果有 MEMCACHED_SUCCESS&nbsp;&nbsp;等等信息。<br/><br/><br/>看下怎么用。我们用libmemcached 来连接memcache ： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>yhm_memc = memcached_create(NULL);<br/>yhm_rc = memcached_server_add(yhm_memc,hostname,port);<br/><br/><br/>memcached_create 是初始化 一个句柄。<br/>memcached_server_add&nbsp;&nbsp;这个才是主菜。大家看就知道了。 它是用来连接mc服务器的。<br/>memcached_server_add(yhm_memc,hostname,port);&nbsp;&nbsp; hostname&nbsp;&nbsp;和port 两个变量都是用户输入的。上面有讲解。就这样。&nbsp;&nbsp;mc在PHP扩展中给连接了。&nbsp;&nbsp; yhm_memc&nbsp;&nbsp;这个变量很重要。因为我们连接了MC后。这个变量成了资源。我们在以后的扩展函数中都需要用到。所以存在一个资源保存的问题。<br/><br/><br/>资源怎么保存呢。怎么给每个扩展中的函数使用呢。在注册资源的时候我们需要先在我们这个MC模块启动的时候就注册一个资源注销函数，方便让模块卸载的时候调用清除MC资源<br/><br/>&nbsp;&nbsp;<br/> 6.jpg (36.79 KB)<br/><br/>2008-5-6 10:47<br/><br/><br/><br/>_close_mc_link 函数是我们自定义的&nbsp;&nbsp;参数：&nbsp;&nbsp;zend_rsrc_list_entry *rsrc TSRMLS_DC 是一个结构体：里面保存着我们的资源。大概鸟样是这样的： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>typedef struct _zend_rsrc_list_entry &#123;<br/>&nbsp;&nbsp; void *ptr;<br/>&nbsp;&nbsp; int type;<br/>&nbsp;&nbsp; int refcount;<br/>&#125; zend_rsrc_list_entry;<br/><br/><br/>成员 void *ptr 才真正指向你的资源。<br/><br/>其实我们不用管那么多。用就是了。 <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>memcached_st *link = (memcached_st *)rsrc-&gt;ptr;<br/>memcached_quit(link);<br/><br/><br/>我们使用libmemcached 库的&nbsp;&nbsp;memcached_quit() 来断开资源连接。逻辑是实现了。但还要注册到PHP内核才行。<br/><br/>注册到内核我们使用: <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>le_link=zend_register_list_destructors_ex(_close_mc_link,NULL,RESOURCE_TAG,module_number);<br/><br/><br/>le_link&nbsp;&nbsp;和&nbsp;&nbsp;RESOURCE_TAG 和&nbsp;&nbsp;module_number 都是在头文件定义的。那么上菜看下先：<br/><br/>&nbsp;&nbsp;<br/> 4.jpg (13.44 KB)<br/><br/>2008-5-6 11:01<br/><br/><br/>le_link&nbsp;&nbsp;静态变量就是我们在注册函数析构函数时返回的资源类型句柄。<br/><br/>资源名&nbsp;&nbsp;宏RESOURCE_TAG&nbsp;&nbsp; 定义为&nbsp;&nbsp;yhm_mc&nbsp;&nbsp;也就是这个资源 var_dump() 的名字为yhm_mc ： 看下var_dump() 后的显示 <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>resource(2) of type (yhm_mc)<br/><br/><br/>PHP中注册资源的函数是&nbsp;&nbsp;zend_register_resource()&nbsp;&nbsp;<br/><br/><br/><br/>因为常用到所以我再一次封装成自己的宏： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>#define YHM_REGISTER_RESOURCE(lk) &#92;<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;zend_register_resource(return_value,lk,le_link);<br/>&#125;<br/><br/><br/>lk&nbsp;&nbsp;为需要注册的资源。 le_link 是注册构释时候返回的资源。都是需要的。&nbsp;&nbsp;return_value 是PHP核心定义的。&nbsp;&nbsp;是一个zval 容器。里面装的就是返回给PHP层面的值。<br/><br/>OK。大家都了解了吧。我们回到&nbsp;&nbsp;PHP_FUNCTION(mc_connect) 函数里。里面有这么段： <br/>复制PHP内容到剪贴板 <br/>PHP代码:<br/>yhm_memc = memcached_create(NULL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;yhm_rc = memcached_server_add(yhm_memc,hostname,port);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(yhm_rc == MEMCACHED_SUCCESS)&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;YHM_REGISTER_RESOURCE(yhm_memc);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;else&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETURN_FALSE;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/><br/>明白了吧。使用自己的宏 YHM_REGISTER_RESOURCE() 把资源&nbsp;&nbsp;yhm_memc&nbsp;&nbsp;注册到PHP里面去。不成功就。RETURN_FALSE;&nbsp;&nbsp; 这个是PHP提供给我们返回 false 的一个宏。<br/><br/>OK。粗略讲完了这个函数。 学扩展需要先看一遍扩展的手册。最好这样拉。要不会有点郁闷 <br/><br/>来源：http://fyp832008.blog.163.com/blog/static/91439416200810462028349/
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 用C写memcache 扩展]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>