巅云智能建站平台搭建版(创业流派版)火爆上线,毕生受权!新增:文章智能收罗+全站真静态打包+都会分站+智能小法式+不法词过滤+H5自顺应+智能链词等功效功效概况
建站专提News

谈谈你对Zend SAPIs(Zend SAPI Internals)的懂得

一佰互联网站开辟设想(www.taishanly.com) 宣布日期 2020-04-27 10:44:58 阅读数: 106

SAPI: Server abstraction API,研讨过PHP架构的同窗应当晓得这个东东的主要性,它供给了一个接口,使得PHP能够和其余利用停止交互数据。 本文不会具体先容每个PHP的SAPI,只是针对最简略的CGI SAPI,来申明SAPI的机制。

起首,咱们来看看PHP的架构图:

图1 PHP Architecture

SAPI供给了一个和内部通讯的接口, 对PHP5.2,默许供给了良多种SAPI, 罕见的给apache的mod_php5,CGI,给IIS的ISAPI,另有Shell的CLI,本文就从CGI SAPI动手 ,先容SAPI的机制。 固然CGI简略,可是不必担忧,它包罗了绝大局部内容,足以让你深切懂得SAPI的使命道理。

要界说个SAPI,起首要界说个sapi_module_struct, 检查 PHP-SRC/sapi/cgi/cgi_main.c:

 */static sapi_module_struct cgi_sapi_module = {#if PHP_FASTCGI "cgi-fcgi",      /* name */ "CGI/FastCGI",     /* pretty name */#else "cgi",       /* name */ "CGI",       /* pretty name */#endif  php_cgi_startup,    /* startup */ php_module_shutdown_wrapper, /* shutdown */  NULL,       /* activate */ sapi_cgi_deactivate,   /* deactivate */  sapi_cgibin_ub_write,   /* unbuffered write */ sapi_cgibin_flush,    /* flush */ NULL,       /* get uid */ sapi_cgibin_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 */ sapi_cgi_read_cookies,   /* read Cookies */  sapi_cgi_register_variables, /* register server variables */ sapi_cgi_log_message,   /* Log message */ NULL,       /* Get request time */  STANDARD_SAPI_MODULE_PROPERTIES};

这个布局,包罗了一些常量,比方name, 这个会在咱们挪用php_info()的时辰被利用。一些初始化,扫尾函数,和一些函数指针,用来告知Zend,若何取得,和输入数据。

1. php_cgi_startup, 当一个利用要挪用PHP的时辰,这个函数会被挪用,对CGI来讲,它只是简略的挪用了PHP的初始化函数:

 static int php_cgi_startup(sapi_module_struct *sapi_module){ if (php_module_startup(sapi_module, NULL, 0) == FAILURE) {  return FAILURE; } return SUCCESS;}

2. php_module_shutdown_wrapper , 一个对PHP封闭函数的简略包装。只是简略的挪用php_module_shutdown;

3. PHP会在每个request的时辰,处置一些初始化,资本分派的事件。这局部便是activate字段要界说的,从下面的布局咱们能够看出,对CGI来讲,它并不供给初始化处置句柄。对mod_php来讲,那就差别了,他要在apache的pool中注册资本析构函数, 请求空间, 初始化情况变量,等等等等。

4. sapi_cgi_deactivate, 这个是对应与activate的函数,望文生义,它会供给一个handler, 用来处置扫尾使命,对CGI来讲,他只是简略的革新缓冲区,用以保障用户在Zend封闭前取得一切的输入数据:

 static int sapi_cgi_deactivate(TSRMLS_D){ /* flush only when SAPI was started. The reasons are:  1. SAPI Deactivate is called from two places: module init and request shutdown  2. When the first call occurs and the request is not set up, flush fails on   FastCGI. */ if (SG(sapi_started)) {  sapi_cgibin_flush(SG(server_context)); } return SUCCESS;}

5. sapi_cgibin_ub_write, 这个hanlder告知了Zend,若何输入数据,对mod_php来讲,这个函数供给了一个向response数据写的接口,而对CGI来讲,只是简略的写到stdout:

static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC){#ifdef PHP_WRITE_STDOUT long ret;#else size_t ret;#endif#if PHP_FASTCGI if (fcgi_is_fastcgi()) {  fcgi_request *request = (fcgi_request*) SG(server_context);  long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);  if (ret <= 0) {   return 0;  }  return ret; }#endif#ifdef PHP_WRITE_STDOUT ret = write(STDOUT_FILENO, str, str_length); if (ret <= 0) return 0; return ret;#else ret = fwrite(str, 1, MIN(str_length, 16384), stdout); return ret;#endif}static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC){ const char *ptr = str; uint remaining = str_length; size_t ret; while (remaining > 0) {  ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);  if (!ret) {   php_handle_aborted_connection();   return str_length - remaining;  }  ptr += ret;  remaining -= ret; } return str_length;}

把真实的写的逻辑剥离出来,便是为了简略完成兼容fastcgi的写体例。

6. sapi_cgibin_flush, 这个是供给给zend的革新缓存的函数句柄,对CGI来讲,只是简略的挪用体系供给的fflush;

7.NULL, 这局部用来让Zend能够考证一个要履行剧本文件的state,从而判定文件是否是占有履行权限等等,CGI不供给。

8. sapi_cgibin_getenv, 为Zend供给了一个按照name来查找情况变量的接口,对mod_php5来讲,当咱们在剧本中挪用getenv的时辰,就会间接的挪用这个句柄。而对CGI来讲,由于他的运转机制和CLI很近似,间接挪用父级是Shell, 以是,只是简略的挪用了体系供给的genenv:

static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC){#if PHP_FASTCGI /* when php is started by mod_fastcgi, no regular environment  is provided to PHP. It is always sent to PHP at the start  of a request. So we have to do our own lookup to get env  vars. This could probably be faster somehow. */ if (fcgi_is_fastcgi()) {  fcgi_request *request = (fcgi_request*) SG(server_context);  return fcgi_getenv(request, name, name_len); }#endif /* if cgi, or fastcgi and not found in fcgi env  check the regular environment */ return getenv(name);}

9. php_error, 毛病处置函数, 到这里,说几句题外话,前次看到php maillist 提到的使得PHP的毛病处置机制完整OO化, 也便是,改写这个函数句柄,使得每当有毛病产生的时辰,都throw一个很是。而CGI只是简略的挪用了PHP供给的毛病处置函数。

10. 这个函数会在咱们挪用PHP的header()函数的时辰被挪用,对CGI来讲,不供给。

11. sapi_cgi_send_headers, 这个函数会在要真正发送header的时辰被挪用,普通来讲,便是当有任何的输入要发送之前:

static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC){ char buf[SAPI_CGI_MAX_HEADER_LENGTH]; sapi_header_struct *h; zend_llist_position pos; if (SG(request_info).no_headers == 1) {  return SAPI_HEADER_SENT_SUCCESSFULLY; } if (cgi_nph || SG(sapi_headers).http_response_code != 200) {  int len;  if (rfc2616_headers && SG(sapi_headers).http_status_line) {   len = snprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH,       "%s", SG(sapi_headers).http_status_line);   if (len > SAPI_CGI_MAX_HEADER_LENGTH) {    len = SAPI_CGI_MAX_HEADER_LENGTH;   }  } else {   len = sprintf(buf, "Status: %d", SG(sapi_headers).http_response_code);  }  PHPWRITE_H(buf, len); } h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) {  /* prevent CRLFCRLF */  if (h->header_len) {   PHPWRITE_H(h->header, h->header_len);   PHPWRITE_H("", 2);  }  h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); } PHPWRITE_H("", 2); return SAPI_HEADER_SENT_SUCCESSFULLY; }

 12. NULL, 这个用来零丁发送每个header, CGI不供给

