`
syu
  • 浏览: 16085 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

PHP常见面试题目深入解答分析(二)

阅读更多

高手请继续无视本文,骨灰们请跳跃路过... :-)

很久没有更新了,继续上一篇文.再来讨论几道常见的试题.查看上次的文章请点击这里

题目一: mysql_pconnect与mysql_connect的区别在哪里?哪一个更好
这道题涉及到了数据库长连接的概念.我们知道,PHP脚本的运行机制,每次使用数据库之前,都必须使用connect去连接数据库.而web应用又是并发性非常高的应用场景,如果同时有10个用户访问,便会有10个进程在运行脚本,相应的,就会产生10次数据库连接.如果有100个用户同时访问.那么就自然会产生100次数据库连接.这样便会有两个问题产生:1是频繁建立和撤消数据库连接.本身的开销就非常大,2是数据库的同时连接数是有限的.如果有1000个用户请求同时要访问数据库.而数据库只开放了最高100个连接允许的话,那么就有900个会进入等待或失败的队列. 这就好比是,一群搬运工往屋里搬东西,每一次都需要 开门-->搬东西-->关门 的操作,如果有很多搬运工同时搬,每个人都要执行 开门/关门 这两步操作的话,显然是会产生很大的不必要开销.而且如果这道门能同时通过的人数有限,很多搬运工不得不在外等待.

pcconnect的长连接方式是怎么解决这个问题的呢?

官方手册中对此的描述是:在脚本结束运行时不关闭的连接。当收到一个永久连接的请求时。PHP 将检查是否已经存在一个(前面已经开启的)相同的永久连接。如果存在,将直接使用这个连接;如果不存在,则建立一个新的连接。所谓“相同”的连接是指用相同的用户名和密码到相同主机的连接。

其机制无非是:初次连接数据库时,便将连接句柄交至父进程,子进程要使用数据库连接时,直接将父进程手中早已连接好的句柄交给子进程,这样子进程的连接就成了一种"虚连接"---它并不用真正去与数据库通讯,只需要从父进程手中拿到已经打开的连接句柄,这样就大大节省了连接/关闭的开销.另外,多个子进程,共享父进程的连接句柄,这样实际上数据库对外的连接数,只是跟父进程之间的个数,1000个用户请求,会产生1000个子进程,可能只会产生10个父进程,有10个数据库连接.这样就解决了连接数的问题.

这样看来.长连接的确是很不错的方式.从机理上讲好于connect.所以长连接更好一些.

但事实是并不能这样简单论定的 :-) ,继续深入下去.
首先,长连接的机制是基于父-子进程模式,也就是说,只能跑于模块(apache-php module或iis的isapi)方式,不适用于CGI和CLI模式,因为CGI和CLI模式都是单独进程,执行完就关闭,没有父进程控制.也就谈不上长链接.

另外,由于多个子进程共用父进程的连接句柄,有时会出现一些意外,比如某个子进程由于一些原因,造成一个连接句柄死锁,便会搞得共享这个句柄的所有其它子进程都无法使用数据库.这时候只有重启web服务才能恢复.

优缺点都摆明了出来.至于用哪一个,大家自己根据情况选择吧.

题目二:CGI模式,模块模式与CLI模式运行PHP的区别

以CGI方式运行时,web server将用户请求以消息的方式转交给PHP独立进程,PHP与web服务之间无从属关系.

纯粹调用--返回结果的形式通讯.而模块方式,则是将PHP做为web-server的子进程控制,两者之间有从属关系.最明显的例子就是在CGI模式下,如果修改了PHP.INI的配置文件,不用重启web服务便可生效,而模块模式下则需要重启web服务.

CLI则是命令行接口,用于在操作系统命令行模式下执行PHP,比如可以直接在win的cmd或linux的shell模式下直接输入 php a.php 来得到结果.它与CGI模式最大的不同的地方在于既不会输出HTTP头信息(CGI模式除了输出用户能看到的结果外,还会输出用户不能直接看到的HTTP头信息),抛出的信息也直接以文本方式而不以HTML方式给出,比如新建一个 test.php,

写入内容 <?php phpinfo();?> ,在浏览器中可以看到以HTML表格描述的信息,而在命令行输入 php test.php 则会直接看到纯文本的输出.

题目三:用PHP实现一个双向队列?(腾讯公司面试题)

上次有人问过我这道题,我个人认为用数组函数处理这道题绰足有余了.

<?php

$data = array(1,2,3,4,5);
//从头部插入
array_unshift($data,6,7,8);
//从头部移除
array_shift($data);

//从尾部插入

array_push($data,9);

//从尾部移除

array_pop($data);

?>

以上四个函数已实现双向队列的四个基本操作.可以写一个class将其封装起来即可.

题目四:遍历一个目录及其子目录(新浪公司面试题)

与网上普遍给的代码不同,这道解答,我用了PHP5更安全的scandir函数,以及迭代(foreach)和递归.

各位自己研究吧.未负责的测试/经验感觉应该比网上普遍的要快一些些.

<?php
Function showDir($rDir)
{
foreach(scandir($rDir) as $v)
{
if($v=='.' || $v=='..') continue;
is_dir($rDir.'/'.$v)?$r[$v]=showDir($rDir.'/'.$v):1;
}
return $r;
}
print_r(showDir('.'));
?>

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics