"PHP Kernel Learning" in-depth understanding of fastcgi

Source: Internet
Author: User
Tags php source code sapi

This article GitHub address: Https://github.com/wusuopubupt/phpLib/blob/master/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3FastCGI


|=-----------------------------------------------------------------------=|| =------------------------=[In-depth understanding fastcgi]=--------------------------=| | =-----------------------------------------------------------------------=|| =--------------------------=[by D4shman]=---------------------------=| | =-----------------------------------------------------------------------=|| =-------------------------=[May 7,]=---------------------------=| | =-----------------------------------------------------------------------=|
Directory
0x01 What is fastcgi0x02 fastcgi workflow 0x03 CGI implementation in PHP PHP-FMP and fastcgi0x05 references
0x01 What is fastcgi
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 executing on a Web server. CGI describes a standard for passing data between the client and the program.
FastCGI is a protocol for communication between Web servers and handlers, an improvement to CGI, fastcgi like a resident (long live) CGI, which can be executed all the time, When a request arrives, it does not take time to fork a process to process it (this is the most notorious fork-and-execute mode of CGI).
CGI program loading is the main reason for the poor CGI performance, fastcgi the CGI interpreter process in memory to achieve higher performance. At the same time, FASTCGI supports distributed computing, which means that Web server and fastcgi can be deployed on different servers.
0x02 fastcgi Workflow
1.Web server starts loading the FASTCGI process Manager (Apache Module, IIS ISAPI, PHP-FPM, etc.) the 2.FastCGI process Manager itself initializes, initiates multiple CGI interpreter processes php-cgi and waits from the Web S    The erver connection.      3. When the client's request arrives at the Web server, FastCGI selects and connects to a CGI interpreter.    WEB server sends CGI environment variables and standard input to the FASTCGI child process php-cgi.      After the 4.FastCGI child process finishes processing, the standard output and error information is returned from the same connection to the Web Server. php-cgi Close this connection and wait for the next connection.
0x03 CGI implementations in PHP
The CGI in PHP implements the FASTCGI protocol, which is a TCP or UDP server that accepts requests from a Web server, creates a server socket listener for the TCP/UDP protocol at startup, and accepts requests for processing. It then enters the PHP life cycle: module initialization, SAPI initialization, handling of PHP requests, module shutdown, SAPI shutdown. The above constitutes the life cycle of CGI in PHP.
In TCP, for example, on the server side of TCP, this is typically done in a few steps: 1. Call the socket function to create a streaming socket for TCP 2. Call the BIND function to bind the local address of the servers to the socket created earlier 3. Call the Listen function to listen for newly created sets The connection request initiated by the client is 4. The server process calls the Accept function to enter the blocking state, knowing that there is a client process calling the Connect function to establish a connection 5. When the connection is established, the server calls the Read_stream function to read the client's request 6. After processing the data , the server calls the Write function to send an answer <!--------------to the client this is the living socket communication AH---------------> The following from the PHP source code to see this process: (The following codes I only keep The key part, the complete code please check the PHP source yourself)
1.socket creation, binding and monitoring (in the sapi/cgi/fastcgi.c of the source code)
/* Create, bind socket and start listen on it */if ((Listen_socket = socket (sa.sa.sa_family, sock_stream, 0)) < 0 |    |     #ifdef so_reuseaddr setsockopt (Listen_socket, Sol_socket, SO_REUSEADDR, (char*) &reuse, sizeof (reuse)) < 0 | |        #endif bind (Listen_socket, (struct sockaddr *) &sa, Sock_len) < 0 | | Listen (Listen_socket, backlog) < 0) {fprintf (stderr, "cannot bind/listen socket-[%d]%s.\n", errno, Strerr        or (errno));    return-1; }
2. 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 (); Fork out new sub-process             switch (PID) {             case 0:                  parent = 0;                     /* don ' t catch our signals */                 sigaction (SIGTERM, &old_term, 0); Stop Signal                  Sigaction (sigquit, &old_quit, 0); Terminal Exit character                  Sigaction (SIGINT, &old_int, 0); Terminal break character                 break;                 ...                 default:                 /* Fine */                 running++;                 break;         } while (Parent && (running < children);     /* Call Fcgi_accept_ Request accepts requests */        while (!fastcgi | | fcgi_accept_request (&request) >= 0) {&NBSP;&NBSP;&NBSP;&NBSP;SG (Server_context) = (void *) &requesT;    init_request_info (Tsrmls_c); &NBSP;&NBSP;&NBSP;&NBSP;CG (interactive) = 0;         }    }
3. Call the Read function to read the client request:
    static int fcgi_read_request (fcgi_request *req)     {         fcgi_header Hdr;        int Len, padding;        unsigned Char buf[fcgi_max_length+8];                 req->keep = 0;         req->closed = 0;        req-> In_len = 0;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;REQ-&GT;OUT_HDR = null;         req->out_pos = Req->out_buf;        req->has_ env = 1;        /* Call Sage_read read fcgi_request type of data req*/         if (Safe_read (req, &AMP;HDR, sizeof (fcgi_header))! = sizeof (Fcgi_header) | |   &nBsp;         hdr.version < fcgi_version_1) {             return 0;         }    }         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.
4.fastCGI processing Complete
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 (reg->fd >= 0), 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:         static inline ssize_t safe_write (fcgi_request *req, const void * BUF, size_t count)     {        int ret;         size_t n = 0;             do {            errno = 0;          #ifdef _WIN32/*win32 Environment */             if (!REQ-&GT;TCP) {/* Non-TCP connection, calling the Write function */                 ret = Write (REQ-&GT;FD, ((char*) buf) +n, count-n);             } else {/* TCP connection, calling the Send function */                 ret = Send (REQ-&GT;FD, ((char*) buf) +n, count-n, 0);                 if (ret <= 0) {                     errno = WSAGetLastError ();                 }             }         #else/* Other environments, Call the Write function */            ret = Write (REQ-&GT;FD, (char *) buf) +n, count-n);         #endif             if (Ret > 0) {                 n + = ret;             } else if (ret <= 0 && errno! = 0 && errno! = eintr) {       & Nbsp;        return ret;             }        } while (n! = count);         return n;    }
The above is the implementation process of PHP fastcgi based on TCP connection.
The full name of 0x04 PHP-FMP and FastCGI php-fpm is the PHP-FASTCGI process Manager (the FastCGI Progress Manager for PHP). We know that PHP's interpreter is php-cgi. But php-cgi is only a CGI program, itself can only parse the request, return results, not process management, so there are some can dispatch php-cgi process procedures, PHP-FPM was born.
0X05 Reference Documents
In-depth understanding of the PHP kernel, HTTP authoritative guide

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.