Verwenden der execlp-Funktion in C

Jinku Hu 12 Oktober 2023
Verwenden der execlp-Funktion in C

Dieser Artikel demonstriert mehrere Methoden, wie Sie die Funktion execlp in C verwenden können.

Verwenden von execlp zum Ausführen eines neuen Programms mit Dateinamen in C

Die exec-Funktionsfamilie wird als alternative API zum Systemaufruf execve auf niedrigerer Ebene bereitgestellt, um das Laden eines neuen Programms in den Prozessspeicher zu verwalten. Es gibt 6 verschiedene Funktionen in dieser Familie und sie unterscheiden sich hauptsächlich in ihren Parametern und nicht im Ergebnis. Die Funktion execlp ist diejenige, die dem Benutzer die Möglichkeit gibt, den Dateinamen anzugeben, und das Programm wird in Verzeichnissen gesucht, die in der aktuellen PATH-Umgebungsvariablen aufgeführt sind.

Wenn der Dateiname noch den Schrägstrich enthält, wird er als relativer oder absoluter Pfadname behandelt. Im folgenden Beispiel implementieren wir ein Programm, das sich ähnlich wie eine Shell verhält. Nämlich nimmt es den Programmnamen vom Benutzer entgegen und führt ihn als Kindprozess aus. Der Elternprozess wartet, und sobald der Kindprozess zurückkehrt, geht die Kontrolle an die nächste Iteration der Benutzereingabe über. Das Programm sollte vom Benutzer mit Ctrl+D wie einem Tastendruck beendet werden (abhängig vom Betriebssystem). Beachten Sie, dass einige Shell-Befehle nicht ausgeführt werden können, und vor allem, dass die Kommandozeilenargumente nicht übergeben werden, sondern das Programm stattdessen couldn't execute ausgibt.

#include <sys/wait.h>

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

enum { MAXLINE = 256, MAXARGS = 48 };

int main(int argc, char *argv[]) {
  char buf[MAXLINE];
  pid_t pid;
  int status;

  char *str1, *token;

  printf("%% ");
  while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0;

    if ((pid = fork()) < 0) {
      perror("fork");
    } else if (pid == 0) {
      execlp(buf, buf, (char *)NULL);
      printf("couldn't execute: %s", buf);
      exit(127);
    }

    if (waitpid(pid, &status, 0) < 0) perror("waitpid");
    printf("%% ");
  }

  exit(EXIT_SUCCESS);
}

execlp ist eine variadische Funktion; sie kann also eine variable Anzahl von Argumenten annehmen. Das erste und das letzte Argument sind jedoch fest, sie repräsentieren den Zeiger auf den Dateinamen und NULL, der entsprechend in char* gegossen wird. Beachten Sie, dass das Casting eines Null-Zeigers zwingend erforderlich ist, damit die Funktion funktioniert, und dass es auch das Ende der variablen Anzahl von Argumenten kennzeichnet. Kurz gesagt, die Argumente der zweiten Position sollten die Kommandozeilenargumente für das Programm angeben, und das erste davon sollte der Dateiname selbst sein.

Alternativ können wir das vorherige Beispiel implementieren, um Befehle mit Argumenten ausführen zu können. In diesem Fall haben wir die Funktion execvp verwendet, die die Argumentliste als Array entgegennimmt. Außerdem haben wir die Benutzereingabe mit strtok geparst, um jede durch Leerzeichen getrennte Zeichenkette zu nehmen und sie als Argumente zu übergeben. Als Ergebnis erhalten wir eine genauere Emulation eines Shell-Programms.

#include <sys/wait.h>

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

enum { MAXLINE = 256, MAXARGS = 48 };

int main(int argc, char *argv[]) {
  char buf[MAXLINE];
  char *args[MAXARGS];
  pid_t pid;
  int status, args_num = 0;

  char *str1, *token;

  printf("%% ");
  while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0;

    str1 = strdup(buf);
    for (int j = 0;; j++, str1 = NULL) {
      token = strtok(str1, " ");
      if (token == NULL) break;
      args[j] = token;
      args_num += 1;
      printf("%d: %s\n", j + 1, args[j]);
    }
    free(str1);
    args[args_num] = (char *)NULL;

    if ((pid = fork()) < 0) {
      perror("fork");
    } else if (pid == 0) {
      execvp(args[0], &args[0]);
      printf("couldn't execute: %s", buf);
      exit(127);
    }

    if (waitpid(pid, &status, 0) < 0) perror("waitpid");
    printf("%% ");
  }

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Verwandter Artikel - C Process