zoukankan      html  css  js  c++  java
  • PHP在linux下调用 C

    1.首先介绍下C程序main函数的两个参数的含义。

    1 #include<stdio.h>
    2 int main(int argc, char * argv[])
    3 {
    4     int i;
    5     for (i=0; i < argc; i++)
    6         printf("Argument %d is %s.\n", i, argv[i]);
    7 
    8     return 0;
    9 }

    假设该程序名称为:hello.c,在Linux下gcc hello.c -o hello编译成hello可执行文件。

    在php中执行下面操作.

    <?php
        $command='hello a b c d e';  //给hello应用程序附上a,b,c,d,e5个参数
        $return = exec($command);    //在php中调用exec命令执行该操作
        echo $return;         //打印程序运行的结果
    ?>
    

     输出结果为:

    Argument 0 is hello
    Argument 1 is a.
    Argument 2 is b.
    Argument 3 is c.
    Argument 4 is d.
    Argument 5 is e.

    通过上面例子可知:argc代表输入参数的个数,argv[i]代表输入的具体参数值(hello a b c d e)。


    2.接下来介绍php调用外部程序的几种方法。

    前提:PHP没有运行在安全模式
    如果PHP运行在安全模式下,那么在执行外部命令、打开文件、连接数据库、基于HTTP的认证这4个方面将会受到制约,可能在调用外部程序时无法获取预期的结果,此时需要设置特定目录,可以在php.ini中编辑safe_mode_exec_dir参数来指定。

    1. exec
    原型:string exec ( string command [, array &output [, int &return_var]] )
    描述:返回值保存最后的输出结果,而所有输出结果将会保存到$output数组,$return_var用来保存命令执行的状态码(用来检测成功或失败)。
    例子:$ret = exec("ls -al", $output, $var);
    注意:
    A. 输出结果会逐行追加到$output中,因此在调用exec之前需要unset($output),特别是循环调用的时候。
    B.如果想通过exec调用外部程序后马上继续执行后续代码,仅仅在命令里加"&"是不够的,此时exec依然会等待命令执行完毕;需要再将标准输出 做重定向才可以,例如:exec("ls -al >/dev/null &", $output, $var);
    C. 要学会善用EscapeShellCmd()和EscapeShellArg()。函数EscapeShellCmd把一个字符串 中所有可能瞒过Shell而去执行另外一个命令的字符转义。这些字符在Shell中是有特殊含义的,象分号(|),重定向(>)和从文件读入 (<)等。函数EscapeShellArg是用来处理命令的参数的。它在给定的字符串两边加上单引号,并把字符串中的单引号转义,这样这个字符串 就可以安全地作为命令的参数。

    2. system
    原型:string system ( string command [, int &return_var] )
    描述:执行给定的命令,返回最后的输出结果;第二个参数是可选的,用来得到命令执行后的状态码。
    例子:$ret = system("ls -al", $var);
    注意:略。

    3. passthru
    原型:void passthru (string command [, int return_var])
    描述:执行给定的命令,但不返回任何输出结果,而是直接输出到显示设备上;第二个参数可选,用来得到命令执行后的状态码。
    例子:passthru("ls -al", $var);
    注意:略。

    4. popen
    原型:resource popen ( string command, string mode )
    描 述:打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。
    例子:$fd = popen("command", 'r'); $ret = fgets($fd);
    注意:只能打开单向管道,不是'r'就是'w';并且需要使用pclose()来关闭。

    5. proc_open
    原 型:resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )
    描述:与popen类似,但是可以提供双向管道。具体的参数读者可以自己翻阅资料,比如该博客:http://hi.baidu.com/alex_wang58/blog/item/a28657de16fec55195ee372a.html
    注意:
    A. 后面需要使用proc_close()关闭资源,并且如果是pipe类型,需要用pclose()关闭句柄。
    B. proc_open打开的程序作为php的子进程,php退出后该子进程也会退出。
    C. 在使用的时候遇到获取外部程序输出阻塞的问题,也就是在例子中的fgets($pipes[1])语句阻塞了,无法继续进行。经过多方查证后发现,问题 一般出在外部程序中,比如外部程序是C程序,使用fprintf(stdin, "**** \n");输出结果,此时需要加上fflush(stdout);才行,否则输出结果可能会暂留缓存中,无法真正输出,而php也就无法获取输出了。

    例子:
    ///< 打开管道
    $pwd = "*****";
    $pipes = array();
    $command = "*****";
    $desc = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
    $handle = proc_open($command, $desc, $pipes, $pwd);
    if (!is_resource($handle)) {
        
    fprintf(STDERR, "proc_open failed.\n");
        
    exit(1);
    }
    ///< 读写
    fwrite($pipes[0], "*****\n");
    $ret = rtrim(fgets($pipes[1]), "\n");
    ///< 关闭管道
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($handle);



  • 相关阅读:
    数据库事务
    什么场景应该用 MongoDB ?
    ES6 箭头函数 =>
    HTML5 <template>标签元素简介
    ES6新特性:使用新方法定义javascript的Class
    Windows平台下Git(gitblit)服务器搭建
    利用WiFi Pineapple Nano渗透客户端获取SHELL
    出现 “未能创建此平台,因为已存在同名的解决方案平台”提示,是什么原因?
    VS2010 常用快捷键
    C# WINFORM 捕获全局异常
  • 原文地址:https://www.cnblogs.com/sallybin/p/3104235.html
Copyright © 2011-2022 走看看