2011-03-08 11 views
33

Voglio eseguire un altro programma nel codice C. Per esempio, voglio eseguire un comandoCome si esegue un programma esterno nel codice C in linux con argomenti?

./foo 1 2 3 

foo è il programma che esiste nella stessa cartella, e 1 2 3 sono argomenti. foo programma crea un file che verrà utilizzato nel mio codice.

Come posso fare?

+1

Perché questa domanda richiede codice C ed è contrassegnata con C++? – Johan

risposta

32

Uso system():

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

system() aspetteranno per foo per completare l'esecuzione, per poi tornare una variabile di stato che può essere utilizzato per controllare ad esempio ExitCode. man 2 wait sul sistema Linux elencare i vari macro è possibile utilizzare per esaminare lo stato, le più interessanti sarebbero WIFEXITED e WEXITSTATUS

In alternativa, se avete bisogno di leggere l'output di foo a stdout, utilizzare popen().

+1

system() è dichiarato dove? –

+4

stdlib.h, trovato in un'altra risposta. –

+2

Vedere https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=2130132 e la risposta alternativa postata da questo autore. –

4

In C

#include <stdlib.h> 

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

In C++

#include <cstdlib> 

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

Quindi aprire e leggere il file come al solito.

1

Come su come questo:

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

Mentre assegna una stringa letterale a un 'char *', è deprecato in C++ e una cattiva idea in C. –

+0

Intendevo: mentre è valido, non solo "while". :) –

1

Ecco il modo di estendere a args variabili quando non si hanno i args hard coded (anche se sono ancora tecnicamente difficile codificati in questo esempio, ma dovrebbe essere facile per capire come estendere ...):

#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

È possibile utilizzare fork() e system() in modo che il programma non ha bisogno di aspettare fino system() rendimenti.

#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

Sarebbe molto più efficiente usare semplicemente execl o execv dal processo figlio perché non userà una shell, non imposterà un nuovo thread, e uscirà subito dopo aver chiamato il sistema, comunque. Inoltre, il processo diventerà uno zombie se non si chiama wait(). – Billy

27

La funzione system invoca una shell per eseguire il comando. Mentre questo è conveniente, è noto allo security implications. Se è possibile specificare completamente il percorso del programma o dello script che si desidera eseguire e si può permettere di perdere l'indipendenza dalla piattaforma fornita da system, è possibile utilizzare un wrapper execve come illustrato nella seguente funzione exec_prog per eseguire in modo più sicuro il programma. .

Ecco come si specificano gli argomenti del chiamante:

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

quindi chiamare la funzione exec_prog in questo modo:

int rc = exec_prog(my_argv); 

Ecco la funzione 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; 
} 

Ricordate il include:

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

Vedi related SE post per situazioni che richiedono la comunicazione con il programma eseguito tramite descrittori di file come stdin e stdout.

+0

Quindi il codice sopra non usa shell per eseguire il comando? – 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; 
} 
Problemi correlati