1. 概要

この記事では、 exec()ファミリーの関数、それらの機能、およびそれらの違いについて説明します。

これらの関数はファイルを実行するために使用され、呼び出されると現在のプロセスイメージを新しいプロセスイメージに置き換えます。 それらは非常に似ていますが、それらの間には違いがあり、それぞれが引数として異なる情報を受け取ります。

2.  execl()

execute()は、実行可能ファイルの場所を最初の引数として受け取ります。 次の引数は、実行時にファイルで使用できるようになります。 最後の引数はNULLである必要があります。

int execl(const char *pathname, const char *arg, ..., NULL)

例を見てみましょう。 unistd.hを必ず含める必要があります。

#include <unistd.h>

int main(void) {
    char *file = "/usr/bin/echo";
    char *arg1 = "Hello world!";
	
    execl(file, file, arg1, NULL);

    return 0;
}

実行しているコマンドは、 / usr / bin /echoにあるechoです。 慣例により、プログラムで使用できる最初の引数はプログラム自体である必要があります。

これで、コードをコンパイルして実行できます。

$ gcc execl.c -o execl
$ ./execl
Hello world!

echoは出力を画面に正常に出力しました。

3.  execlp()

execlp()は、 execl()と非常によく似ています。 ただし、 execlp()は、PATH環境変数を使用してファイルを検索します。 したがって、実行可能ファイルへのパスは必要ありません。

int execlp(const char *file, const char *arg, ..., NULL)

例を見てみましょう:

#include <unistd.h>

int main(void) {
    char *file = "echo";
    char *arg1 = "Hello world!";

    execlp(file, file, arg1, NULL);
    return 0;
}

これで、コンパイルして実行できます。

$ gcc execlp.c -o execlp
$ ./execlp
Hello world!

echo はすでにPATH環境変数にあるため、その場所を指定する必要はありませんでした。

4.  execle()

execle()、を使用すると、環境変数を関数に渡すことができ、それらを使用します。

int execle(const char *pathname, const char *arg, ..., NULL, char *const envp[])

例えば:

#include <unistd.h>

int main(void) {
    char *file = "/usr/bin/bash";
    char *arg1 = "-c";
    char *arg2 = "echo $ENV1 $ENV2!";
    char *const env[] = {"ENV1=Hello", "ENV2=World", NULL};
	
    execle(file, file, arg1, arg2, NULL, env);

    return 0;
}

これで、コンパイルして実行できます。

$ gcc execle.c -o execle
$ ./execle
Hello World!

bash は環境変数を正常に受信し、画面に出力しました。

5.  execv()

execv()は、 execute()とは異なり、実行可能ファイルで使用できる引数のベクトルを受け取ります。 さらに、ベクトルの最後の要素はNULLである必要があります。

int execv(const char *pathname, char *const argv[])

例を見てみましょう:

#include <unistd.h>

int main(void) {
    char *file = "/usr/bin/echo";
    char *const args[] = {"/usr/bin/echo", "Hello world!", NULL};
	
    execv(file, args);

    return 0;
}

これで、コンパイルして実行できます。

$ gcc execv.c -o execv
$ ./execv
Hello world!

6.  execvp()

execlp()と同様に、 execvp()はPATH環境変数でプログラムを検索します。

int execvp(const char *file, char *const argv[])

例えば:

#include <unistd.h>

int main(void) {
    char *file = "echo";
    char *const args[] = {"/usr/bin/echo", "Hello world!", NULL};
	
    execvp(file, args);

    return 0;
}

これで、コンパイルして実行できます。

$ gcc execvp.c -o execvp
$ ./execvp
Hello world!

今回は、プログラムの正確な場所を指定する必要はありませんでした。

7.  execve()

execve()に環境変数を渡すことができます。 さらに、引数はNULLで終了するベクトル内にある必要があります。

int execve(const char *pathname, char *const argv[], char *const envp[])

例えば:

#include <unistd.h>

int main(void) {
    char *file = "/usr/bin/bash";
    char *const args[] = {"/usr/bin/bash", "-c", "echo Hello $ENV!", NULL};
    char *const env[] = {"ENV=World", NULL};
	
    execve(file, args, env);

    return 0;
}

コンパイルして実行しましょう:

$ gcc execve.c -o execve
$ ./execve
Hello World!

環境変数と引数をbashに正常に渡し、画面に出力しました。

8. 結論

この記事では、 exec()ファミリーの関数の各メンバーが何をするのか、そしてそれらの違いを学びました。