2011-03-08 34 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; 
} 
相關問題