Wie führe ich ein externes Programm in C-Code in Linux mit Argumenten aus?

Lesezeit: 5 Minuten

Benutzeravatar von js0823
js0823

Ich möchte ein anderes Programm in C-Code ausführen. Ich möchte zum Beispiel einen Befehl ausführen

./foo 1 2 3

foo ist das Programm, das im selben Ordner vorhanden ist, und 1 2 3 sind Argumente.
foo Das Programm erstellt eine Datei, die in meinem Code verwendet wird.

Wie mache ich das?

  • Warum fragt diese Frage nach C-Code und ist mit C++ gekennzeichnet?

    – Johann

    9. März 2011 um 16:19 Uhr

  • Weil jede Lösung in C++ funktionieren würde

    Benutzer9599745

    30. Oktober 2019 um 1:27 Uhr

Benutzeravatar von Erik
Erik

Verwenden Sie für einen einfachen Weg system():

#include <stdlib.h>
...
int status = system("./foo 1 2 3");

system() wartet, bis foo die Ausführung abgeschlossen hat, und gibt dann eine Statusvariable zurück, mit der Sie z. B. den Exitcode überprüfen können (der Exitcode des Befehls wird mit 256 multipliziert, also teilen Sie den Rückgabewert von system() durch diesen, um den tatsächlichen Exitcode zu erhalten: int exitcode = status / 256).

Die Manpage für wait() (in Abschnitt 2, man 2 wait auf Ihrem Linux-System) listet die verschiedenen Makros auf, mit denen Sie den Status untersuchen können, die interessantesten wären WIFEXITED und WEXITSTATUS.

Alternativ, wenn Sie die Standardausgabe von foo lesen müssen, verwenden Sie popen(3)die einen Dateizeiger zurückgibt (FILE *); Die Interaktion mit der Standard-Ein-/Ausgabe des Befehls entspricht dann dem Lesen oder Schreiben in eine Datei.

  • wo wird system() deklariert?

    – Jens Björnhager

    7. September 2013 um 18:04 Uhr

  • stdlib.h, gefunden in einer anderen Antwort.

    – Jens Björnhager

    7. September 2013 um 18:06 Uhr

  • Sehen securecoding.cert.org/confluence/pages/… und alternative Antwort von diesem Autor gepostet.

    – Jonathan Ben-Avraham

    27. November 2014 um 14:30 Uhr

  • @Erik: Was kann ich tun, wenn keine Shell verfügbar ist?

    – Benutzer2284570

    6. April 2015 um 14:26 Uhr

  • Diese Lösung ist nicht der richtige Weg, Sie können viele Sicherheitsfehler in Ihre Anwendung einführen. Überprüfen Sie dies: securecoding.cert.org/confluence/pages/… Eine bessere Lösung ist die Verwendung von popen oder execve oder verwandten Funktionen.

    – Dunkelmord

    30. August 2016 um 12:24 Uhr

Benutzeravatar von Jonathan Ben-Avraham
Jonathan Ben-Avraham

Das system Funktion ruft eine Shell auf, um den Befehl auszuführen. Das ist zwar bequem, aber bekanntlich Auswirkungen auf die Sicherheit. Wenn Sie den Pfad zu dem Programm oder Skript, das Sie ausführen möchten, vollständig angeben können, können Sie es sich leisten, die Plattformunabhängigkeit zu verlieren system bietet, dann können Sie eine verwenden execve Wrapper wie in der abgebildet exec_prog Funktion unten, um Ihr Programm sicherer auszuführen.

So geben Sie die Argumente im Aufrufer an:

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

Dann ruf die an exec_prog funktionieren so:

int rc = exec_prog(my_argv);

Hier ist die exec_prog Funktion:

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;
}

Denken Sie daran, dass Folgendes enthalten ist:

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

Siehe verwandten SE-Beitrag für Situationen, die eine Kommunikation mit dem ausgeführten Programm über Dateideskriptoren wie z stdin und stdout.

  • Was macht %s und %m rein machen perror Anrufe) ? Ist es kein Fehler?

    – Loxaxe

    5. April 2018 um 7:51 Uhr

Benutzeravatar von Pedro Alves
Pedro Alve

Sie können verwenden fork() und system() damit Ihr Programm nicht bis warten muss system() kehrt zurück.

#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;
}

  • Es wäre weitaus effizienter, nur execl oder execv aus dem untergeordneten Prozess zu verwenden, da dies keine Shell verwendet, keinen neuen Thread forkt und Sie sowieso direkt nach dem Aufruf von system beenden. Außerdem wird der Prozess zu einem Zombie, wenn Sie wait() nicht aufrufen.

    – Billi

    26. September 2016 um 21:42 Uhr

Billys Benutzeravatar
Billy

system() führt eine Shell aus, die dann für das Analysieren der Argumente und das Ausführen des gewünschten Programms verantwortlich ist. Um das Programm direkt auszuführen, verwenden Sie fork() und exec() (was system() verwendet, um die Shell auszuführen, sowie das, was die Shell selbst verwendet, um Befehle auszuführen).

#include <unistd.h>

int main() {
     if (fork() == 0) {
          /*
           * fork() returns 0 to the child process
           * and the child's PID to the parent.
           */
          execl("/path/to/foo", "foo", "arg1", "arg2", "arg3", 0);
          /*
           * We woundn't still be here if execl() was successful,
           * so a non-zero exit value is appropriate.
           */
          return 1;
     }

     return 0;
}

In C

#include <stdlib.h>

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

In C++

#include <cstdlib>

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

Öffnen und lesen Sie die Datei dann wie gewohnt.

  • Ich versuche dies zu tun, aber anstatt den Wert direkt zu verwenden, muss ich eine AC-Variable übergeben, wie kann ich das tun?

    – Everaldo

    16. Juli 2021 um 21:37 Uhr

Benutzeravatar von Johan
Johann

Wie wäre es so:

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

  • Ich versuche dies zu tun, aber anstatt den Wert direkt zu verwenden, muss ich eine AC-Variable übergeben, wie kann ich das tun?

    – Everaldo

    16. Juli 2021 um 21:37 Uhr

Benutzeravatar von Hazok
Hazok

So können Sie auf variable Argumente erweitern, wenn Sie die Argumente nicht fest codiert haben (obwohl sie in diesem Beispiel technisch immer noch fest codiert sind, aber einfach herauszufinden sein sollten, wie sie erweitert werden …):

#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);

1413710cookie-checkWie führe ich ein externes Programm in C-Code in Linux mit Argumenten aus?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy