Press "Enter" to skip to content

保证PHP扩展的依赖关系

cyj网友提到, 如果俩个PHP扩展模块之间有互相依赖关系, 那么该如何保证正确的加载顺序呢?
也就是说, 如何保证模块的依赖关系?
关于这个问题, 可以从如下俩点入手展开:
1. 扩展的加载顺序是和它出现在配置文件中的先后顺序相关的, 也就是说, 如果在配置文件中的顺序如下,

extension=mysql.so
extension=pdo.so
    

那么, mysql扩展就会比pdo扩展先载入.
同理,对于单独的配置文件,则和这个文件的载入顺序相关. 一般来说,这个时候和这个文件的命名相关.
2. 那么如果顺序出错, 我们又要怎么保证正确的加载, 或者告诉Zend此时出错了呢?
回忆, 我们在写扩展的时候, 都会申明一个zend_module_entry结构的扩展说明模块, 这个结构用来告诉Zend所有和当前模块相关的, Zend关心的信息, 也就是在这里, 我们可以申明我们的模块所依赖的模块, 这样当依赖关系出错的时候Zend就会报错, 给出详细的出错信息, 并停止运行.

struct _zend_module_entry {
    unsigned short size;
    unsigned int zend_api;
    unsigned char zend_debug;
    unsigned char zts;
    struct _zend_ini_entry *ini_entry;
    struct _zend_module_dep *deps;  //关键属性
    char *name;
    struct _zend_function_entry *functions;
    int (*module_startup_func)(INIT_FUNC_ARGS);
    int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
    int (*request_startup_func)(INIT_FUNC_ARGS);
    int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
    void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
    char *version;
    size_t globals_size;
#ifdef ZTS
    ts_rsrc_id* globals_id_ptr;
#else
    void* globals_ptr;
#endif
    void (*globals_ctor)(void *global TSRMLS_DC);
    void (*globals_dtor)(void *global TSRMLS_DC);
    int (*post_deactivate_func)(void);
    int module_started;
    unsigned char type;
    void *handle;
    int module_number;
};
   

第5个属性, zend_module_dep是一个接受zend_module_dep结构数组的指针, 用来指出当前模块所以来的所有模块, 而zend_module_dep的结构如下:

struct _zend_module_dep {
    char *name;         /* module name */
    char *rel;          /* version relationship: NULL (exists), lt|le|eq|ge|gt (to given version) */
    char *version;      /* version */
    unsigned char type; /* dependency type */
};
  

但, 很PHP特色的, 我们不需要知道详细的这个结构细节, 也不需要去和这个结构直接接触, 我们可以使用PHP提供的宏:GET_MOD_REQUIRE来完成zend_module_dep的填写, 比如在pdo_mysql中:

static zend_module_dep pdo_mysql_deps[] = {
    ZEND_MOD_REQUIRED("pdo")
    {NULL, NULL, NULL}
};
  

申明了, pdo_mysql必须依赖于pdo扩展模块.
然后,把这个数组指针填入pdo_mysql_module_entry中相应字段即可完成我们的目标~

