使用 C 語言中的 execlp 函式

Jinku Hu 2022年3月29日 2021年2月28日
使用 C 語言中的 execlp 函式

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

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

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

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

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include <sys/wait.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 "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include <sys/wait.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);
}
Author: 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

相關文章 - C Process