fastcgi Introduction
The CGI full name is the Universal Gateway Interface (Common Gateway Interface), which allows a client to request data from a Web browser to a program that executes on a Web server. CGI describes a standard for transferring data between the client and the program. One purpose of CGI is to be independent of any language, so CGI can be written in any language, as long as the language has standard input, output, and environment variables. such as PHP,PERL,TCL, etc.
FastCGI is like a resident (long-live) CGI, which can be executed all the time, so long as it is activated, it will not take a moment to fork once (this is the most notorious fork-and-execute mode of CGI). It also supports distributed operations where the FastCGI program can execute and accept requests from other Web servers on hosts other than the Web server.
FastCGI is a language-independent, extensible architecture for CGI open extensions whose main behavior is to keep the CGI interpreter process in memory and thus achieve high performance. As we all know, the repeated loading of CGI interpreter is the main reason of poor CGI performance, if the CGI interpreter remains in memory and accepts the FASTCGI process manager scheduling, it can provide good performance, scalability, fail-over characteristics and so on.
In general, this is the whole workflow of fastcgi.
When Web server starts, it loads the FASTCGI process Manager (IIS ISAPI or Apache Module) fastcgi The process manager itself, launches multiple CGI interpreter processes (visible multiple php-cgi), and waits for a connection from the Web server. When a client request arrives at the Web server, the FASTCGI process manager selects and connects to a CGI interpreter. WEB server sends CGI environment variables and standard input to the FASTCGI child process php-cgi. The FASTCGI child process returns standard output and error information from the same connection to the Web Server after processing is complete. When the fastcgi child process closes the connection, the request is processed to completion. The fastcgi child process then waits and processes the next connection from the FASTCGI process Manager (running in Web server). In CGI mode, php-cgi exits here. CGI implementations in PHP
The CGI implementation of PHP is essentially a server that implements a TCP or UDP protocol in socket programming, and when started, creates a socket listener for the TCP/UDP protocol server and receives the relevant request for processing. This is just the processing of the request, which is based on the addition of module initialization, SAPI initialization, module shutdown, SAPI shutdown, etc., which constitute the entire CGI life cycle.
In the case of TCP, for example, on the server side of TCP, the following steps are typically performed:
Call the socket function to create a streaming socket for TCP, call the BIND function to bind the server's local address to the socket created earlier, call the Listen function to listen for the newly created socket, wait for the client-initiated connection, and when the client has multiple connections to the socket, Queue processing may be required, and the server process calls the Accept function to enter a blocking state until a connection is made by the client process, and when the connection is created with the client, the server calls the Read_stream function to read the client's request, and after the data is processed, The server calls the Write function to send an answer to the client.
TCP on the client-server transaction is shown in Timing 2.6:
The CGI implementation of PHP starts with the main function of the Cgi_main.c file, and in the main function calls the initialization, monitoring, and other functions defined in the Fastcgi.c file. In contrast to the TCP process, we look at PHP implementations of the TCP protocol, although PHP itself implements these processes, but some of the processes in the main function are encapsulated as a function implementation. Corresponding to the TCP operation Flow, PHP will first execute create socket, bind socket, create the listener:
if (bindpath) { fcgi_fd = Fcgi_listen (Bindpath, +); implement socket listener, call Fcgi_init initialization ...}
In the Fastcgi.c file, the Fcgi_listen function is primarily used to create, bind, and start listening, which goes through the first three phases of the TCP process listed earlier.
if ((Listen_socket = socket (sa.sa.sa_family, sock_stream, 0)) < 0 | | ... Bind (Listen_socket, (struct sockaddr *) &sa, Sock_len) < 0 | | Listen (Listen_socket, backlog) < 0) { ... }
When the service-side initialization is complete, the process calls the accept function into the blocking state, and in the main function we see the following code:
while (parent) {do {pid = fork (); Generate a new child process switch (PID) {case 0://child process parent = 0; /* don ' t catch our Signals */sigaction (SIGTERM, &old_term, 0); Termination signal sigaction (sigquit, &old_quit, 0); Terminal exit character Sigaction (SIGINT, &old_int, 0); Terminal interrupt break; ... default:/* Fine */running++; Break } while (parent && (Running < children)); ... while (!fastcgi | | fcgi_accept_request (&request) >= 0) {SG (Server_context) = (void *) &reque St Init_request_info (Tsrmls_c); CG (interactive) = 0; ... }
The code above is a build child process and waits for the user to request. In the Fcgi_accept_request function, the program calls the Accept function to block the newly created process. When a user's request arrives, the Fcgi_accept_request function determines whether to process the user's request, which filters some connection requests, ignores requests from the restricted client, and if the program accepts the user's request, it parses the requested information and writes the relevant variable to the corresponding variable. The Safe_read method is called when the content of the request is read. as follows: [Main () Fcgi_accept_request (), Fcgi_read_request (), Safe_read ()]
Static inline ssize_t safe_read (fcgi_request *req, const void *buf, size_t count) { size_t n = 0; Do { ...// omit handling of Win32 RET = Read (REQ->FD, ((char*) buf) +n, count-n); Non-win version read operation ... // omit } while (n! = count);}
As on the corresponding server side read the user's request data.
After the request initialization is complete and the read request is completed, the requested PHP file is processed. Assuming this request is php_mode_standard, the Php_execute_script execution php file is called. In this function it initializes some of the contents of this file, then calls the Zend_execute_scripts function, performs lexical parsing and parsing of the PHP file, generates intermediate code, and executes the Zend_execute function to execute the intermediate code. For the execution of the entire script, see section III, script execution.
After processing the user's request, the server side will return information to the client, at this time in the main function is called Fcgi_finish_request (&request, 1); The Fcgi_finish_request function is defined in the Fastcgi.c file with the following code:
int Fcgi_finish_request (fcgi_request *req, int force_close) {int ret = 1;if (req->fd >= 0) { if (!req->closed) { ret = Fcgi_flush (req, 1); req->closed = 1; } Fcgi_close (req, force_close, 1);} return ret;}
As above, when the socket is open and the request is not closed, the results will be brushed to the client and the request shutdown set to True. The program that brushes the data to the client calls the Fcgi_flush function. In this function, the key is to agree to the construction and write operation of the head. The write operation of the program is called the Safe_write function, while the Safe_write function for the final write operation for the win and Linux environment to make a distinction, under WIN32, if the TCP connection is the Send function, If non-TCP, the Write function is used like a non-win environment. The following code:
#ifdef _win32if (!req->tcp) { ret = write (REQ->FD, ((char*) buf) +n, count-n);} else { ret = send (REQ->FD, ((char*) buf) +n, count-n, 0); if (ret <= 0) { errno = WSAGetLastError (); }} #elseret = Write (REQ->FD, ((char*) buf) +n, count-n); #endif
After sending the requested answer, the server side will perform the shutdown operation, which is limited to the CGI itself, and the program executes the Fcgi_close function. The Fcgi_close function, in the Fcgi_finish_request function mentioned earlier, executes after the request has been answered. Similarly, the win platform and the non-win platform have different processing. Where the write function is called for non-win platforms.
The above is a simple description of a TCP server-side implementation. This is only the basis of our PHP CGI model, on this basis PHP added more features. In the previous chapters we mentioned that each SAPI has a sapi_module_struct structure that belongs to them: Cgi_sapi_module, whose code is defined as follows:
/* {{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 */s Api_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 mes Sage */null, /* Get Request time */null,/* Child terminate */standard_sapi_module_properties} ;/* }}} */
Similarly, in the case of reading cookies, when we invoke the read cookie in PHP in a CGI environment, the final location of the data obtained is when the SAPI is activated. The method that it calls is read_cookies.
SG (request_info). Cookie_data = Sapi_module.read_cookies (Tsrmls_c);
For each server at the time of loading, we have specified Sapi_module, in the first section of the Apache module mode, Sapi_module is Apache2_sapi_module, the corresponding Read_cookies method is Php_apache _sapi_read_cookies function, and in our case, the function of reading a cookie is sapi_cgi_read_cookies. Explain again the reason for defining the SAPI structure: Unified interface, interface-oriented programming, with better extensibility and adaptability.
Reference HTTP://WWW.FASTCGI.COM/DRUPAL/NODE/2 http://baike.baidu.com/view/641394.htm
This is the revised version of the third section of the second chapter of the Tipi project, although there are still some problems, but there are some improvements compared to the previous version, at least we are trying ...
This article address: PHP CGI implementation article source: PHP source reading, PHP design mode, PHP learning notes, project management-Chubby space
Reprint please indicate the original source and the author in the form of a link, decline do not respect copyright copy!