【PHP内核学习】SAPI

鸟哥的博客提到了SAPI,我也来看下源码。

-------------

php架构图(图片出自http://stblog.baidu-tech.com/?p=763):

  • 中间层(sapi)解耦隔离了web server和php



每个SAPI实现都是一个_sapi_module_struct 结构体:

在php源码目录下用 grep -r _sapi_module_struct 搜索到它的定义在main/SAPI.h中:

struct _sapi_module_struct {
    char *name;
    char *pretty_name;

    int (*startup)(struct _sapi_module_struct *sapi_module);
    int (*shutdown)(struct _sapi_module_struct *sapi_module);

    int (*activate)(TSRMLS_D);
    int (*deactivate)(TSRMLS_D);

    int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);
    void (*flush)(void *server_context);
    struct stat *(*get_stat)(TSRMLS_D);
    char *(*getenv)(char *name, size_t name_len TSRMLS_DC);

    void (*sapi_error)(int type, const char *error_msg, ...);

    int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
    int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);
    void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC);

    int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC);
    char *(*read_cookies)(TSRMLS_D);

    void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
    void (*log_message)(char *message TSRMLS_DC);
    double (*get_request_time)(TSRMLS_D);
    void (*terminate_process)(TSRMLS_D);

    char *php_ini_path_override;

    void (*block_interruptions)(void);
    void (*unblock_interruptions)(void);

    void (*default_post_reader)(TSRMLS_D);
    void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC);
    char *executable_location;

    int php_ini_ignore;
    int php_ini_ignore_cwd; /* don't look for php.ini in the current directory */

    int (*get_fd)(int *fd TSRMLS_DC);

    int (*force_http_10)(TSRMLS_D);

    int (*get_target_uid)(uid_t * TSRMLS_DC);
    int (*get_target_gid)(gid_t * TSRMLS_DC);
    unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);

    void (*ini_defaults)(HashTable *configuration_hash);
    int phpinfo_as_text;

    char *ini_entries;
    const zend_function_entry *additional_functions;
    unsigned int (*input_filter_init)(TSRMLS_D);
};

下面,以cgi_sapi为例说明sapi的实现:

static sapi_module_struct cgi_sapi_module = {
    "cgi-fcgi",                     /* name */
    "CGI/FastCGI",                  /* pretty name */

    php_cgi_startup,                /* startup 当SAPI初始化时,首先会调用该函数 */
    php_module_shutdown_wrapper,    /* shutdown  关闭函数包装器,它用来释放所有的SAPI的数据结构、内存等*/

    sapi_cgi_activate,              /* activate  此函数会在每个请求开始时调用,它会再次初始化每个请求前的数据结构*/
    sapi_cgi_deactivate,            /* deactivate  此函数会在每个请求结束时调用,它用来确保所有的数据都,以及释放在activate中初始化的数据结构*/

    sapi_cgi_ub_write,              /* unbuffered write  不缓存的写操作(unbuffered write),它是用来将PHP的数据输出给客户端*/
    sapi_cgi_flush,                 /* flush  刷新输出,在CLI模式下通过使用C语言的库函数fflush实现*/
    NULL,                           /* get uid */
    sapi_cgi_getenv,                /* getenv */

    php_error,                      /* error handler */

    NULL,                           /* header handler */
    sapi_cgi_send_headers,          /* send headers handler 发送头部信息*/
    NULL,                           /* send header handler */

    sapi_cgi_read_post,             /* read POST data  当请求的方法是POST时,程序会操作$_POST、$HTTP_RAW_POST_DATA等变量*/
    sapi_cgi_read_cookies,          /* read Cookies  在SAPI激活时,程序会调用此函数,并且将此函数获取的值赋值给SG(request_info).cookie_data*/

    sapi_cgi_register_variables,    /* register server variables */
    sapi_cgi_log_message,           /* Log message */
    NULL,                           /* Get request time */
    NULL,                           /* Child terminate */

    STANDARD_SAPI_MODULE_PROPERTIES
};


通过上面cgi的例子,我们可以看到,整个SAPI类似于一个面向对象中的模板方法模式的应用。SAPI.c和SAPI.h文件所包含的一些函数就是模板方法模式中的抽象模板, 各个服务器对于sapi_module的定义及相关实现则是一个个具体的模板。


参考:

1.http://stblog.baidu-tech.com/?p=763

2.http://www.laruence.com/2008/08/12/180.html

3.http://www.nowamagic.net/librarys/veda/detail/1292




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值