摘要:起步很多时候,需要把控制权限交给用户,或者在扩展里完成某件事后去回调用户的方法。在扩展里是通过函数来调用用户空间的函数的。收集回调函数的返回值。回调函数需要传递参数的个数。利用语言多线程库来实现一个简单的并行扩展。
起步
很多时候,需要把控制权限交给用户,或者在扩展里完成某件事后去回调用户的方法。
在PHP扩展里是通过 call_user_function_ex 函数来调用用户空间的函数的。
定义它的定义在 Zend/zend_API.h :
#define call_user_function_ex(function_table, object, function_name, retval_ptr, param_count, params, no_separation, symbol_table) _call_user_function_ex(object, function_name, retval_ptr, param_count, params, no_separation)
通过宏定义替换为_call_user_function_ex,其中参数 function_table 被移除了,它之所以在API才存在大概是为了兼容以前的写法。函数的真正定义是:
ZEND_API int _call_user_function_ex( zval *object, zval *function_name, zval *retval_ptr, uint32_t param_count, zval params[], int no_separation);
参数分析:
zval *object:这个是用来我们调用类里的某个方法的对象。
zval *function_name:要调用的函数的名字。
zval *retval_ptr:收集回调函数的返回值。
uint32_t param_count:回调函数需要传递参数的个数。
zval params[]: 参数列表。
int no_separation:是否对zval进行分离,如果设为1则直接会出错,分离的作用是为了优化空间。
回调功能的实现PHP_FUNCTION(hello_callback) { zval *function_name; zval retval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) { return; } if (Z_TYPE_P(function_name) != IS_STRING) { php_printf("Function require string argumnets!"); return; } //TSRMLS_FETCH(); if (call_user_function_ex(EG(function_table), NULL, function_name, &retval, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { php_printf("Function call failed!"); return; } *return_value = retval; zval_copy_ctor(return_value); zval_ptr_dtor(&retval); }
zval_copy_ctor()原始(zval)的内容拷贝给它。zval_ptr_dtor()释放空间。return_value不是一个函数外的变量,它的由函数声明里的变量。PHP_FUNCTION(hello_callback)这个声明是简写,最终会被预处理宏替换为:
void zif_hello_callback(zend_execute_data *execute_data, zval *return_value)
return_value变量其实也就是最终返回给调用脚本的,RETURN_STR(s) 等返回函数最终也都是宏替换为对该变量的操作。
测试脚本:
一个并行扩展早期的php不支持多进程多线程的,现在随着发展有很多扩展不断完善它,诸如pthread,swoole等,不仅能多线程,而且能实现异步。
利用c语言多线程pthread库来实现一个简单的并行扩展。
先声明我们一会用到的结构:
struct myarg { zval *fun; zval ret; };线程函数:
static void my_thread(struct myarg *arg) { zval *fun = arg->fun; zval ret = arg->ret; if (call_user_function_ex(EG(function_table), NULL, fun, &ret, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } }函数的实现:
PHP_FUNCTION(hello_thread) { pthread_t tid; zval *fun1, *fun2; zval ret1, ret2; struct myarg arg; int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &fun1, &fun2) == FAILURE) { return; } arg.fun = fun1; arg.ret = ret1; ret = pthread_create(&tid, NULL, (void*)my_thread, (void*)&arg); if(ret != 0) { php_printf("Thread Create Error "); exit(0); } if (call_user_function_ex(EG(function_table), NULL, fun2, &ret2, 0, NULL, 0, NULL TSRMLS_CC) != SUCCESS) { return; } pthread_join(tid, NULL); RETURN_NULL(); }测试脚本:
输出:
两次的输出结果不一样,并且echo "after 多并发";是在两个函数都运行完后才执行的。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22092.html
摘要:但在密集计算方面比等静态编译语言差几十倍甚至上百倍。一使用栈内存在引擎和扩展中,经常要创建一个的变量,底层就是一个指针。代码中创建的变量也进行了优化,直接在栈内存上预分配。应用层与底层在错误抛出的方式全部统一为异常。 原文:http://rango.swoole.com/archives/440最近PHP官方终于发布了传说中的PHP7,虽然只是alpha版。PHP7号称是新一代的PHP...
摘要:目前来看等语言还难以企及和。作为一个资深的开发者,在技术上给各位程序十点未来的建议,希望对大家有所帮助。开发者应当学习掌握规范,在开发程序时应当尽量遵循规范。程序员除了写后台程序之外,还有很大一部分工作在展现层,和浏览器前端打交道。 PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js 、 GO 、 Pytho...
摘要:修复添加超过万个以上定时器时发生崩溃的问题增加模块,下高性能序列化库修复监听端口设置无效的问题等。线程来处理网络事件轮询,读取数据。当的三次握手成功了以后,由这个线程将连接成功的消息告诉进程,再由进程转交给进程。此时进程触发事件。 本文示例代码详见:https://github.com/52fhy/swoo...。 简介 Swoole是一个PHP扩展,提供了PHP语言的异步多线程服务器...
摘要:我们为了处理这些挑战,提出了一个新的引用测试框架当然,也是开源的,并且在整个过程中节省了上百万美元。另一方面,被证实有一些严重的缺点部署困难而且慢。在缓存刷新期间,当可用于别的进程的已缓存的文件字节码在此时损坏,就会导致崩溃。 How Badoo saved one million dollars switching to PHP7 我们成功的把我们的应用迁移到了php7上面(数百台机...
阅读 1598·2021-11-04 16:11
阅读 3309·2021-09-09 11:33
阅读 1558·2019-08-30 15:54
阅读 619·2019-08-30 15:44
阅读 3173·2019-08-30 15:43
阅读 2553·2019-08-30 13:06
阅读 1697·2019-08-29 17:00
阅读 894·2019-08-29 15:33