SAPI,是 Server Application Programming Interface 的首字母缩写,意思是服务器端应用编程接口。

这是 PHP 内核提供给外部调用其服务的接口,即外部系统可以通过 SAPI 来调用 PHP 提供的编译脚本、执行脚本的服务。

PHP中常用的SAPI有cli、php-fpm,cli是命令行下执行PHP脚本的实现:bin/php script.php,它是单进程的,处理模型比较简单,而php-fpm相对比较复杂,它实现了网络处理模块,用于与web服务器交互。

从下图可以较为清晰的理解外部系统是如何通过 SAPI 调用 PHP 服务的

Zend引擎

Zend是PHP语言实现的最为重要的部分,是PHP最基础、最核心的部分,它的源码在/Zend目录下,PHP代码从编译到执行都是由Zend完成的,后面章节绝大部分的源码分析都是针对Zend的。Zend整体由两个部分组成:

  • 编译器: 负责将PHP代码编译为抽象语法树,然后进一步编译为可执行的opcodes,这个过程相当于GCC的工作,编译器是一个语言实现的基础
  • 执行器: 负责执行编译器输出的opcodes,也就是执行PHP脚本中编写的代码逻辑

 

接下来主要是讨论下我们常见的 Cli、和 Fpm 是如何工作的。

Cli

Cli(Command Line Interface),即命令行接口,用于在命令行下执行 PHP 脚本,就像 Shell 那样,它是执行 PHP 脚本最简便的一种方式。

Cli 是单进程模式,处理完请求后就直接关闭了,生命周期先后经历 module startuprequest startupexecute scriptrequest shutdownmodule shutdown,其执行流程比较简单,关键的处理过程如下:

main()-> php_cli_startup()-> do_cli()-> php_module_shutdown()
Fpm

Fpm(FastCGI Process Manager)是 PHP FastCGI 运行模式的一个进程管理器,从它的定义可以看出,Fpm的核心功能是进程管理。

FastCGI 是 Web 服务器(如Nginx、Apache)和处理程序之间的一种通信协议,它是与HTTP类似的一种应用层通信协议。
注意:它只是一种协议!

Fpm 是一种多进程模型,它由一个 master 进程和多个 worker 进程组成。master 进程启动时会创建一个 socket,但是不会接收、处理请求,而是由 fork 出的 worker 子进程完成请求的接收及处理。即 master 进程管理 worker 进程,而 worker 进程才是真正的处理请求。

Fpm 在启动后首先会进行 SAPI 的注册操作;接着会进入 PHP 生命周期的 module startup 阶段,在这个阶段会调用各个扩展定义的 MINT 钩子函数。然后会进行一系列的初始化操作,最后 master、worker 进程进入不同的处理环节。

worder 进程的生命周期如下图:


其生命周期主要经历这几个阶段:等待请求、解析请求、请求初始化、执行 PHP 脚本、关闭请求。

master 进程主要通过三种不同的方式来管理 worder 进程,分别是静态模式(static)、动态模式(dynamic)、按需模式(ondemand)。具体要使用哪种模式可以在conf配置中通过pm指定。

  • static: 这种方式比较简单,在启动时master按照pm.max_children配置fork出相应数量的worker进程,即worker进程数是固定不变的
  • dynamic: 动态进程管理,首先在fpm启动时按照pm.start_servers初始化一定数量的worker,运行期间如果master发现空闲worker数低于pm.min_spare_servers配置数(表示请求比较多,worker处理不过来了)则会fork worker进程,但总的worker数不能超过pm.max_children,如果master发现空闲worker数超过了pm.max_spare_servers(表示闲着的worker太多了)则会杀掉一些worker,避免占用过多资源,master通过这4个值来控制worker数
  • ondemand: 这种方式一般很少用,在启动时不分配worker进程,等到有请求了后再通知master进程fork worker进程,总的worker数不超过pm.max_children,处理完成后worker进程不会立即退出,当空闲时间超过pm.process_idle_timeout后再退出

线程安全

在C语言中声明在任何函数之外的变量为全局变量,全局变量为各线程共享,不同的线程引用同一地址空间,如果一个线程修改了全局变量就会影响所有的线程。所以线程安全是指多线程环境下如何安全的获取公共资源。

PHP的SAPI多数是单线程环境,比如cli、fpm、cgi,每个进程只启动一个主线程,这种模式下是不存在线程安全问题的,但是也有多线程的环境,比如Apache,或用户自己嵌入PHP实现的环境,这种情况下就需要考虑线程安全的问题了,因为PHP中有很多全局变量,比如最常见的:EG、CG,如果多个线程共享同一个变量将会冲突,所以PHP为多线程的应用模型提供了一个安全机制:Zend线程安全(Zend Thread Safe, ZTS)。

