PHP8의 기본 커널 소스 코드인 SAPI에 대한 심층 분석(1)
이 기사에서는 PHP8의 기본 커널 소스 코드에 대한 심층 분석을 제공하고 SAPI에 대해 알아봅니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
추천 관련 기사: "PHP8 기반 커널 소스 코드 분석 - 배열(1)"
Docker 아래에 다음 환경 구축
[root@a951700e857d cui-php]# php -v PHP 8.0.2 (cli) (built: Mar 2 2021 02:40:03) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.2, Copyright (c) Zend Technologies [root@a951700e857d cui-php]#
Brother Bird 사진 소개
에서 -Zend SAPI(Zend SAPI Internals)에 대한 심층적인 이해
https://link.zhihu.com/?target=https%3A//www.laruence.com/2008/08/12/180.html
SAPI(서버 애플리케이션 프로그래밍 인터페이스, 서버 애플리케이션 프로그래밍 인터페이스)는 PHP 외부 환경의 에이전트와 동일합니다. PHP는 터미널에 적용할 수도 있고 웹 서버에 적용할 수도 있습니다. 터미널에 적용하는 SAPI를 CLI SAPI라고 하고, 웹 서버에 적용하는 SAPI를 CGI SAPI라고 합니다.
이전과 다음을 연결하는 중간 레이어나 글루와 같습니다. sapi의 핵심 정의와 매크로 파일은 Structure_sapi_module_struct
//* sapi_module_struct cgi_sapi_module static sapi_module_struct cgi_sapi_module = { "cgi-fcgi", /* name */ "CGI/FastCGI", /* pretty name */ php_cgi_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ sapi_cgi_activate, /* activate */ sapi_cgi_deactivate, /* deactivate */ sapi_cgi_ub_write, /* unbuffered write */ sapi_cgi_flush, /* flush */ 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 */ sapi_cgi_read_cookies, /* read Cookies */ sapi_cgi_register_variables, /* register server variables */ sapi_cgi_log_message, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ STANDARD_SAPI_MODULE_PROPERTIES };
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)(void); int (*deactivate)(void); size_t (*ub_write)(const char *str, size_t str_length); void (*flush)(void *server_context); zend_stat_t *(*get_stat)(void); char *(*getenv)(const char *name, size_t name_len); void (*sapi_error)(int type, const char *error_msg, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers); int (*send_headers)(sapi_headers_struct *sapi_headers); void (*send_header)(sapi_header_struct *sapi_header, void *server_context); size_t (*read_post)(char *buffer, size_t count_bytes); char *(*read_cookies)(void); void (*register_server_variables)(zval *track_vars_array); void (*log_message)(const char *message, int syslog_type_int); double (*get_request_time)(void); void (*terminate_process)(void); char *php_ini_path_override; void (*default_post_reader)(void); void (*treat_data)(int arg, char *str, zval *destArray); 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); int (*force_http_10)(void); int (*get_target_uid)(uid_t *); int (*get_target_gid)(gid_t *); unsigned int (*input_filter)(int arg, const char *var, char **val, size_t val_len, size_t *new_val_len); void (*ini_defaults)(HashTable *configuration_hash); int phpinfo_as_text; char *ini_entries; const zend_function_entry *additional_functions; unsigned int (*input_filter_init)(void); };
struct _sapi_module_struct {
char *name; // 名字,如cli、 fpm-fcgi等
char *pretty_name; // 更易理解的名字,比如fpm-fcgi对应的为FPM/FastCGI
int (*startup)(struct _sapi_module_struct *sapi_module);
//模块启动时调用的函数
int (*shutdown)(struct _sapi_module_struct *sapi_module);
//模块结束时调用的函数
int (*activate)(void); // 处理request时,激活需要调用的函数指针
int (*deactivate)(void); // 处理完request时,使要调用的函数指针无效
size_t (*ub_write)(const char *str, size_t str_length);
// 这个函数指针用于输出数据
void (*flush)(void *server_context); // 刷新缓存的函数指针
zend_stat_t *(*get_stat)(void); // 判断对执行文件是否有执行权限
char *(*getenv)(char *name, size_t name_len); // 获取环境变量的函数指针
void (*sapi_error)(int type, const char *error_msg, ...)
ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); // 错误处理函数指针
int (*header_handler)(sapi_header_struct *sapi_header,
sapi_header_op_enum op, sapi_headers_struct *sapi_headers);
//调用header()时被调用的函数指针
int (*send_headers)(sapi_headers_struct *sapi_headers);
// 发送全部header的函数指针
void (*send_header)(sapi_header_struct *sapi_header, void *server_context);
// 发送某一个header的函数指针
size_t (*read_post)(char *buffer, size_t count_bytes);
// 获取HTTP POST中数据的函数指针
char *(*read_cookies)(void); // 获取cookie中数据的函数指针
void (*register_server_variables)(zval *track_vars_array);
// 从$_SERVER中获取变量的函数指针
void (*log_message)(char *message, int syslog_type_int);
// 输出错误信息函数指针
double (*get_request_time)(void); // 获取请求时间的函数指针
void (*terminate_process)(void); // 调用exit退出时的函数指针
char *php_ini_path_override; // PHP的ini文件被复写的地址
void (*default_post_reader)(void); //负责解析POST数据的函数指针
void (*treat_data)(int arg, char *str, zval *destArray);
// 对数据进行处理的函数指针
char *executable_location; // 执行的地理位置
int php_ini_ignore; // 是否不使用任何ini配置文件
int php_ini_ignore_cwd; // 忽略当前路径的php.ini
int (*get_fd)(int *fd); // 获取执行文件的fd的函数指针
int (*force_http_10)(void); // 强制使用http 1.0版本的函数指针
int (*get_target_uid)(uid_t *); // 获取执行程序的uid的函数指针
int (*get_target_gid)(gid_t *); // 获取执行程序的gid的函数指针
unsigned int (*input_filter)(int arg, char *var, char **val, size_t val_len,
size_t *new_val_len);
// 对输入进行过滤的函数指针。比如将输入参数填充到自动全局变量$_GET、$_POST、$_COOKIE中
void (*ini_defaults)(HashTable *configuration_hash);
// 默认的ini配置的函数指针,把ini配置信息存在HashTable中
int phpinfo_as_text; // 是否输出phpinfo信息
char *ini_entries; // 执行时附带的ini配置,可以使用php -d设置
const zend_function_entry *additional_functions;
// 每个SAPI模块特有的一些函数注册,比如cli的cli_get_process_title
unsigned int (*input_filter_init)(void);
};
cgi_main.c를 살펴보면 전체 CGI 코드가 총 900줄이 넘습니다.
일부 코드를 접어보세요. ZTS 관련(스레드 안전 등)
zend_signal_startup 신호 처리 방법(Linux 신호에 대해서는 나중에 설명하겠습니다. 피트가 너무 큽니다.)
sapi_startup(&cgi_sapi_module)을 호출하고 초기화 작업을 수행합니다. sapi_model
typedef struct _sapi_globals_struct { void *server_context; sapi_request_info request_info; sapi_headers_struct sapi_headers; int64_t read_post_bytes; unsigned char post_read; unsigned char headers_sent; zend_stat_t global_stat; char *default_mimetype; char *default_charset; HashTable *rfc1867_uploaded_files; zend_long post_max_size; int options; zend_bool sapi_started; double global_request_time; HashTable known_post_content_types; zval callback_func; zend_fcall_info_cache fci_cache; } sapi_globals_struct;