22 Comments

  1. […] 列出PHP扩展,更方便的往某个点进行深入和掌握。关于PHP扩展加载顺序问题参考,保证PHP扩展的依赖关系。 […]

  2. bettingon.football
    bettingon.football September 8, 2016

    In stark distinction to thee initial 1990’s version, played on a Nintendo Gameboy
    machine, this augmented-reality recreation for cellphones forces its
    consumers to explore the earth around them too capture thhe 150 Pokemon currently accessible, fight towartds other people,
    and obtain merchandise to electric power uup their arsenals oof pocket monsters.

  3. 0xFF_
    0xFF_ September 25, 2013

    经试验,确实和ini中的顺序相关,但却不一定,我使用这个配置顺序
    1440 extension=”apc.so”

    1457 extension=”session.so”
    并加了日志,但是得到:
    Notice: PHP Startup: session MINIT in Unknown on line 0
    Notice: PHP Startup: apc MINIT in Unknown on line 0

  4. gaodi07
    gaodi07 February 5, 2013

    楼主好高深,以后会经常来打扰了

  5. Wraith
    Wraith May 19, 2011

    不知是否对PDO和mysqli的性能和开销对比有兴趣?

  6. laruence
    laruence November 25, 2010

    @进口泵 你这相关性也太差了,,,发到这里,,不会有任何广告效益的..

  7. 进口泵
    进口泵 November 25, 2010

    PS3 power cord Cyber Monday deals 2010 Best Buy Target & More ,power cord the next generation of gaming with Nyko’s Power Cord for PlayStation 3. The power cord fits into any standard wall outlet and works great as a;江苏大学海水淡化装置科研成果国际领先,乳化机国产高压泵样机一次开机成功,进口阀门现场有一台国外进口泵也同时运行,经检测,在相同频率运行时,国产泵流量、均质器压力均高于进口泵,电机电流值低于进口泵,效率约为进口泵的1.11倍。进口水泵这意味着一个日产万吨级的反渗透海水淡化装置,进口泵如采用两台国产高压泵运行。

  8. 苏斌
    苏斌 September 14, 2009

    换友情链接吗

  9. cyj
    cyj August 19, 2009

    是不是我提供外部模块使用的时候使用这个PHPAPI前缀的函数,思路满满有点清晰了,我看书理解问题不细心,看了这么多资料总是浮在表面,十分感谢您能抽出时间回答问题呢,赞汝之名!
    以后有问题还请多多指教。

  10. 雪候鸟
    雪候鸟 August 19, 2009

    @cyj 没区别, 俩者都是定义符号导出的宏. YOUEXT_API更其实是”你自己”定义的宏. 在不同的平台展开的结果不同而已, php5.3以前在*unix下展开都为空, 在php5.3之后, 对于GCC4.x 会展开成__attribute__(visibility(“default”)), 如果你们不是Windows平台, 可以忽略这个.

  11. cyj
    cyj August 19, 2009

    我又来了。。。我想问下PHPAPI与PHP_MODULE_API的区别呢,在网上寻找时候找到这段
    Use PHPAPI / YOREXT_API
    If you plan to use the functions in other extensions

  12. cyj
    cyj August 19, 2009

    确实这个问题问的我都不好意思了。。太依赖别人了,不过一个动态链接库被外部引用又牵扯到线程安全让人头疼呢,研究一下,有问题了找你~

  13. 雪候鸟
    雪候鸟 August 19, 2009

    呵呵,这个我想你可以通过google找到答案~ 😉

  14. cyj
    cyj August 19, 2009

    这个没有测试,但确实是在worker模式下进行。我觉得很有可能是多进程导致的问题,php中没有基于JSP中scope=application这样的呢。
    再次回到测试问题,我写了两个模块,一个模块引入另外一个模块的全局变量,通过引入另外一个模块的php_module.h文件,但是编译时显示找不到另外一个模块的全局变量呢.对C语言依赖关系不熟。。。

  15. 雪候鸟
    雪候鸟 August 19, 2009

    @cyj, apache的worker模式是么? 俩次的访问是同一个进程在处理么?

  16. cyj
    cyj August 19, 2009

    你好,又来打扰了。我声明了一个模块全局变量,在mini函数里面初始化0,在rini里面进行++操作,在同一浏览器下能自增,但是换浏览器或者换机器又从0开始读取了,难道每次换浏览器模块里面都shutdown一下次?

  17. cyj
    cyj August 19, 2009

    确实,但是TM说如果多个模块读取配置文件,这部分代码应该独立出来。。。

  18. 雪候鸟
    雪候鸟 August 19, 2009

    @cyj, 我觉得,每个模块自己的配置文件, 应该会更好一些.

  19. cyj
    cyj August 19, 2009

    因为一些需要,我们的模块需要自己的配置文件,但这些配置文件根据目录的不同而不同,所以我设想通过一个模块读取配置文件,将这些信息存入哈希表,然后通过其他模块与它交互获取配置信息,不知道这个思路有没有什么问题啊。
    ps:php5.3后可以通过.user.ini配置本目录文件了,但是只支持cgi/fastcgi模式,而且我们的服务器使用的是apache2 worker模式

  20. 雪候鸟
    雪候鸟 August 19, 2009

    @cyj, 能帮到你就好, 🙂

  21. cyj
    cyj August 19, 2009

    十分感谢~这部分经过您的指教已经基本理解了,如果以后有问题的话,请不吝赐教~

Comments are closed.