使用 C 語言中的 execlp 函式

Jinku Hu 2023年10月12日
使用 C 語言中的 execlp 函式

本文將演示關於如何使用 C 語言中的 execlp 函式的多種方法。

使用 execlp 在 C 語言中使用檔名執行新程式

exec 系列函式是作為低階 execve 系統呼叫的替代 API 提供的,用於管理將新程式載入到程序記憶體中。這個系列有 6 個獨立的函式,它們主要是引數不同而不是結果不同。execlp 函式是給使用者指定檔名的選項,程式會在當前 PATH 環境變數列出的目錄中搜尋。

如果檔名仍然包含斜線,則被視為相對或絕對路徑名。在下面的例子中,我們實現了一個行為類似於 shell 的程式。也就是說,它從使用者那裡獲取程式名,並作為一個子程序來執行。父程序等待,一旦子程序返回,控制權就會進入使用者輸入的下一個迭代。程式應該由使用者用Ctrl+D這樣的按鍵終止(取決於作業系統)。注意,有些 shell 命令不能執行,最重要的是,命令列引數沒有傳遞,而程式卻列印出 couldn't execute

#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 是可變函式,因此,它可以接受不同數量的引數。不過第一個和最後一個引數是固定的,代表檔名的指標,而 NULL 則相應地投向 char*。需要注意的是,強制轉換 null 指標是函式工作的必備條件,同時也表示變數引數數的結束。總之,第二個位置的引數應該指定程式的命令列引數,其中第一個引數應該是檔名本身。

另外,我們也可以實現前面的例子,能夠執行帶有引數的命令。在這種情況下,我們利用了 execvp 函式,它將引數列表作為一個陣列。同時,我們使用 strtok 來解析使用者輸入,將每個空格分隔的字串作為引數傳遞。結果,我們得到了更接近 shell 程式的模擬。

#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);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C Process