C 語言中的 execvp 函式

Jinku Hu 2023年1月30日 2021年2月7日
  1. 在 C 語言中使用 execvp 函式替換程序映像
  2. 正確處理 execvp 函式呼叫錯誤方案和相應的輸出訊息
  3. 在 C 語言中使用 execvpfork 函式建立一個子程序並執行不同的程式
C 語言中的 execvp 函式

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

在 C 語言中使用 execvp 函式替換程序映像

在基於 Unix 的系統中,有兩個獨立的系統呼叫來建立一個新的程序和將新的程式程式碼載入到一個正在執行的程序中。後者使用 exec 系列庫函式來完成,這些函式只是 execve 系統呼叫的不同介面。有 6 種不同的函式原型。execlpexecleexecvexecvpexecvpe。這些函式以一個檔名或一個新程式檔案的路徑名作為第一個引數來載入和執行。execvp 也接受一個程式引數陣列作為第二個引數。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void) {
    const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };

    execvp("vim", args);

    exit(EXIT_SUCCESS);
}

正確處理 execvp 函式呼叫錯誤方案和相應的輸出訊息

需要注意的是,exec 系列函式只有在發生錯誤時才會返回,所以要實現錯誤檢查例程,並根據需要處理相應的程式碼路徑。
其中 execvp 在失敗時返回 -1,而且它還會設定 errno 變數。不過要注意,errno 應該在函式呼叫前明確設定為 0,只有在給定的呼叫返回後才檢查該值。execvp 函式可以接受沒有斜線的檔名,這意味著檔案是在 PATH 環境變數指定的目錄中搜尋的。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void) {
    const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };

    errno = 0;
    if (execvp("vim", args) == -1) {
        if (errno == EACCES)
            printf("[ERROR] permission is denied for a file\n");
        else
            perror("execvp");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

在 C 語言中使用 execvpfork 函式建立一個子程序並執行不同的程式

另外,假設使用者需要建立一個新的程序,並執行給定的程式程式碼,那麼在這種情況下,我們可以利用 fork 函式呼叫與 execvp 相結合。在這種情況下,我們可以利用 fork 函式呼叫與 execvp 相結合。fork 複製呼叫的程序,並建立一個新的程序,稱為-子程序。在下面的例子中,我們實現了一個自定義函式包裝器來建立一個新的程序並載入/執行給定的程式程式碼。請注意,一旦建立了子程序,它就會執行不同的程式碼,而父程序則會等待,直到子程序退出。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>

pid_t spawnChild(const char* program, char** arg_list)
{
    pid_t ch_pid = fork();
    if (ch_pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (ch_pid > 0) {
        printf("spawn child with pid - %d\n", ch_pid);
        return ch_pid;
    } else {
        execvp(program, arg_list);
        perror("execve");
        exit(EXIT_FAILURE);
    }
}

int main(void) {
    const char *args[] = { "vim", "/home/ben/tmp3.txt", NULL };

    pid_t child;
    int wstatus;

    child = spawnChild("vim", args);

    if (waitpid(child, &wstatus, WUNTRACED | WCONTINUED) == -1) {
        perror("waitpid");
        exit(EXIT_FAILURE);
    }

    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