通常来说调用system会发生阻塞,如果程序未执行完毕的话。
system非阻塞方式注意点:必须转后台,同时将输出重定向。否则变为阻塞方式。
<?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以为输出结束,故便没有阻塞了。