13. sapi_cgi_read_post, 这个句柄指了然若何取得POST的数据,若是做过CGI编程的话,咱们就晓得CGI是从stdin中读取POST DATA的,

static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC){ uint read_bytes=0, tmp_read_bytes;#if PHP_FASTCGI char *pos = buffer;#endif count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes)); while (read_bytes < count_bytes) {#if PHP_FASTCGI  if (fcgi_is_fastcgi()) {   fcgi_request *request = (fcgi_request*) SG(server_context);   tmp_read_bytes = fcgi_read(request, pos, count_bytes - read_bytes);   pos += tmp_read_bytes;  } else {   tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);  }#else  tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);#endif  if (tmp_read_bytes <= 0) {   break;  }  read_bytes += tmp_read_bytes; } return read_bytes;}

14. sapi_cgi_read_cookies, 这个和下面的函数一样,只不过是去取得cookie值:

static char *sapi_cgi_read_cookies(TSRMLS_D){ return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);}

15. sapi_cgi_register_variables, 这个函数给了一个接口,用以给$_SERVER变量中增加变量,对CGI来讲,注册了一个PHP_SELF,如许咱们就能够在剧本中拜候$_SERVER["PHP_SELF"]来取得

本次的request_uri:

static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC){ /* In CGI mode, we consider the environment to be a part of the server  * variables  */ php_import_environment_variables(track_vars_array TSRMLS_CC); /* Build the special-case PHP_SELF variable for the CGI version */ php_register_variable("PHP_SELF", (SG(request_info).request_uri ? SG(request_info).request_uri : ""), track_vars_array TSRMLS_CC);}