PHP 的 SAPI 是个什么东西(转)的更多相关文章

  1. 【开发实例】C#调用SAPI实现语音合成的两种方法

    我们都知道现在的语音合成TTS是可以通过微软的SAPI实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种:  1.使用COM组件技术,不管是C++,C#,D ...

  2. cgi ISAP sapi等

    1.CGI和FastCGI是apache处理php脚本的其中两种工作模式,还有ISAPI,SAPI等 2.而php-fpm并不是一种工作模式,而是一个PHP在FastCGI模式运行下的进程管理器,全称 ...

  3. php提供的sapi有哪些?CGI、FastCGI、php-fpm、php-cgi解释

    一.前言 一直对PHP的sapi是什么东西好奇,在网上一查都是各种说fpm cgi fastcgi php-cgi 直到看了鸟哥的这篇文章介绍戳这里,看到源码下的sapi目录才有所了解. 二.sapi ...

  4. C#中调用SAPI实现语音识别的2种方法

    通过微软的SAPI,不仅仅可以实现语音合成TTS,同样可以实现语音识别SR.下面我们就介绍并贴出相关代码.主要有两种方式: 1.使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来 ...

  5. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  6. iOS有关横向TableView的东西

    之前看到Apple store里面有横向的tableview,当然也有可能是collectionview啦. 尤其是项目中只有一条那么需要横向滑动的东西,就没有必要使用庞大的collectionvie ...

  7. 使用ENode框架前您需要了解的东西(初稿)

    选择ENode意味着什么可能很多人还不太清楚.我简单整理了一下: 意味着你选择了:你需要做DDD领域建模.选择了事件驱动的架构.选择了CQRS架构.选择了最终一致性.选择了事件溯源.选择了分布式.这些 ...

  8. 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛

        如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...

  9. Intellij IDEA的一些东西

    Intellij IDEA的一些东西 2016-03-19 15:26 Ctrl + R 在当前文件进行文本替换 (必备) Ctrl + N 根据输入的 类名 查找类文件 Ctrl + Ctrl + ...

随机推荐

  1. 在Windows上使用Docker运行.NET COE应用

    在Windows上使用Docker运行.NET COE应用 执行步骤: 1:安装Docker For Windows(注意:docker for windows-64位Windows 10.必须开启 ...

  2. 指令——mdadm

    Mdadm命令详解 Linux内核中有一个md(multiple devices)模块在底层管理RAID设备,它会在应用层给我们提供一个应用程序的工具mdadm ,mdadm是linux下用于创建和管 ...

  3. uniGUI之通过URL控制参数(25)

    通过URL代入参数,在代码中读取,如: http://localhost:8077/?ServerPort=212&&ServerIP=192.168.31.12 procedure ...

  4. Tensorflow机器学习入门——ModuleNotFoundError: No module named 'tensorflow.keras'

    这个bug的解决办法: # from tensorflow.keras import datasets, layers, models from tensorflow.python.keras imp ...

  5. 机器学习基础系列--先验概率 后验概率 似然函数 最大似然估计(MLE) 最大后验概率(MAE) 以及贝叶斯公式的理解

    目录 机器学习基础 1. 概率和统计 2. 先验概率(由历史求因) 3. 后验概率(知果求因) 4. 似然函数(由因求果) 5. 有趣的野史--贝叶斯和似然之争-最大似然概率(MLE)-最大后验概率( ...

  6. 学习笔记(12)- chatopera的语义理解系统

    参考https://github.com/chatopera/clause-py-demo 前提:安装完毕 Docker.Docker Compose 和 Python3.x git clone ht ...

  7. android.view.WindowManager$BadTokenException 崩掉

    问题: 以前的项目,今天打开运行,Activity刚打开的时候,点开一个弹窗是好的,但是再点到另一个界面的时候,返回,再点弹窗就崩了. 解决: 网上查了一下,发现出现这个问题的还特别多,大体如下: 1 ...

  8. springmvc面试问题

    1.讲下SpringMvc和Struts1,Struts2的比较的优势 性能上Struts1>SpringMvc>Struts2 开发速度上SpringMvc和Struts2差不多,比St ...

  9. <c:foreach>指定循环次数

    <c:forEach begin="0" end="4" var="i"> <c:set var="ans&qu ...

  10. IDEA导入项目后,导入artifacts 方法 以及 Spring的配置文件找不到的解决方法

    我们一般选择 open 项目,如果没有artifacts 的添加选项,我们就要选择 import 项目. 如果没有artifacts ,项目下面会有错误提示,点击错误提示Fix,设置里面导入artif ...