说说php的sapi (cgi fastcgi .etc.)

sapi这是神马?Server Application Programming Interface ,服务器应用编程接口。

sapi是应用层(比如apache,nginx,cli .etc)和php交互数据的入口。

而就是sapi这个入口,使得php和其上面的应用层解耦合了。

sapi实现了和各种应用层的兼容,应用层可以根据自身情况,定制sapi,比如:

1)apache2handler和apache2filter,这是提供给apache mod_php的sapi;

2)cgi,webserver去fork出cgi进程使用的sapi;

3)fastcgi ,webserver采用网络通信或者网络IPC和php交换数据的sapi;

4)cli,命令行方式运行php脚本的sapi。


一:SAPI

webserver的请求或者命令行的请求到了sapi入口,接下来会发生什么事情呢?

每个sapi都会初始化变量、初始化zend引擎,解析配置文件,初始化各种extensions,初始化环境,

每一个sapi实现都对应着一个结构体:_sapi_module_struct,各个sapi此结构体中的各个函数都对应各自实现,以满足应用层和php的完整交互。

这些函数夹杂着php的提供的api,完成了初始化环境变量,引擎,模块,处理输入,zend处理php,处理输出,关闭请求等。

struct _sapi_module_struct {
    char *name;       /* name */
    char *pretty_name; /* pretty name */

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

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

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

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

    int (*header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC);/* header handler */
    int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);/* send headers handler */
    void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC);/* send header handler */

    int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC);/* read POST data */
    char *(*read_cookies)(TSRMLS_D);/* read Cookies */

    void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);/* register server variables *
    void (*log_message)(char *message); /* Log message */
    time_t (*get_request_time)(TSRMLS_D); /* Get request time */

    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 (*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;
};



二:下面详细说道说道上面提到的几个常用sapi

1)apache2handler和apache2filter

      apache 扩展模块mod_php把apache和php联系起来了,apache启动的时候,就会加载mod_php模块,作为apache的一个phase进行。

     这样可见,每个apache进程启动的时候,php的环境已经初始化好,请求来的时候,直接就可以解释执行目标php文件。

     但是这样的话,如果使用了opcode缓存的话,php代码更改了,要重启apache。

     和apache耦合度比较深鸟,一方出现错误会影响另一方。

    性能高

2)cgi,webserver去fork出cgi进程使用的sapi;

     每次来一个动态请求到达web服务器,web服务器就会fork一个cgi进程(外部的c程序,fork之后,调用exec),cgi进程处理完把结果和错误信息返回给webserver,cgi进程就自行退出了,即大家所谓的fork-and-execute 模式。

     这样opcode缓存ok,但是每次都要fork进程,而且还要重新加载php环境,是很大的开销。

    

3)fastcgi ,webserver采用网络通信或者网络IPC和php交换数据的sapi;

      这篇文章所涉及到php信息,都是基于php-5.2.6版本的。在php-5.2.6版本,sapi是直接支持fastcgi的,和cgi是同一个sapi模块。这个sapi模块虽然支持两种模式,但是只能每次只能编译出一种。在php编译时,--enable-fastcgi参数决定了编译出的二进制php采用的是cgi还是fastcg模式,并可以根据 bin/php -v 查看模式类别。

      fastcgi是有个master-workers模式的网络模型。

      master进程按照PHP_FCGI_CHILDREN配置,fork出一定数量的worker进程。

      master进程只进行初始化php环境,创建socket,接收外部信号,管理worker进程。

      worker进程去accept请求,进行处理。每当处理了PHP_FCGI_MAX_REQUESTS个请求后,退出。worker进程退出,master进程会重启一个新worker

      worker进程采用锁避免了accept惊群,但是现在的操作系统已经解决惊群的问题了。

     webserver和php-cgi进程通信,采用的是socket。fastcgi在这里可以通过ip:端口和websever通信,也可以通过网络IPC和webserver通信。

     通过ip和端口启动:bin/php-cgi -b 127.0.0.1:8888。

     如果使用网络IPC的话,必须部署在同一台机器上,因为这是进程通信范畴的。

     如果想支持网络IPC,需要在编译的时候加上参数:--enable-sockets,启动的时候指定socket路径和名称:bin/php-cgi -b /tmp/socket.fastcgi

    

4)cli,命令行方式运行php脚本的sapi。

      摘抄一下源码中的README吧,~_~

    

The CLI (command line interface) SAPI has been introduced
with a goal of making PHP better at supporting the creation of  
stand alone applications.

It is based on CGI SAPI with all CGI specific things removed.

The main differences between the two:

* CLI is started up in quiet mode by default.
  (-q switch kept for compatibility)
* It does not change the working directory to that of the script.
  (-C switch kept for compatibility)
* Plain text error message
* $argc and $argv registered irrespective of register_globals
  and register_argc_argv php.ini settings.
* implicit_flush always on
* -r option which allows execution of PHP code directly from
  the command line (e.g. php -r 'echo md5("test");' )
* Other more sophisticated command line switches (see: man php)
* max_execution_time is set to unlimited, overriding php.ini setting.



the end

   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值