16. sapi_cgi_log_message ,用来输入毛病信息,对CGI来讲,只是简略的输入到stderr:

static void sapi_cgi_log_message(char *message){#if PHP_FASTCGI if (fcgi_is_fastcgi() && fcgi_logging) {  fcgi_request *request;  TSRMLS_FETCH();  request = (fcgi_request*) SG(server_context);  if (request) {   int len = strlen(message);   char *buf = malloc(len+2);   memcpy(buf, message, len);   memcpy(buf + len, "", sizeof(""));   fcgi_write(request, FCGI_STDERR, buf, len+1);   free(buf);  } else {   fprintf(stderr, "%s", message);  }  /* ignore return code */ } else#endif /* PHP_FASTCGI */ fprintf(stderr, "%s", message);}

颠末阐发,咱们已领会了一个SAPI是若何完成的了, 阐发过CGI今后,咱们也就能够设想mod_php, embed等SAPI的完成机制。 :)

怎样样,本文先容的是否是很是具体,但愿大师喜好。

一佰互联是天下着名建站品牌办事商,咱们有九年、网站建造、网页设想、php开辟和域名注册及假造主机办事经历,供给的办事更是天下着名。最近几年来还整合团队上风自立开辟了可视化多用户”“3.0平台版,拖拽排版网站建造设想,轻松完成pc站、手机微网站、小法式、APP一体化全网营销网站扶植 ,已胜利的为天下上百家收集公司供给自助建站平台搭建办事。更多资讯:tags标签

相干消息more

10
05月
搜刮引擎优化网站优化之普遍多样化胜利非偶尔

北京网站扶植公司巅云建站:搜刮引擎愈来愈正视用户休会已是个趋向,可是这并不可否定链接和首创内容的主要性。内容是网站建造的魂灵,也是搜刮引擎... >>概况

21
03月
收费建站,自助建站,智能建站,网站扶植轻松!

收费建站,自助建站,智能建站,网站扶植轻松!凡在庆吉科技购假造主机,便可收费取得代价90-290元的建站宝盒软件助你智能建站建网站!无需法式... >>概况

15
05月
你可找到了将来专业网站建造最风行的设想小元素

window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":... >>概况

24
12月
高端企业建完站后的保护有4点须要出格的注重

高端企业建站后保护4点须要出格注重巅云建站   网站扶植好并不是与日俱增,建好网站后也是须要专心保护。高端... >>概况

高端网站扶植

美工统筹SEO,为企业电子商务营销助力!

德律风:

023-85725751
建站

产物

域名注册 假造主机 云办事器 企业邮局
智能建站 APP打包 微站/小法式 创业平台
网站推行 媒体营销 智能收罗 AI机械人
400德律风 短信营销 店销机械人
私家定制 流派网站