...
sapi_startup(&cgi_sapi_module);
fastcgi = fcgi_is_fastcgi();
cgi_sapi_module.php_ini_path_override = NULL;
SAPI_API void sapi_startup(sapi_module_struct *sf) { sf->ini_entries = NULL // ini_entries设置null sapi_module = *sf; // 把传进来的结构体赋值给sapi_module // 上面有关于sap_module的 定义 sapi_module_struct sapi_module; //这里你可以理解为 初始化了sapi_module_struct #ifdef ZTS ts_allocate_fast_id(&sapi_globals_id, &sapi_globals_offset, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor); # ifdef PHP_WIN32 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); # endif #else sapi_globals_ctor(&sapi_globals); #endif #ifdef PHP_WIN32 tsrm_win32_startup(); #endif reentrancy_startup(); }
memset은 기본입니다. C언어로 메모리 초기화 방법
static void sapi_globals_ctor(sapi_globals_struct *sapi_globals) { memset(sapi_globals, 0, sizeof(*sapi_globals)); zend_hash_init(&sapi_globals->known_post_content_types, 8, NULL, _type_dtor, 1); php_setup_sapi_content_types(); }
下面是 memset() 函数的声明。 void *memset(void *str, int c, size_t n) 参数 str -- 指向要填充的内存块。 c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。 n -- 要被设置为该值的字符数。 返回值 该值返回一个指向存储区 str 的指针。
/* {{{ php_startup_sapi_content_types */ int php_startup_sapi_content_types(void) { sapi_register_default_post_reader(php_default_post_reader); sapi_register_treat_data(php_default_treat_data); sapi_register_input_filter(php_default_input_filter, NULL); return SUCCESS; }
sapi_startup(&cgi_sapi_module); fastcgi = fcgi_is_fastcgi(); cgi_sapi_module.php_ini_path_override = NULL;
그래서 fcgi_init() 함수
int fcgi_is_fastcgi(void) { if (!is_initialized) { return fcgi_init(); } else { return is_fastcgi; } }
로 가서 fgi 프로토콜 관련 내용을 초기화했습니다
글이 너무 길어서 작성하지 못했습니다. 내일 보충하겠습니다. 먼저 gdb로 cli 모드를 분석하겠습니다
이 기사는 원저자 PHP Cui Xuefeng의 승인을 받아 PHP 중국어 웹사이트(원본 주소: https://zhuanlan.zhihu)에 게시되었습니다. .com/p/356037371
추천 학습: "PHP 비디오 튜토리얼
"위 내용은 PHP8의 기본 커널 소스 코드인 SAPI에 대한 심층 분석(1)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 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)

뜨거운 주제











php5와 php8의 차이점은 성능, 언어 구조, 유형 시스템, 오류 처리, 비동기 프로그래밍, 표준 라이브러리 기능 및 보안 측면에서 있습니다. 자세한 소개: 1. 성능 향상 PHP5와 비교하여 PHP8은 JIT 컴파일러를 도입하여 일부 고주파 실행 코드를 컴파일하고 최적화하여 실행 속도를 향상시킵니다. PHP8에는 몇 가지 새로운 언어 구조와 기능이 도입되었습니다. PHP8은 명명된 매개변수를 지원하므로 개발자는 매개변수 순서 대신 매개변수 이름을 전달할 수 있습니다.

php8에 mysql 확장을 추가하는 단계는 다음과 같습니다. 1. MySQL 클라이언트 라이브러리를 설치합니다. 2. PHP 8용 개발 도구를 설치합니다. 3. MySQL 확장 소스 코드를 다운로드합니다. 5. MySQL 확장을 활성화합니다. MySQL 확장; 6. 웹 서버만 다시 시작합니다.

이번 글에서는 apache2.4 설치 방법과 php8.0 설정 방법을 소개하겠습니다. 글에는 사진과 함께 apache2.4+php8.0 설정 방법이 자세히 나와 있습니다.

PHP8은 mysqli와 PDO를 사용하여 데이터베이스에 연결할 수 있습니다. 자세한 소개: 1. 연결할 데이터베이스 서버 이름, 사용자 이름, 비밀번호 및 데이터베이스 이름을 전달하여 mysqli를 사용하여 데이터베이스에 연결합니다. 그런 다음 `connect_error` 속성을 사용하여 연결 성공 여부를 확인하고 연결이 실패하면 오류 메시지를 출력합니다. 마지막으로 `close()` 메소드를 호출하여 연결을 닫습니다. 2. PDO를 사용하여 데이터베이스에 연결하고 데이터베이스 서버 이름, 비밀번호, 데이터베이스 이름 등을 전달하여 연결합니다.

php8 데이터 형식의 방법에는 문자열을 정수로 변환, 정수를 문자열로 변환, 문자열을 부동 소수점 수로 변환, 부동 소수점 수를 문자열로 변환, 배열을 문자열로 변환, 문자열을 배열로 변환, 부울 값을 정수로 변환, 정수를 문자열로 변환 등이 있습니다. 부울 값 및 변수 유형 결정 및 변환. 자세한 소개: 1. 문자열을 정수로 변환하는 작업에는 intval() 함수와 (int) 강제 형식 변환이 포함됩니다. 2. 정수를 문자열로 변환하는 작업에는 strval() 함수와 (문자열) 강제 형식 변환이 포함됩니다. 부동 소수점에 대한 문자열 등등.

이 기사에서는 PHP 8의 JIT를 안내하고 JIT가 해석 프로세스에 참여하는 방법에 대해 설명합니다. 이것이 모든 사람에게 도움이 되기를 바랍니다.

php8의 향상된 성능에는 다음이 포함됩니다. 1. JIT 컴파일러 도입 3. 가비지 수집 메커니즘 개선 5. 새로운 언어 기능 최적화 8. 새로운 메모리 관리 메커니즘을 도입합니다. 9. 코드 생성을 최적화합니다. 자세한 소개: 1. JIT 컴파일러의 도입 PHP8은 보다 효율적인 실행을 위해 PHP 코드를 기계어 코드로 변환할 수 있는 동적 컴파일 기술인 JIT 컴파일러를 도입합니다.

php8의 기능: 1. 명명된 매개변수, 4. 주석, 6. 일치 표현식, 7. 향상된 유형 시스템, 10. 일관성 개선. 자세한 소개: 1. JIT 컴파일러인 PHP8은 PHP 코드를 기본 기계 코드로 컴파일하여 프로그램의 실행 속도를 향상시키는 JIT(Just-In-Time) 컴파일 기술을 도입합니다. 2. 명명된 매개변수, PHP8은 명명된 매개변수를 지원하여 다음을 사용할 수 있습니다. 함수 호출 시 매개변수 이름 등
