PHP 会话 线程 进程,php进程后台调用(多线程/进程)

/* Note that the call itself isn‘t sanitized in any way, so it‘s

important to make sure that this can‘t be exploited, see

docs for escapeshellcmd() for details

*/

// Demonstration

if(launchBackgroundProcess(‘touch testfile.txt‘)){

print ‘Successfully launched background process‘;

}

/**

* Launch Background Process

*

* Launches a background process (note, provides no security itself, $call must be sanitized prior to use)

* @param string $call the system call to make

* @author raccettura

*/

function launchBackgroundProcess($call) {

// Windows

if(is_windows()){

pclose(popen(‘start /b ‘.$call.‘‘, ‘r‘));

}

// Some sort of UNIX

else {

pclose(popen($call.‘ /dev/null &‘, ‘r‘));

}

return true;

}

/**

* Is Windows

*

* Tells if we are running on Windows Platform

* @author raccettura

*/

function is_windows(){

if(PHP_OS == ‘WINNT‘ || PHP_OS == ‘WIN32‘){

return true;

}

return false;

}

?>

关键在于

‘ /dev/null &‘

(*nix下的后台运行方式)

‘start /b ‘

(windows下的后台运行方式)

想了一下,似乎很多脚本都可以用这种方式将一些操作移交后台进行,可以大幅提高效率。

如果要返回结果,则可以用异步执行并返回状态的方式,边处理边显示处理结果,这可以用在一些耗时较长的操作上,比如论坛备份\恢复等:

/****

* Again notice this is unsanitized since we trust ourselves. Coming from the web

* it would need to be sanitized to ensure it‘s safe to use. see escapeshellarg()

****/

$hostname = ‘accettura.com‘;

?>

Traceroute to $hostname

if(is_windows()){

$cmd = ‘tracert -w 10‘;

} else {

$cmd = ‘traceroute -w 10‘;

}

$handle = popen("$cmd $hostname 2>&1", ‘r‘);

while(!feof($handle)) {

$buffer = fgets($handle);

$buffer = ‘

‘.trim(htmlspecialchars($buffer)).‘

‘;

echo $buffer;

ob_flush();

flush();

}

pclose($handle);

/**

* Is Windows

*

* Tells if we are running on Windows Platform

* @author raccettura

*/

function is_windows(){

if(PHP_OS == ‘WINNT‘ || PHP_OS == ‘WIN32‘){

return true;

}

return false;

}

?>

继续php多线程/进程的问题

昨天找到了进程后台运行的方法,今天测试了一下,发现popen的速度很慢,要40-50毫秒,exec更慢!类似的程序调用命令,都要经过系统调用,每次都开启一个php进程想必很慢。

比较笨的办法还是用fsockopen去通过http在server端get,试了一下,这样不会慢,缺点是增加了apache负载,每个请求都要在后台再请求一次。

我写了段脚本test.php,用fsockopen循环连接本地另外一个脚本test1.php,不做任何操作立即关闭连接,test1.php每次在文本文件test.cache中写入一行,循环100次的时候执行很快,test.cache中也正确的记录了100行。当循环1000次的时候,问题就来了,test.php执行了21.6888360977秒,也就是21秒内向apache发了1000个请求连test1.php,系统马上没有响应了,内存占用飙升到1G多,一分钟之后才恢复正常。test.cache中丢失63行,可能是由于apache超载造成的,但是系统内存却始终没有降下来,apache的占用了83M,剩下的不知道怎么回事- -

最后又找了半天,找到了fork实现的真正多线程!fork是pcntl(Process Control Functions)下的一个函数,pcntl只支持*nix系统,目前没有windows下的相关模块。(文档中说需要在编译php时--enable-pcntl,我用phpize编译成php模块的方式,通过在php.ini中添加extension=pcntl.so也可以使用。)

php手册里面就有了,但是在网上几乎找不到中文的文档!文档里面有这样一个实例:

declare(ticks=1);

echo "I‘m going to be a Dad.n";

if (spawn_child(‘child_function‘)) {

echo ‘Parent pid:‘.posix_getpid()."n";

}

echo "I‘m going to be a Dad again!.n";

if (spawn_child(‘child_function‘,1,2,3,4)) {

echo ‘Child - 2 Parent pid:‘.posix_getpid()."n";

}

echo "What you‘re pregnant again!?.n";

if (spawn_child(‘grand_children‘)) {

echo ‘Child - 3 Parent pid:‘.posix_getpid()."n";

}

function grand_children() {

echo "Dad I‘m going to have a baby.n";

spawn_child(‘child_function‘,‘Joe‘);

echo "I‘m so proud of my kids.n";

}

function spawn_child($function) {

$original_pid = posix_getpid();

$pid = pcntl_fork();

if ($pid == -1) {

die ("Unable to spawn childn");

}

$new_pid = posix_getpid();

if ($new_pid == $original_pid) {

return true;

}

if (function_exists($function)) {

$numargs = func_num_args();

if ($numargs > 1) {

$args = func_get_args();

//print_r ($args);

unset($args[0]);

call_user_func($function,$args);

} else {

call_user_func($function);

}

echo "Done with child ".$new_pid." they moved out.n";

exit;

} else {

die ("$function does not existn");

}

}

function child_function() {

echo ‘Child pid:‘.posix_getpid()."n";

$args = func_get_args();

if (!empty($args))

print_r ($args);

}

pcntl_wait( $status);

?>

用pcntl实现的多线程可以解决很多问题了,但是似乎还是不能解决我的问题。在多线程虽然可以让程序并行执行,但所有的程序仍然在前台完成,在所有的线程完成之前,浏览器仍然会显示载入状态。在这种状态下,javascript代码不会执行,而我正是需要php产生一段javascript脚本,我想我的目的可能不是多线程或者并发处理,而是异步调用、后台执行,让生成脚本之外的操作在后台执行。

所以我的这种情况用最开始的fsockopen()方法可能更有效,但是fsockopen是不能进行异步处理的,如果要跟打开的连接进行交互,就没有任何优势可言了。不过我在网上找到了可以进行异步通信的办法,其实是变相的实现了多线程:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值