php 的fast-cgi 入口在sapi/fpm-main.c裡的main函數,
第一部分還是常規的命令模式,通過php_getopt獲取用戶啟動php-fpm
第二部分cgi_sapi_module.startup(&cgi_sapi_module) ,SAPI啟動,載入PHP擴展,執行每個擴展的PHP_MINIT_FUNCTION。
核心部分fpm_init初始化,包括讀取php-fpm.conf 配置文件。初始化執行過程:
/*Php module 和 sapi shutdown等系列清理操作*/
fpm_php_init_main
/*打開/dev/null,把所有的輸出信息、Warning等往這個黑洞裡扔*/
fpm_stdio_init_main
/*讀取php-fpm.conf 配置文件*/
fpm_conf_init_main
/*讀取unix內核數據,檢查系統rlimit等*/
fpm_unix_init_main
fpm_scoreboard_init_main
fpm_pctl_init_main
fpm_env_init_main
fpm_signals_init_main
fpm_children_init_main
fpm_sockets_init_main
fpm_worker_pool_init_main
fpm_event_init_main
初始化線程池
fcgi_fd = fpm_run(&max_requests);
Fcig 初始化完畢,現在開始進入請求初始化(request init)
fcgi_init_request(&request, fcgi_fd);
request 數據結構
typedef struct _fcgi_request {
int listen_socket;
#ifdef _WIN32
int tcp;
#endif
int fd;
int id;
int keep;
int closed;
int in_len;
int in_pad;
fcgi_header *out_hdr;
unsigned char *out_pos;
unsigned char out_buf[1024*8];
unsigned char reserved[sizeof(fcgi_end_request_rec)];
HashTable *env;
} fcgi_request;
typedef struct _fcgi_header {
unsigned char version; //fast-cgi 版本
unsigned char type;//消息類型
unsigned char requestIdB1;//消息請求唯一標記
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
} fcgi_header;
具體閱讀 http://www.fastcgi.com/drupal/node/6?q=node/22#S4
接下來進入請求等待循環,通過accept創建一個新的鏈接、每個http請求都會執行創建
while (fcgi_accept_request(&request) >= 0) {
fcgi_accept_request :
int fcgi_accept_request(fcgi_request *req)
{
...
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
...
}
把請求消息壓入到SG(server_context)
SG(server_context) = (void *) &request;
SG(server_context) 數據結構
typedef struct _sapi_globals_struct {
void *server_context;
/*
http 請求數據
*/
sapi_request_info request_info;
sapi_headers_struct sapi_headers;
int64_t read_post_bytes;
unsigned char post_read;
unsigned char headers_sent;
struct stat global_stat;
char *default_mimetype;
char *default_charset;
HashTable *rfc1867_uploaded_files;
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;
zend_bool callback_run;
} sapi_globals_struct;
typedef struct {
const char *request_method;
char *query_string;
char *cookie_data;
long content_length;
char *path_translated;
char *request_uri;
/* Do not use request_body directly, but the php://input stream wrapper instead */
struct _php_stream *request_body;
const char *content_type;
zend_bool headers_only;
zend_bool no_headers;
zend_bool headers_read;
sapi_post_entry *post_entry;
char *content_type_dup;
/* for HTTP authentication */
char *auth_user;
char *auth_password;
char *auth_digest;
/* this is necessary for the CGI SAPI module */
char *argv0;
char *current_user;
int current_user_length;
/* this is necessary for CLI module */
int argc;