PHP内核-Apache2的SAPI
我们知道定义SAPI之前,首先要定义sapi_module_struct这个结构,相看源码:/soft/php-5.2.9/sapi/apache2handler/sapi_apache2.c,可以看到定义该结构,我直接复制过来:
[cpp]
static sapi_module_struct apache2_sapi_module = {
"apache2handler",
"Apache 2.0 Handler",
php_apache2_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
NULL, /* activate */
NULL, /* deactivate */
php_apache_sapi_ub_write, /* unbuffered write */
php_apache_sapi_flush, /* flush */
php_apache_sapi_get_stat, /* get uid */
php_apache_sapi_getenv, /* getenv */
php_error, /* error handler */
php_apache_sapi_header_handler, /* header handler */
php_apache_sapi_send_headers, /* send headers handler */
NULL, /* send header handler */
php_apache_sapi_read_post, /* read POST data */
php_apache_sapi_read_cookies, /* read Cookies */
php_apache_sapi_register_variables,
php_apache_sapi_log_message, /* Log message */
php_apache_sapi_get_request_time, /* Request Time */
STANDARD_SAPI_MODULE_PROPERTIES
};
1,php_apache2_startup:当通过apache调用PHP时,这个函数会被调用。该函数定义如下,主要是对PHP进行初始化。
[cpp]
static int php_apache2_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
return FAILURE;
}
return SUCCESS;
}
2,php_module_shutdown_wrapper :PHP的关闭函数。
3,PHP会在每个request的时候,处理一些初始化,资源分配的事务。这部分就是activate字段要定义的。
4,与activate的函数,就是deactiveate,它会提供一个handler, 用来处理收尾工作。
5,php_apache_sapi_ub_write:提供一个向Response数据写的接口。
[cpp]
static int
php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
request_rec *r;
php_struct *ctx;
ctx = SG(server_context);
r = ctx->r;
if (ap_rwrite(str, str_length, r)
php_handle_aborted_connection();
}
return str_length; /* we always consume all the data passed to us. */
}
6,php_apache_sapi_flush:提供给zend刷新缓存的句柄。
[cpp]
static void
php_apache_sapi_flush(void *server_context)
{
php_struct *ctx;
request_rec *r;
TSRMLS_FETCH();
ctx = server_context;
/* If we haven't registered a server_context yet,
* then don't bother flushing. */
if (!server_context) {
return;
}
r = ctx->r;
sapi_send_headers(TSRMLS_C);
r->status = SG(sapi_headers).http_response_code;
SG(headers_sent) = 1;
if (ap_rflush(r) connection->aborted) {
php_handle_aborted_connection();
}
}
7,php_apache_sapi_get_stat:这部分用来让Zend可以验证一个要执行脚本文件的state,从而判断文件是否据有执行权限等等。
[cpp]
static struct stat*
php_apache_sapi_get_stat(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
ctx->finfo.st_uid = ctx->r->finfo.user;
ctx->finfo.st_gid = ctx->r->finfo.group;
ctx->finfo.st_dev = ctx->r->finfo.device;
ctx->finfo.st_ino = ctx->r->finfo.inode;
#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
#else
ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
#endif
ctx->finfo.st_size = ctx->r->finfo.size;
ctx->finfo.st_nlink = ctx->r->finfo.nlink;
return &ctx->finfo;
}
8,php_apache_sapi_getenv:为Zend提供了一个根据name来查找环境变量的接口,当我们在脚本中调用getenv的时候,就会间接的调用这个句柄。
[cpp]
static char *
php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const char *env_var;
env_var = apr_table_get(ctx->r->subprocess_env, name);
return (char *) env_var;
}
9,php_error:错误处理函数,直接调用PHP错误处理函数。
10,php_apache_sapi_header_handler:在调用PHP的header()函数时,会调用这个函数。
[cpp]
static int
php_apache_sapi_header_handler(sapi_header_struct *sapi_header,sapi_headers_struct *sapi_headers TSRMLS_DC)
{
php_struct *ctx;
char *val, *ptr;
ctx = SG(server_context);
val = strchr(sapi_header->header, ':');
if (!val) {
sapi_free_header(sapi_header);
return 0;
}
ptr = val;
*val = '\0';
do {
val++;
} while (*val == ' ');
if (!strcasecmp(sapi_header->header, "content-type")) {
if (ctx->content_type) {
efree(ctx->content_type);
}
ctx->content_type = estrdup(val);
} else if (sapi_header->replace) {
apr_table_set(ctx->r->headers_out, sapi_header->header, val);
} else {
apr_table_add(ctx->r->headers_out, sapi_header->header, val);
}
*ptr = ':';
return SAPI_HEADER_ADD;
}
11,php_apache_sapi_send_headers:当要真正发送header的时候,这个函数会被调用。
[cpp]
static int
php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const char *sline = SG(sapi_headers).http_status_line;
ctx->r->status = SG(sapi_headers).http_response_code;
/* httpd requires that r->status_line is set to the first digit of
* the status-code: */
if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
ctx->r->proto_num = 1000 + (sline[7]-'0');
if ((sline[7]-'0') == 0) {
apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
}
}
/* call ap_set_content_type only once, else each time we call it,
configured output filters for that content type will be added */
if (!ctx->content_type) {
ctx->content_type = sapi_get_default_content_type(TSRMLS_C);
}
ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
efree(ctx->content_type);
ctx->content_type = NULL;
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
12,在php_apache_sapi_send_headers指针下面有一个域,用来指明发送每一个单独的header时调用。
13,php_apache_sapi_read_post:表示如何读取POST数据。
[cpp]
static int
php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
{
apr_size_t len, tlen=0;
php_struct *ctx = SG(server_context);
request_rec *r;
apr_bucket_brigade *brigade;
r = ctx->r;
brigade = ctx->brigade;
len = count_bytes;
/*
* This loop is needed because ap_get_brigade() can return us partial data
* which would cause premature termination of request read. Therefor we
* need to make sure that if data is available we fill the buffer completely.
*/
while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
apr_brigade_flatten(brigade, buf, &len);
apr_brigade_cleanup(brigade);
tlen += len;
if (tlen == count_bytes || !len) {
break;
}
buf += len;
len = count_bytes - tlen;
}
return tlen;
}
14,php_apache_sapi_read_cookie:如何读取cookie。
[cpp]
static char *
php_apache_sapi_read_cookies(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
const char *http_cookie;
http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
/* The SAPI interface should use 'const char *' */
return (char *) http_cookie;
}
15,php_apache_sapi_register_variables:提供接口,用于给$_SERVER[]数组提供变量。
[cpp]
static void
php_apache_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
char *key, *val;
int new_val_len;
APR_ARRAY_FOREACH_OPEN(arr, key, val)
if (!val) {
val = "";
}
if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len TSRMLS_CC)) {
php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC);
}
APR_ARRAY_FOREACH_CLOSE()
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len TSRMLS_CC)) {
php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC);
}
}
16,php_apache_sapi_log_message:输出错误信息。
[cpp]
static void php_apache_sapi_log_message(char *msg)
{
php_struct *ctx;
TSRMLS_FETCH();
ctx = SG(server_context);
if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
} else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "%s", msg);
}
}
17,php_apache_sapi_get_request_time:获取请求时间。
[cpp]
static time_t php_apache_sapi_get_request_time(TSRMLS_D) {
php_struct *ctx = SG(server_context);
return apr_time_sec(ctx->r->request_time);
}
这就完成了apache的SAPI定义。之后,就是当用户用URL请求apache服务,这些函数指针就会在适当的时候,发挥作用了(被调用)。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

CakePHP에 로그인하는 것은 매우 쉬운 작업입니다. 한 가지 기능만 사용하면 됩니다. cronjob과 같은 백그라운드 프로세스에 대해 오류, 예외, 사용자 활동, 사용자가 취한 조치를 기록할 수 있습니다. CakePHP에 데이터를 기록하는 것은 쉽습니다. log() 함수는 다음과 같습니다.

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

CakePHP는 오픈 소스 MVC 프레임워크입니다. 이를 통해 애플리케이션 개발, 배포 및 유지 관리가 훨씬 쉬워집니다. CakePHP에는 가장 일반적인 작업의 과부하를 줄이기 위한 여러 라이브러리가 있습니다.
