# PHP运行模式及安装方式

> PHP能做什么？
>
> 服务端脚本
>
> 命令行脚本
>
> 编写桌面应用程序

## PHP运行模式

php一共分为五大运行模式：

* cgi (通用网关接口Common Gateway Interface)
* fast-cgi (fast-cgi 是cgi的升级版本)
* cli (Command Line Interface)
* isapi (Internet Server Application Program Interface，是微软提供的一套面向Internet服务的API接口)
* apache2handler (将php作为apache的模块, nginx类似)
* 其他(continuity, embed, litespeed, milter等)

isapi 和 apache2handler 同属于模块模式

### CLI模式

Command Line Interface的简称，即**PHP命令行接口**，在windows和linux下都支持PHP-CLI模式

它可以直接在命令行下运行,那就意味着完全可以不要任何http容器. 例如`php test.php`

**应用场景**

* 定时任务
* 开发桌面应用就是使用PHP-CLI和GTK包
* 开发shell脚本

**优点和缺点**

* 以上应用场景决定了其优点
* 无法为普通用户提供http服务

> CLI专用常量 STDIN、STDOUT、STDERR
>
> 命令行下参数$argc 、 $arg
>
> 本地查看运行模式的方法
>
> ```
> php -r "phpinfo();" |grep "Server API"
> php -r "echo php_sapi_name();"
> phpinfo();
> ```

**示例:**

使用标准stdin 常量输入数据 / stdout输出

```php
//标准输入 stdin
$stdin1 = fopen("php://stdin","r");
echo "please input a number!\r\n";
$num = fgets($stdin1);
echo "ok , $num";

echo "the second type:";
$stdin2 = fgets(STDIN);
var_dump($stdin2);

//标准输出stdout
//第一种方式:
$stdout = fopen('php://stdout', 'w');
fwrite($stdout, "1:php://stdout\r\n");
fclose($stdout);
//第二种方式
fwrite(STDOUT, "2:STDOUT\r\n");
exit;

//标准错误stderr,默认情况会发送到客户端
$stderr = fopen('php://stderr', 'w');
fwrite($stderr, "err1");
fclose($stderr);
fwrite(STDERR, "err2");
```

可执行PHP脚本：phphead 来模拟“head” 命令

```php
error_reporting(E_ERROR);

$filename = $argv[1];
$number = intval($argv[2]);

$data = '';
if(!file_exists($filename)){
    exit($filename." is not exists!");
}

if(!$number){
    $number = 10;
}

$fp = fopen($filename,"r");
$i = 1;
while($i<=$number){
    $data .= fgets($fp);
    $i++;
}
fclose($fp);
echo $data;
```

### CGI模式

CGI即通用网关接口(Common Gateway Interface)，它是一段程序, 通俗的讲CGI就象是一座桥，把网页和WEB服务器中的执行程序连接起来，它把http服务器接收的指令传递给执行程序，再把执行程序的结果返还给http服务器。CGI 的跨平台性能极佳，几乎可以在任何操作系统上实现。

**执行过程**&#x20;

* http服务器接受到用户请求后 ,例如 index.php ,会通过它配置的CGI服务来执行
* 生成一个php-cgi.exe的进程,并执行php程序   &#x20;
* 执行的返回结果交给http服务器   &#x20;

**应用场景**

* 提供http服务

**优点和缺点**

* 跨平台,几乎可以在任何操作系统上实现.
* web和server是独立的,结构清晰,可控性强
* 性能比较差,来一个请求,fork一个进程,100个请求就会fork100进程,消耗资源较多(fork-and-execute 模式)
* 最近几年已经很少见到使用这种模式了

### FastCGI模式

快速通用网关接口（Fast Common Gateway Interface／FastCGI）是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口（CGI）的增强版本。FastCGI致力于减少Web服务器与CGI程序之间互动的开销，从而使服务器可以同时处理更多的网页请求。。

**执行过程**&#x20;

* web服务器启动时 ,载入FastCGI进程管理器
* FastCGI进程管理器会启动多个CGI进程等待web服务器的链接.
* 当客户端请求到达Web Server时，FastCGI进程管理器选择并连接到一个CGI解释器。Web server将环境变量和标准输入发送到FastCGI子进程php-cgi
* FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时，请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中，php-cgi在此便退出了。

**应用场景**

* 提供http服务

**优点和缺点**

* 跨平台,几乎可以在任何操作系统上实现.
* web和server是独立的,结构清晰,可控性强,并不需要web升级而变化
* 支持大并发
* 多进程,消耗较多内存

### 模块模式

模块模式指将php作为web服务器的一个模块运行

主要说说 **iis 的 isapi** 和**apache的apache2handler**

**apache的apache2handler执行过程**

* apache监听到一个用户请求index.php
* apache根据conf文件中配置的LoadModule php\_module modules/mod\_php5.so(windows下面是php5apache2\_2.dll)调用PHP
* 在mod\_php5.so(php5apache2\_2.dll)注册一个php的钩子 php\_ap2\_register\_hook

> 这个php\_ap2\_register\_hook钩子函数中包括4个挂钩以及对应的函数ap\_hook\_pre\_config, ap\_hook\_post\_config ap\_hook\_handler,ap\_hook\_child\_init。其中pre\_config,post\_config,child\_init是启动挂钩，它们在服务器启动时调用。 handler挂钩是请求挂钩，它在服务器处理请求时调用。其中在post\_config挂钩中启动php。

* php执行完成数据通过.so或dll返回给apache
* apache将数据返回到客户端

**应用场景**

* 提供http服务

**优点和缺点**

* 安装配置方便，不需要安装代码解析程序
* 支持多线程，占用资源少
* 支持大并发

> Thread Safe 和 Non Thread Safe (线程安全与线程非安全)
>
> Thread Safe是线程安全，执行时会进行线程（Thread）安全检查，以防止有新要求就启动新线程的执行方式而耗尽系统资源。Non Thread Safe是非线程安全，在执行时不进行线程（Thread）安全检查。
>
> 由于ISAPI 是线程执行,所以选择下载php版本的时候需要选择Thread Safe版本的 . 其他的选择NTS版本的就行了

### PHP主要的安装方式

* Linux下  Apache + PHP
* Linux下  Nginx + PHP
* Windows下  IIS + PHP
* Windows下  Apahe + PHP
* Windows下  Nginx + PHP
