system, exec阻塞问题

通常来说调用system会发生阻塞,如果程序未执行完毕的话。

sleep.php
<?php
sleep(60);

system非阻塞方式注意点:必须转后台,同时将输出重定向。否则变为阻塞方式。

system.php
<?php
for ($i = 0; $i < 10; $i++) {
  echo "i: ", $i, "\n";
  system('php sleep.php >/dev/null 2>&1 &');
}
echo "ok\n";

在shell程序中调用执行很久的php的程序也会阻塞住,若需要并发执行多个,则必须末尾加&

php中几个可以执行shell命令的函数:exec, system, passthru

/* {{{ php_exec
 * If type==0, only last line of output is returned (exec)
 * If type==1, all lines will be printed and last lined returned (system)
 * If type==2, all lines will be saved to given array (exec with &$array)
 * If type==3, output will be printed binary, no lines will be saved or returned (passthru)
 *
 */

查看php源码exec, system, passthru这几个函数均是使用C popen()进行系统调用实现:fp = popen(cmd_p, “r”);

The popen() function ``opens'' a process by creating a bidirectional pipe, forking, and invoking the shell.  Any streams opened by
previous popen() calls in the parent process are closed in the new child process.  Historically, popen() was implemented with a
unidirectional pipe; hence, many implementations of popen() only allow the mode argument to specify reading or writing, not both.
Because popen() is now implemented using a bidirectional pipe, the mode argument may request a bidirectional data flow.  The mode
argument is a pointer to a null-terminated string which must be `r' for reading, `w' for writing, or `r+' for reading and writing.

将进程转后台并输出重定向,让popen以为输出结束,故便没有阻塞了。

参考

php/system_block.txt · 最后更改: 2012/04/15 23:11 由 admin
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki