2011-03-08 31 views
33

我想在C代码中执行另一个程序。 例如,我想执行一个命令如何在Linux中使用参数在C代码中执行外部程序?

./foo 1 2 3 

foo是存在于同一文件夹中的程序,并且是1 2 3参数。 foo程序创建一个文件,将在我的代码中使用。

我该怎么做?

+1

这个问题为什么要求C代码,并用C++标记? – Johan

回答

32

使用system()

int status = system("./foo 1 2 3"); 

system()将等待FOO完成执行,然后返回,你可以用它来检查例如状态变量退出码。 man 2 wait你的linux系统会列出你可以用它来检查状态的不同的宏上,最有趣的是WIFEXITEDWEXITSTATUS

另外,如果你需要阅读Foo的输出到标准输出,使用popen()

+1

system()声明在哪里? –

+4

stdlib.h,在另一个答案中找到。 –

+2

请参阅https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=2130132以及本作者发布的替代答案。 –

4

在C

#include <stdlib.h> 

system("./foo 1 2 3"); 

在C++

#include <cstdlib> 

std::system("./foo 1 2 3"); 

然后,打开并读取该文件如常。

1

这个怎么样:

char* cmd = "./foo 1 2 3"; 
system(cmd); 
+4

将字符串文字赋值给char *时,它在C++中被弃用,在C中变成坏主意。 –

+0

我的意思是:它是有效的,而不仅仅是“while”。 :) –

1

这里是延伸到可变ARGS当你没有硬编码的ARGS(虽然还是在技术上很难在这个例子中编码的方式,但应该很容易弄清楚如何延长...):

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int argcount = 3; 
const char* args[] = {"1", "2", "3"}; 
const char* binary_name = "mybinaryname"; 
char myoutput_array[5000]; 

sprintf(myoutput_array, "%s", binary_name); 
for(int i = 0; i < argcount; ++i) 
{ 
    strcat(myoutput_array, " "); 
    strcat(myoutput_array, args[i]); 
} 
system(myoutput_array); 
15

您可以使用fork()system()让你的程序不必等到system()回报。

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc,char* argv[]){ 

    int status; 

    // By calling fork(), a child process will be created as a exact duplicate of the calling process. 
    // Search for fork() (maybe "man fork" on Linux) for more information. 
    if(fork() == 0){ 
     // Child process will return 0 from fork() 
     printf("I'm the child process.\n"); 
     status = system("my_app"); 
     exit(0); 
    }else{ 
     // Parent process will return a non-zero value from fork() 
     printf("I'm the parent.\n"); 
    } 

    printf("This is my main program and it will continue running and doing anything i want to...\n"); 

    return 0; 
} 
+0

从子进程中使用execl或execv会更有效率,因为它不会使用shell,它不会分叉新线程,并且在您调用system之后即将退出。另外,如果你不叫wait(),这个过程将会变成僵尸。 – Billy

27

system函数调用shell来运行该命令。虽然这很方便,但它已经众所周知security implications。如果您可以完全指定要执行的程序或脚本的路径,并且您可以承受失去的平台独立性,则可以使用execve封装器,如下面的exec_prog函数所示,以更安全地执行您的程序。

这里是你如何在调用者指定的参数:

const char *my_argv[64] = {"/foo/bar/baz" , "-foo" , "-bar" , NULL}; 

然后调用exec_prog功能是这样的:

int rc = exec_prog(my_argv); 

这里的exec_prog功能:

static int exec_prog(const char **argv) 
{ 
    pid_t my_pid; 
    int  status, timeout /* unused ifdef WAIT_FOR_COMPLETION */; 

    if (0 == (my_pid = fork())) { 
      if (-1 == execve(argv[0], (char **)argv , NULL)) { 
        perror("child process execve failed [%m]"); 
        return -1; 
      } 
    } 

#ifdef WAIT_FOR_COMPLETION 
    timeout = 1000; 

    while (0 == waitpid(my_pid , &status , WNOHANG)) { 
      if (--timeout < 0) { 
        perror("timeout"); 
        return -1; 
      } 
      sleep(1); 
    } 

    printf("%s WEXITSTATUS %d WIFEXITED %d [status %d]\n", 
      argv[0], WEXITSTATUS(status), WIFEXITED(status), status); 

    if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) { 
      perror("%s failed, halt system"); 
      return -1; 
    } 

#endif 
    return 0; 
} 

记住包括:

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <stdio.h> 

参见related SE post用于需要经由文件描述符如stdinstdout执行的程序的通信状况。

+0

所以上面的代码不使用shell来执行命令? – user3769778

2
#include <unistd.h> 

int main() { 
    if (fork() == 0) { 
      execl("foo", "foo", "1", "2", "3", 0); 
      # We woundn't still be here if execl() was successful, so we exit with a non-zero value. 
      return -1; 
    } 

    return 0; 
} 
相关问题