[李景山php] 深入理解PHP内核[读书笔记]--第二章:用户代码执行--SAPI概述-PHP中的CGI实现

来源:互联网 发布:波谱 常见 数据 编辑:程序博客网 时间:2024/05/16 05:04

PHP中的CGI实现


PHP的CGI实现了Fastcgi协议,是一个TCP或UDP协议的服务器接受来自Web服务器的请求,当启动时创建TCP/UDP协议的服务器的socket监听,并接收相关请求进行处理。随后就进入了PHP的生命周期:模块初始化,sapi初始化,处理PHP请求,模块关闭,sapi关闭等就构成了整个CGI的生命周期。

以TCP为例,在TCP的服务端,一般会执行这样几个操作步骤:
1 调用socket函数创建一个TCP用的流式套接字
2 调用bind函数将服务器的本地地址与前面创建的套接字绑定
3 调用listen函数将创建的套接字作为监听,等待客户端发起的连接,当客户端有多个连接连接到这个套接字时,可能需要排队处理。
4 服务器进程调用accept函数进入阻塞状态,直到有客户进程调用connect函数而建立一个连接
5 当与客户端创建连接后,服务器调用read_stream函数读取客户的请求
6 处理完数据后,服务器调用write函数向客户端发送应答

如下图:
这里写图片描述

PHP的CGI实现从cgi_main.c文件的main函数开始,在main函数中调用了定义在fastcgi.c文件中的初始化,监听等函数。对比TCP流程,我们查看PHP对TCP协议的实现,虽然PHP本身也实现了这些流程,但是在main函数中一些过程被封装成一个函数实现。对应TCP的操作流程,PHP首先会执行创建socket,绑定套接字,创建监听:

if(bindpath){     fcgi_fd = fcgi_listen(bindpath,128);//实现socket监听,调用fcgi_init初始化}

在fastcgi.c文件中,fcgi_listen函数主要用于创建、绑定socket并开始监听,它走完了前面听列TCP流程的前三个阶段,

if((listen_socket = socket(sa.sa.sa_family,SOCK_STREAM))<0 || bind(listen_socket,(struct sockaddr *) &sa,sock_len) <0 || listen(listen_socket,backlog)<0){}

当服务端初始化完成后,进程调用accept函数进入阻塞状态,在main函数中我们看到如下代码:

while(parent){     do{          pid = fork();//生成新的子进程          switch(pid){               parent = 0;               // don't catch our signals               sigaction(SIGTERM,&old_term,0);//终止信号,          }     }while(parent && (runing < children));}
0 0