目录:
一、如何使用php导入导出csv?
二、php接收POST数据的方式有哪些?
三、如何让json_encode()不转义斜杠?我在作服务器返回一些数据时须要返回一些地址,可是默认的json_code是会对 / 转义成 \/ 的
四、新浪微博、QQ空间、今日头条PC版、蘑菇街、美丽说等网站是如何实现滚屏加载的?即:无刷新动态加载数据技术的应用
五、移动浏览器的判断方法(通用)
六、php中如何优化多个 if...elseif...elseif...else... 语句的状况?
七、php如何检测当前是否是正在使用HTTPS协议?
八、php如何实如今数组$items的任意位置插入数据?
九、如何快速提取URL中的域名?以下 $url='http://bbs.sijiaomao.com/read.php?tid=942&fid=22';如何快速提取 "bbs.sijiaomao.com"
十、若是用foreach来访问PHP的数组, 遍历的顺序是固定的么? 有什么规律可循呢 ?php
十一、php中如何使用file_get_contents()发送post请求?html
十二、如何判断php是线程安全仍是非线程安全的?nginx
1三、php线程安全与非线程安全版本的区别?程序员
1四、Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。web
1五、线程与进程的区别ajax
1六、FastCgi与PHP-fpm之间是个什么样的关系apache
1七、PHP的线程安全模式(Thread Safety)编程
一、如何使用php导入导出csv?json
<?php //读取csv文件中数据:使用php内置函数fgetcsv() function input_csv($handle) { $out = array (); $n = 0; while ($data = fgetcsv($file_handle, 10000)) { $num = count($data); for ($i = 0; $i < $num; $i++) { $out[$n][$i] = $data[$i]; } $n++; } return $out; } //导出数据到csv function export_csv($filename,$data) { header("Content-type:text/csv"); header("Content-Disposition:attachment;filename=".$filename); header('Cache-Control:must-revalidate,post-check=0,pre-check=0'); header('Expires:0'); header('Pragma:public'); echo $data; } ?>
二、php接收POST数据的方式有哪些?windows
一般状况下用户使用浏览器网页表单向服务器post提交数据,咱们使用PHP接收用户POST到服务器的数据,并进行适当的处理。但有些状况下,如用户使用客户端软件向服务端php程序发送post数据,而不能用$_POST来识别,那又该如何处理呢?
①$_POST方式接收数据
$_POST方式是经过 HTTP POST 方法传递的变量组成的数组,是自动全局变量。如使用$_POST['name']就能够接收到网页表单以及网页异步方式post过来的数据,即$_POST只能接收文档类型为Content-Type: application/x-www-form-urlencoded提交的数据。
②$GLOBALS['HTTP_RAW_POST_DATA']方式接收数据
若是用过post过来的数据不是PHP可以识别的文档类型,好比 text/xml 或者 soap 等等,咱们能够用$GLOBALS['HTTP_RAW_POST_DATA']来接收。$HTTP_RAW_POST_DATA 变量包含有原始的POST数据。此变量仅在碰到未识别MIME 类型的数据时产生。$HTTP_RAW_POST_DATA 对于enctype="multipart/form-data" 表单数据不可用。也就是说使用$HTTP_RAW_POST_DATA没法接收网页表单post过来的数据。
③php://input方式接收数据
若是访问原始 POST 数据的更好方法是 php://input。php://input 容许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,而且不须要任何特殊的php.ini设置,而php://input不能用于 enctype="multipart/form-data"。
例如,用户使用某个客户端应用程序post给服务器一个文件,文件的内容咱们无论它,可是咱们要把这个文件完整的保存在服务器上,咱们能够使用以下代码:
$input = file_get_contents('php://input'); file_put_contents($original, $input); //$original为服务器上的文件
以上代码使用file_get_contents('php://input')接收post数据,而后将数据写入$original文件中,其实能够理解为从客户端上传了一个文件到服务器上,此类应用很是多,尤为是咱们PHP开发要与C,C++等应用程序开发进行产品联合开发时会用到,例如本站有文章:拍照上传就是结合flash利用此原理来上传照片的。
如下是一个小示例,演示了$_POST,$GLOBALS['HTTP_RAW_POST_DATA']和php://input三种不一样方式的接收POST数据处理:
a.html
<form name="demo_form" action="post.php" method="post"> <p><label>Name: </label><input type="text" class="input" name="name"></p> <p><label>Address: </label><input type="text" class="input" name="address"></p> <p><input type="submit" name="submit" class="btn" value="Submit"></p> </form>
post.php
header("Content-type:text/html;charset=utf-8"); echo '$_POST接收:<br/>'; print_r($_POST); echo '<hr/>'; echo '$GLOBALS[\'HTTP_RAW_POST_DATA\']接收:<br/>'; print_r($GLOBALS['HTTP_RAW_POST_DATA']); echo '<hr/>'; echo 'php://input接收:<br/>'; $data = file_get_contents('php://input'); print_r(urldecode($data));
输出结果:
$_POST接收:
Array( [name] => xiaoqiang [address] => huilongguan [submit] => Submit)
$GLOBALS['HTTP_RAW_POST_DATA']接收:
php://input接收:
name=xiaoqiang&address=huilongguan&submit=Submit
三、如何让json_encode()不转义斜杠?我在作服务器返回一些数据时须要返回一些地址,可是默认的json_code是会对 / 转义成 \/ 的,因此解决办法有以下两种:
echo str_replace("\\/", "/", json_encode("<font color='red'>www.baidu.com<\/font>")); //第一种方式:正则替换 echo json_encode("<font color='red'>www.baidu.com<\/font>", JSON_UNESCAPED_SLASHES); //第二种方式:php5.4+ echo json_encode("百度", JSON_UNESCAPED_UNICODE); //汉字不转义为\u开头的UNICODE数据,必须PHP5.4+
四、新浪微博、QQ空间、今日头条PC版、蘑菇街、美丽说等网站是如何实现滚屏加载的?即:无刷新动态加载数据技术的应用
//①、首先,咱们要获取浏览器可视区域页面的高度 var winH = $(window).height(); //②、而后,当滚动页面的时候须要作的事情是:计算页面总高度(当滚动底部时,页面新加载数据,因此页面总高度是动态变化的),计算滚动条位置(滚动条位置也是随着加载页面的高度动态变化的),而后构造一个公式,计算相对比例。 $(window).scroll(function () { var pageH = $(document.body).height(); //页面总高度 var scrollT = $(window).scrollTop(); //滚动条top var aa = (pageH-winH-scrollT)/winH;//aa值越小,滚动条越接近底部 理想状态下:页面总高度 = 浏览器可视区域页面高度 + 滚动条正好在底部时的top高度 }); //③、当滚动条接近页底时,触发ajax加载,在本例中咱们使用jQuery的getJSON方法,向服务端result.php发送请求,请求的参数为page,即页数。 if(aa<0.02){ $.getJSON("result.php",{page:i},function(json){ ..... }); } //④、若是请求响应成功返回JSON数据,则解析JSON数据,并将数据追加到页面DIV#container后,若是没有JSON数据返回,则说明数据所有显示完毕。 if(json){ var str = ""; $.each(json,function(index,array){ //遍历 var str = "..."; //获取的JSON数据 $("#container").append(str); //追加 }); i++; //页数+1 }else{ $(".nodata").show().html("别滚动了,已经到底了。。。"); return false; } //完整的代码 $(function(){ var winH = $(window).height(); //页面可视区域高度 var i = 1; //设置当前页数 $(window).scroll(function () { var pageH = $(document.body).height(); var scrollT = $(window).scrollTop(); //滚动条top var aa = (pageH-winH-scrollT)/winH; if(aa<0.02){ $.getJSON("result.php",{page:i},function(json){ if(json){ var str = ""; $.each(json,function(index,array){ var str = "<div class=\"single_item\"><div class=\"element_head\">"; var str += "<div class=\"date\">"+array['date']+"</div>"; var str += "<div class=\"author\">"+array['author']+"</div>"; var str += "</div><div class=\"content\">"+array['content']+"</div></div>"; $("#container").append(str); }); i++; }else{ $(".nodata").show().html("别滚动了,已经到底了。。。"); return false; } }); } }); });
$(window).scroll(function(){ var scrollTop = $(this).scrollTop(); var scrollHeight = $(document).height(); var windowHeight = $(this).height(); if(scrollTop + windowHeight == scrollHeight){ alert("you are in the bottom"); } });
五、移动浏览器的判断方法(通用)
<?php /** * 移动浏览器判断 * * @return bool */ function browse_is_mobile () { return false; $user_agent = $_SERVER['HTTP_USER_AGENT']; if(preg_match("/iPhone/i", $user_agent) || preg_match("/iPod/i", $user_agent) || preg_match("/Android/i", $user_agent)){ return true; } else { return false; } } /** * 检测浏览器类型 * * @return bool|int */ function check_mobile_browse () { $user_agent = $_SERVER['HTTP_USER_AGENT']; if(preg_match("/iPhone/i", $user_agent) || preg_match("/iPod/i", $user_agent)){ return 1; } elseif (preg_match("/Android/i", $user_agent)) { return 2; } else { return false; } } ?>
六、php中如何优化多个 if...elseif...elseif...else... 语句的状况?
<?php //对于不少时候咱们须要用N多个if,elseif,elseif…来达到连续断定完后取出某个值的效果,例如: $data = array(); if("login"==$type){ $data = array("uid"=>1,"pwd"=>123); }elseif("register"==$type){ $data = array("username"=>"max","new_pwd"=>432); }elseif("put_info"==$type){ $data = array("something"=>"Hello"); } //向上面这样的连续判断效率较低,有些人会说改为switch case 的写法,效率会高过if,可是依然是十分的繁琐,以下: $data = array(); switch($type){ case "login": $data = array("uid"=>1,"pwd"=>123); break; case "register": $data = array("username"=>"max","new_pwd"=>432); break; case "put_info": $data = array("something"=>"Hello"); break; } //可是这样写依然会比较麻烦,且运行效率也不会过高,当数据量较大的时候速度会比较慢,如上程序改为以下样式: //优势:在php中数组使用的是hashtable,时间复杂度是O(1),运行速度远远高于以上两种,另外书写起来也更简便的多。即便传入的参数是未定义的,也不会浪费大量的系统资源 $data_arr = array( "login" => array("uid"=>1,"pwd"=>123), "register" => array("username"=>"max","new_pwd"=>432), "put_info" => array("something"=>"Hello") ); if(isset($data_arr[$type])){ $data = $data_arr[$type]; } ?>
七、php如何检测当前是否是正在使用HTTPS协议?
<?php function is_HTTPS(){ if(!isset($_SERVER['HTTPS'])) return FALSE; if($_SERVER['HTTPS'] === 1){ //Apache return TRUE; }elseif($_SERVER['HTTPS'] === 'on'){ //IIS return TRUE; }elseif($_SERVER['SERVER_PORT'] == 443){ //其余 return TRUE; } return FALSE; } ?>
八、php如何实如今数组$items的任意位置插入数据?
<?php $items= ['苹果','橘子','梨','菠萝','香蕉','火龙果'] ; /* $items 传入的数组 $index 要插入的位置 $value 要插入的数据 */ function insertAt($items, $index, $value) { return $items; } $items=insertAt($items, 2 , '橙子'); //执行完成后,结果以下: ['苹果','橘子','橙子','梨','菠萝','香蕉','火龙果'] ; ?>
九、如何快速提取URL中的域名?以下 $url='http://bbs.sijiaomao.com/read.php?tid=942&fid=22';如何快速提取 "bbs.sijiaomao.com"
<?php echo parse_url($url, PHP_URL_HOST); ?>
十、若是用foreach来访问PHP的数组, 遍历的顺序是固定的么? 有什么规律可循呢 ?
<?php //PHP中遍历数组的顺序, 是和元素的添加前后相关的! 因此无论是索引数组仍是关联数组,结果都同样,添加的顺序就是依据! 至于为何会这样,就须要深刻探寻数组的底层实现原理了 $items[2] = 2015; $items[1] = 2014; $items[0] = 2013; foreach ($items as $key => $val) { //结果是什么? echo $key,' => ' ,$val, "\n"; } ?>
十一、php中如何使用file_get_contents()发送post请求?
<?php //咱们知道PHP中的file_get_contents无比强大,不只仅能读取文件内容,还能设置超时时间采集网页数据。那么,可否用file_get_contents来发送post请求呢,若是能,改如何写? $postdata = http_build_query( array( 'username' => '号外', 'password' => '123456' ) ); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); $result = file_get_contents('http://www.baidu.com/server.php', false, $context); ?>
1三、如何判断php是线程安全仍是非线程安全的?
什么是线程安全与非线程安全?
线程安全就是在多线程环境下也不会出现数据不一致,而非线程安全就有可能出现数据不一致的状况。
线程安全因为要确保数据的一致性,因此对资源的读写进行了控制,换句话说增长了系统开销。因此在单线程环境中效率比非线程安全的效率要低些,可是若是线程间数据相关,须要保证读写顺序,用线程安全模式
这个主要是针对web server 而言,在windows环境下,若是你使用的web server 是apchae 或者 iis 7如下版本,则应该选择线程安全的安装文件,而若是你使用Fast-cgi模式时,能够选择非线程安全,由于 web sever 自己能保证线程安全。
固然还有二进制文件编译时所使用的编译器:vc9 (vs系列) vc6(gcc)
如楼上所言,是针对web server的,部分web server在处理应用请求的时候是用多线程而非多进程的方式处理,线程方式由于涉及到共享寄存器和内存,因此很容易出错,这个时候程序就须要花一些额外的经历去处理寄存器中的数据一致性,即保证线程安全。
因此是否采用线程安全主要看你的web server所采用的PHP请求处理方式,若是是多线程处理,那么请选择线程安全的,不然选择非线程安全的,如楼上所说Fast-cgi方式可选择非线程安全的
先从字面意思上理解,None-Thread Safe就是非线程安全,在执行时不进行线程(thread)安全检查;Thread Safe就是线程安全,执行时会进行线程(thread)安全检查,以防止有新要求就启动新线程的 CGI 执行方式耗尽系统资源。
再来看PHP的两种执行方式:ISAPI和FastCGI。FastCGI执行方式是以单一线程来执行操做,因此不须要进行线程的安全检查,除去线程安全检查的防御反而能够提升执行效率,因此,若是是以 FastCGI(不管搭配 IIS 6 或 IIS 7)执行 PHP ,都建议下载、执行 non-thread safe 的 PHP (PHP 的二進位檔有兩種包裝方式:msi 、zip ,請下載 zip 套件)。而线程安全检查正是为ISAPI方式的PHP准备的,由于有许多php模块都不是线程安全的,因此须要使用Thread Safe的PHP。
说到这里,你们应该知道应该如何选择哪一个版本的PHP了。None-Thread Safe or Thread Safe,您会选择哪一个?
Windows下的PHP如今的版本已是5.3.6,如今的Windows版本能够在PHP官方PHP For Windows(http://windows.php.net/download/)下载,下载的时候同版本有VC9 x86 Non Thread Safe、VC9 x86 Thread Safe、VC6 x86 Non Thread Safe、VC6 x86 Thread Safe等四个版本。那么这些版本有什么区别呢?
VC9的版本是用legacy VS 2008编译的,VC6的版本是用legacy VS6编译的。
若是你是在windows下使用IIS+PHP的话,你须要下载VC9的版本。
若是你是在windows下使用Apache+PHP的话,你须要下载VC6的版本。
Non Thread Safe是指非线程安全,Thread Safe则是指线程安全。
若是是使用ISAPI的方式来运行PHP就必须用Thread Safe(线程安全)的版本;而用FastCGI模式运行PHP的话就没有必要用线程安全检查了,用None Thread Safe(NTS,非线程安全)的版本可以更好的提升效率。
如何判断:
经过phpinfo(); 查看其中的 Thread Safety 项,这个项目就是查看是不是线程安全,若是是:enabled,通常来讲应该是ts版,不然是nts版。
1三、php线程安全与非线程安全版本的区别是什么?
Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分,这二者不一样在于何处?到底应该用哪一种?这里作一个简单的介绍
从2000年10月20日发布的第一个Windows版的PHP3.0.17开始的都是线程安全的版本,这是因为与Linux/Unix系统是采用多进程的工做方式不一样的是Windows系统是采用多线程的工做方式。若是在IIS下以CGI方式运行PHP会很是慢,这是因为CGI模式是创建在多进程的基础之上的,而非多线程。
通常咱们会把PHP配置成以ISAPI的方式来运行,ISAPI是多线程的方式,这样就快多了。但存在一个问题,不少经常使用的PHP扩展是以Linux/Unix的多进程思想来开发的,这些扩展在ISAPI的方式运行时就会出错搞垮IIS。所以在IIS下CGI模式才是PHP运行的最安全方式,但CGI模式对于每一个HTTP请求都须要从新加载和卸载整个PHP环境,其消耗是巨大的。
为了兼顾IIS下PHP的效率和安全,微软给出了FastCGI的解决方案。FastCGI可让PHP的进程重复利用而不是每个新的请求就重开一个进程。同时FastCGI也能够容许几个进程同时执行。这样既解决了CGI进程模式消耗太大的问题,又利用上了CGI进程模式不存在线程安全问题的优点。
所以,若是是使用ISAPI的方式来运行PHP就必须用Thread Safe(线程安全)的版本;而用FastCGI模式运行PHP的话就没有必要用线程安全检查了,用None Thread Safe(NTS,非线程安全)的版本可以更好的提升效率。
PHP官方http://php.net/上关于widows的版本有4个:VC9 x86 Non Thread Safe,VC9 x86 Thread Safe,VC6 x86 Non Thread Safe,VC6 x86 Thread Safe;那么有什么区别呢?
1.支持的服务器不一样
VC9版本是针对IIS服务器的版本,没有对APACHE的支持,而VC6版本对IIS和apache都提供了支持
VC6 是什么?VC6 就是 legacy Visual Studio 6 compiler ,就是使用这个编译器编译的。
VC9 是什么?VC9 就是 the Visual Studio 2008 compiler ,就是用微软的 VS 编辑器编译的。
那咱们如何选择下载哪一个版本的 PHP 呢?
若是你是在 windows 下使用 Apache+PHP 的,请选择 VC6 版本;
若是你是在 windows 下使用 IIS+PHP 的,请选择 VC9 版本;
2.运行方式的不一样
PHP有2中运行方式:ISAPI和FastCGI。
ISAPI执行方式是以DLL动态库的形式使用,能够在被用户请求后执行,在处理完一个用户请求后不会立刻消失,因此须要进行线程安全检查,这样来提升程序的执行效率,因此若是是以ISAPI来执行PHP,建议选择Thread Safe版本;
而FastCGI执行方式是以单一线程来执行操做,因此不须要进行线程的安全检查,除去线程安全检查的防御反而能够提升执行效率,因此,若是是以FastCGI来执行PHP,建议选择Non Thread Safe版本。
对于apache服务器来讲通常选择isapi方式,而对于nginx服务器则选择FastCGI方式。
3.总结
PHP所推出的Thread Safe主要针对的是Windows下以IIS来运行PHP的状况,由于Windows中频繁申请进程开销较大,因此在Windows中要以多线程方式来运转PHP,这时候就须要Thread Safe版本。而在Linux系统下,PHP绝大多数状况下都以多进程方式运行,因此直接使用None Thread Safe便可。
若是是使用ISAPI的方式来运行PHP就必须用Thread Safe(线程安全)的版本;而用FastCGI模式运行PHP的话就没有必要用线程安全检查了,用None Thread Safe(NTS,非线程安全)的版本可以更好的提升效率。
若是有多线程,就用线程安全版;若是只有一个线程,就用非线程安全版。
1四、Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式
Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。
今天为在Windows下创建PHP开发环境,在考虑下载何种PHP版本时,遭遇一些让我困惑的状况,为了解决这些困惑,不出意料地牵扯出更多让我困惑的问题。
为了将这些困惑一网打尽,我花了一下午加一夜的时间查阅了大量资料,并作了一番实验后,终于把这些困惑全都搞得清清楚楚了。
说实话,之因此花了这么多时间,很大程度上是因为网上的资料几乎全都是支离破碎、以讹传讹的。既然我已经搞懂了,就花时间整理出来,即方便本身看,也便于你们阅读。相信经过这篇文章,能够解答不少在Windows下搭建PHP开发环境的朋友的困惑。
关于从何处下载Apache:
要安装Apache,你可能想固然地会去Apache官方网站下载适用于Windows的二进制版本。而这偏偏错了!
PHP官方不建议在Windows下安装从apache.org网站下载的Apache二进制安装包。缘由是若是你使用来自apache.org的安装包,则因为这些安装包是基于陈旧的Visual Studio 6编译的,致使你不得没必要须使用一样陈旧的PHP版本(即VC6的PHP版本。也即便用Visual Studio 6编译的PHP版本)才能与其配合使用。
要想使用最新版的PHP,应遵从PHP的官方建议。PHP官方的建议是你在Windows下能够使用IIS,或者使用来自Apache Lounge(www.apachelounge.com)的Apache版本。
Apache Lounge所提供的Apache二进制安装包是使用VC11创建的。所以可搭配最新版本的PHP使用。
网上不少资料说若是你是在Windows下使用 Apache,则必须使用PHP的VC6版本,只有使用IIS时才能使用VC9及以上版本,彻底是没有搞清状况的以讹传讹。
如何选择PHP版本(选择线程安全仍是非线程安全):
在Windows下安装PHP,在选择PHP版本上颇有讲究。
Windows下的PHP版本分两种:线程安全版本与非线程安全版本。
若是你打算使用IIS,则你能够以ISAPI或FastCGI这两种方式来安装PHP。CGI的方式由于效率低下,故不予考虑。
若是你要在IIS中以FastCGI方式使用PHP,则你应该使用PHP的非线程安全的版本(Non-Thread Safe,NTS)。缘由是以FastCGI方式安装PHP时,PHP拥有独立的进程,而且FastCGI是单一线程的,不存在多个线程之间可能引起的相互干扰(这种干扰一般都是因为全局变量和静态变量致使的)。因为省去了线程安全的检查,所以使用FastCGI方式比ISAPI方式的效率更高一些。
若是你要在IIS中以ISAPI的方式使用PHP,则你应该使用PHP的线程安全版本(Thread Safe,TS)。缘由是PHP以ISAPI方式安装时,PHP没有独立的进程,而是做为DLL被IIS加载运行的,便是依附于Web服务器进程的。当Web服务器运行在多线程模式下(IIS正是这种状况),PHP天然也就运行在多线程模式下。只要是在多线程模式下运行,就可能存在线程安全问题,所以应选择PHP的线程安全版本。
但在这里还有必要说明一下,尽管Apache自己是线程安全的,同时你也选择了PHP的线程安全版本,但因为一些Apache和PHP下的第三方扩展最初是基于Unix的多进程思想开发出来的,在设计开发时没有考虑线程安全的问题,所以,不排除在这种状况下仍然存在IIS被某些第三方扩展搞崩溃的可能。
若是你打算使用Apache,则你能够以模块、ISAPI、FastCGI这三种方式来安装PHP。CGI的方式由于效率低下,故不予考虑。
若是你要在Apache中以模块方式安装PHP,则你应该使用PHP的线程安全的版本。缘由是当PHP做为Apache的模块安装时,PHP没有独立的进程,而是做为模块以DLL的形式被加载到Apache中的,是随Apache的启动而启动的,而Windows下的Apache为多线程工做模式,所以PHP天然也就运行在多线程模式下。所以,这种状况下应使用PHP的线程安全版本。
再来看ISAPI的状况。一般认为ISAPI是配合IIS使用的,由于ISAPI最初就是微软为IIS开发的。但Apache如今也能够经过加载mod_isapi.so模块来实现ISAPI的功能,以容许PHP以ISAPI的方式安装。.so文件是Apache自1.3版本后制定的用于Windows下的模块命名规则,对于Windows下的Apache而言,.so与.dll文件同样,都是动态连接库文件。
当要以ISAPI方式来安装PHP时,一般是加载一个名如phpXisapi.dll的DLL文件,其中的X为阿拉伯数字四、5等等这样子。
但通常不建议在Apache中以ISAPI方式来安装PHP,缘由是到目前为止,Apache经过mod_isapi.so模块来实现的ISAPI功能并不完整,并未完整实现微软对ISAPI所制定的所有规范。
一样的,因为以ISAPI方式来安装PHP时,PHP也没有独立的进程,也是做为模块被加载到Apache中的,所以,一样也须要使用PHP的线程安全版本。
若是你要在Apache中以FastCGI方式使用PHP,则同在IIS中使用FastCGI的PHP的状况同样,你应该使用PHP的非线程安全的版本。缘由是在Apache中以FastCGI方式安装PHP时,PHP拥有独立的进程,而且FastCGI是单一线程的,故应使用PHP的非线程安全版本以提升性能。
1五、线程与进程的区别
这么解释问题吧:
1。单进程单线程:一我的在一个桌子上吃菜。
2。单进程多线程:多我的在同一个桌子上一块儿吃菜。
3。多进程单线程:多我的每一个人在本身的桌子上吃菜。
多线程的问题是多我的同时吃一道菜的时候容易发生争抢,例如两我的同时夹一个菜,一我的刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一我的夹一口以后,在还给另一我的夹菜,也就是说资源共享就会发生冲突争抢。
1。对于 Windows 系统来讲,【开桌子】的开销很大,所以 Windows 鼓励你们在一个桌子上吃菜。所以 Windows 多线程学习重点是要大量面对资源争抢与同步方面的问题。
2。对于 Linux 系统来讲,【开桌子】的开销很小,所以 Linux 鼓励你们尽可能每一个人都开本身的桌子吃菜。这带来新的问题是:坐在两张不一样的桌子上,说话不方便。所以,Linux 下的学习重点你们要学习进程间通信的方法。
--
补充:有人对这个开桌子的开销颇有兴趣。我把这个问题推广说开一下。
开桌子的意思是指建立进程。开销这里主要指的是时间开销。
能够作个实验:建立一个进程,在进程中往内存写若干数据,而后读出该数据,而后退出。此过程重复 1000 次,至关于建立/销毁进程 1000 次。在我机器上的测试结果是:
UbuntuLinux:耗时 0.8 秒
Windows7:耗时 79.8 秒
二者开销大约相差一百倍。
这意味着,在 Windows 中,进程建立的开销不容忽视。换句话说就是,Windows 编程中不建议你建立进程,若是你的程序架构须要大量建立进程,那么最好是切换到 Linux 系统。
大量建立进程的典型例子有两个,一个是 gnu autotools 工具链,用于编译不少开源代码的,他们在 Windows 下编译速度会很慢,所以软件开发人员最好是避免使用 Windows。另外一个是服务器,某些服务器框架依靠大量建立进程来干活,甚至是对每一个用户请求就建立一个进程,这些服务器在 Windows 下运行的效率就会不好。这"可能"也是放眼全世界范围,Linux 服务器远远多于 Windows 服务器的缘由。
--
再次补充:若是你是写服务器端应用的,其实在如今的网络服务模型下,开桌子的开销是能够忽略不计的,由于如今通常流行的是按照 CPU 核心数量开进程或者线程,开完以后在数量上一直保持,进程与线程内部使用协程或者异步通讯来处理多个并发链接,于是开进程与开线程的开销能够忽略了。
另一种新的开销被提上日程:核心切换开销。
现代的体系,通常 CPU 会有多个核心,而多个核心能够同时运行多个不一样的线程或者进程。
当每一个 CPU 核心运行一个进程的时候,因为每一个进程的资源都独立,因此 CPU 核心之间切换的时候无需考虑上下文。
当每一个 CPU 核心运行一个线程的时候,因为每一个线程须要共享资源,因此这些资源必须从 CPU 的一个核心被复制到另一个核心,才能继续运算,这占用了额外的开销。换句话说,在 CPU 为多核的状况下,多线程在性能上不如多进程。
于是,当前面向多核的服务器端编程中,须要习惯多进程而非多线程。
--------------------------------------------------------------------------------------------------------
不少人答案说的是操做系统提供的多进程而不是单个程序内的多线程。
多线程使得程序内部能够分出多个线程来作多件事情,而不会形成程序界面卡死。好比迅雷等多线程下载工具就是典型的多线程。一个下载任务进来,迅雷把文件平分红10份,而后开10个线程分别下载。这时主界面是一个单独的线程,并不会由于下载文件而卡死。并且主线程能够控制下属线程,好比某个线程下载缓慢甚至中止,主线程能够把它强行关掉并重启另一个线程。
另外就是一些程序的打印功能,好比记事本、Adobe Reader,打印的时候就只能打印,没法在主界面进行操做,而Word就有“后台打印”的功能,点了打印命令以后,还能够回到主界面进行修改、保存等操做。
另外多线程除了并行完成一些任务之外,还有生产者-消费者模式。好比Windows命令行下在某个硬盘根目录执行一个"dir/s | more"命令,前一条显示硬盘里的全部文件,要执行好久才能执行得完,后面那条命令会把前面命令的输出分屏显示出来。可是执行整条命令时,会马上有显示,也就是说,前面一条命令输出满一页内容到缓冲区,more命令就把缓冲区封死了,等用户敲了一个键显示下一屏的时候,more命令把缓冲区的内容取出并清空,前面的命令才能输出下一屏到缓冲区。这样的多线程使得整条命令不用等待前面的命令所有执行完才能执行下一条命令。
多线程和多进程的区别。日常指的多进程是操做系统下同时运行多个进程,好比Word和Excel同时打开,而且能够并行地同时执行一些操做。这种多进程和多线程没什么比如较的。能够比较的是同一个程序里的多线程和多进程。
多线程由于在同一个进程里,因此能够共享内存和其余资源,好比迅雷里10个线程一齐下载一个文件,这个文件是由进程打开的,而后10个线程均可以往里写入东西。若是是10个进程就不行了,操做系统不容许一个文件由两个进程同时写入。另外,Chrome就是一个典型的多进程程序,里面每一个标签页、扩展、插件都是单独的进程,各自独占资源,相互隔离,一个进程出错死掉只会影响一个页面或者插件,不再会出现Flash插件出错崩溃致使整个浏览器崩溃的状况了。
--------------------------------------------------------------------------------------------------------
多线程最通常的应用是简化程序的写法。好比对于IO工做而言,若是底层的API仅提供了同步操做函数,这样一来,单线程的应用很难写,可是支持多线程后,彻底能够把IO操做转入线程中执行,主线程仍然能够进行正常的消息循环。
举一个小例子。你用qq邮箱的中转站功能,上传一个文件,在文件传输的时候,你能够最小化上传窗口,去发送、查看邮件,这个就是典型的多线程例子。
打个比方:咱们寝室洗手台有2个水龙头,就是多线程。能够知足2我的刷牙。否则排队蛋疼。
举个最最最简单的例子,程序里面要干两件绝不相干的事情A和B,各费时10分钟,那单线程程序就会这样:等A完了再执行B,总共耗时20分钟。但若是将A和B用两个线程来作则以下:等待两个线程结束。若是两个线程被分配到不一样的cpu上,则理论耗时共10分钟。
--------------------------------------------------------------------------------------------------------
一样以吃饭举例子,假设不少人须要吃饭吃饭,桌子不够,那么桌子就是紧缺资源。单线程就是整个餐厅只有一个单人桌,这我的吃完了,下一我的轮上。但大餐馆用的多是八仙桌(好吧我比较喜欢这种古代的方正桌子),同时能容纳八我的吃饭,这就是多线程:从一次一个变成了一次多个或者屡次多个。如何安排吃饭顺序对程序员来讲是个巨大的挑战,主要问题在于对资源-桌子的安排上,举例说明:
1.死锁-你们都在等着吃饭,但须要特定条件才能开吃:桌一等着桌二的碗,桌二等着桌三的筷子,桌三呢,等着桌一的勺。因而这三桌就都不能吃饭。
2.非原子变量更新-空闲桌子的数字是要加以保护的,相似于特定人员才能修改,假如没有保护,空桌子一下子是四个,一下子是五个,最终的数字每每是不正确的,服务员要被玩死-这就是多线程的加锁操做。
还有其余几种,就很少说了,多线程的调度和使用是一个坑,是否能用好是程序员水平高低的一个标志。
1六、FastCgi与PHP-fpm之间是个什么样的关系
我在网上查fastcgi与php-fpm的关系,查了快一周了,基本看了个遍,真是众说纷纭,没一个权威性的定义。
网上有的说,fastcgi是一个协议,php-fpm实现了这个协议; 有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的; 有的说,php-fpm是php内核的一个补丁; 有的说,修改了php.ini配置文件后,没办法平滑重启,因此就诞生了php-fpm; 还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干嘛又弄个php-fpm出来,我就更晕了;
发个贴,想听听你们的理解,网上的我都已经看了个遍,由于我查了一周了,哈哈,因此想听听原创的理解。
-------------------------------------------------------------------------------------------------
刚开始对这个问题我也挺纠结的,看了《HTTP权威指南》后,感受清晰了很多。
首先,CGI是干吗的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者。
web server(好比说nginx)只是内容的分发者。好比,若是请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。好了,若是如今请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,须要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器。Nginx会传哪些数据给PHP解析器呢?url要有吧,查询字符串也得有吧,POST数据也要有,HTTP header不能少吧,好的,CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。仔细想一想,你在PHP代码中使用的用户从哪里来的。
当web server收到/index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,而后处理请求,再以规定CGI规定的格式返回处理后的结果,退出进程。web server再把结果返回给浏览器。
好了,CGI是个协议,跟进程什么的不要紧。那fastcgi又是什么呢?Fastcgi是用来提升CGI程序性能的。
提升性能,那么CGI程序的性能问题在哪呢?"PHP解析器会解析php.ini文件,初始化执行环境",就是这里了。标准的CGI对每一个请求都会执行这些步骤(不闲累啊!启动进程很累的说!),因此处理每一个时间的时间会比较长。这明显不合理嘛!那么Fastcgi是怎么作的呢?首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境,而后再启动多个worker。当请求过来时,master会传递给一个worker,而后当即能够接受下一个请求。这样就避免了重复的劳动,效率天然是高。并且当worker不够用时,master能够根据配置预先启动几个worker等着;固然空闲worker太多时,也会停掉一些,这样就提升了性能,也节约了资源。这就是fastcgi的对进程的管理。
那PHP-FPM又是什么呢?是一个实现了Fastcgi的程序,被PHP官方收了。
你们都知道,PHP的解释器是php-cgi。php-cgi只是个CGI程序,他本身自己只能解析请求,返回结果,不会进程管理(皇上,臣妾真的作不到啊!)因此就出现了一些可以调度php-cgi进程的程序,好比说由lighthttpd分离出来的spawn-fcgi。好了PHP-FPM也是这么个东东,在长时间的发展后,逐渐获得了你们的承认(要知道,前几年你们但是抱怨PHP-FPM稳定性太差的),也愈来愈流行。
好了,最后来回来你的问题。
网上有的说,fastcgi是一个协议,php-fpm实现了这个协议
对。
有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的
对。php-fpm的管理对象是php-cgi。但不能说php-fpm是fastcgi进程的管理器,由于前面说了fastcgi是个协议,彷佛没有这么个进程存在,就算存在php-fpm也管理不了他(至少目前是)。 有的说,php-fpm是php内核的一个补丁
之前是对的。由于最开始的时候php-fpm没有包含在PHP内核里面,要使用这个功能,须要找到与源码版本相同的php-fpm对内核打补丁,而后再编译。后来PHP内核集成了PHP-FPM以后就方便多了,使用--enalbe-fpm这个编译参数便可。
有的说,修改了php.ini配置文件后,没办法平滑重启,因此就诞生了php-fpm
是的,修改php.ini以后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就能够歇着了,经过这种机制来平滑过分。
还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干嘛又弄个php-fpm出
不对。php-cgi只是解释PHP脚本的程序而已。
----------------------------------------------------------------------------------------------
你(PHP)去和爱斯基摩人(web服务器,如 Apache、Nginx)谈生意
你说中文(PHP代码),他说爱斯基摩语(C代码),互相听不懂,怎么办?那就都把各自说的话转换成英语(FastCGI 协议)吧。
怎么转换呢?你就要使用一个翻译机(PHP-FPM)
(固然对方也有一个翻译机,那个是他自带的)
咱们这个翻译机是最新型的,老式的那个(PHP-CGI)被淘汰了。不过它(PHP-FPM)只有年轻人(Linux系统)会用,老头子们(Windows系统)不会摆弄它,只好继续用老式的那个。
---------------------------------------------------------------------------------------------
Fastcgi是CGI的升级版,一种语言无关的协议,用来沟通程序(如PHP, Python, Java)和Web服务器(Apache2, Nginx), 理论上任何语言编写的程序均可以经过Fastcgi来提供Web服务。
Fastcgi的特色是会在一个进程中依次完成多个请求,以达到提升效率的目的,大多数Fastcgi实现都会维护一个进程池。
而PHP-fpm就是针对于PHP的,Fastcgi的一种实现,他负责管理一个进程池,来处理来自Web服务器的请求。目前,PHP-fpm是内置于PHP的。
可是PHP-fpm仅仅是个“PHP Fastcgi 进程管理器”, 它仍会调用PHP解释器自己来处理请求,PHP解释器(在Windows下)就是php-cgi.exe.
---------------------------------------------------------------------------------------------
FASTCGI:WEB服务器与处理程序之间通讯的一种协议,是CGI的改进方案。
CGI程序反复加载是CGI性能低下的主要缘由,若是CGI程序保持在内存中并接受FastCGI进程管理器调度,则能够提供良好的性能、伸缩性、Fail-Over特性等。
FASTCGI是常驻型的CGI,它能够一直运行,在请求到达时,不会花费时间去fork一个进程来处理。
FastCGI是语言无关的、可伸缩架构的CGI开放扩展,将CGI解释器进程保持在内存中,以此得到较高的性能。
通常状况下,FastCGI的整个工做流程是这样的:
一、Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)
二、FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待WebServer的链接。
三、当客户端请求到达Web Server时,FastCGI进程管理器选择并链接到一个CGI解释器。 Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
四、FastCGI子进程完成处理后将标准输出和错误信息从同一链接返回Web Server。当FastCGI子进程关闭链接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个链接。在CGI模式中,php-cgi在此便退出了。
-------------------------------------------------------------------------------------------
fastcgi 是 app server 和web server 之间的通讯协议。 正常架构 app server 是master,web server是client
php-fpm 带两个功能:1.实现了一个支持fastcgi协议的server程序 2. 进程管理器
有了php-fpm,就能够把php脚本变成 多进程模式,采用fastcgi协议的app server,和web server进行通讯
-------------------------------------------------------------------------------------------
CGI => http://www.w3.org/CGI/
FastCGI => http://www.fastcgi.com/drupal/
FPM => FastCGI Process Manager(FastCGI进程管理器)
-------------------------------------------------------------------------------------------
fastcgi是一个协议,没错。php-fpm实现了这个协议,没错。 php-fpm的fastcgi协议须要有个金城吧?php-fpm实现的fastcgi进程就叫php-cgi= =。因此php-fpm就是他自身的fastcgi或php-cgi进程管理器,没错。php-fpm在5.2以前官方是没有php-fpm的。php-fpm是做为一个第三方的补丁你才能用的。5.2以后捏,官方就已经默认加入了,今后就不是一个补丁了。
-------------------------------------------------------------------------------------------
1七、PHP的线程安全模式(Thread Safety)
PHP自身是不支持线程的,可是它在安装的时候,涉及到一个线程安全的问题,Windows下提供了二种安装包,Linux下编译安装提供了–enable-maintainer-zts这个选项。不少人一看到“安全”,就觉得是好事,其实否则。既然PHP没有线程,那么这个线程安全指的是什么呢?这和它的运行方式有关。这里仅对Linux系统下流行的两种PHP运行方式(LNMP和LNAMP)来说一下。若是是LNMP环境,也就是说PHP以php-fpm方式运行,那么就不涉及到线程安全这个问题了,由于php-fpm是以多进程的方式来运行的。若是是以LNAMP或者LAMP方式运行(mod_php),那么应该先了解下Apache的MPM,简单点说,Apache支持以多线程的方式运行(Worker),也支持以多进程的方式运行(Prefork)。通常来说,Linux下的Apache绝大多数都是运行在Prefork模式下,这是出于稳定性的考虑。因此总结下,LNMP下不需线程安全,Apache下为了稳定性的考虑,建议以多进程的方式运行(Prefork),这样也是不须要线程安全的。最后一点,PHP安装为线程安全,会比非线程安全多占用一些CPU,而且可能会增长bug或者不稳定的问题,这才是重点,否则PHP就不必设置这个选项了。