私は最近システムプログラミングコースをフォローしており、システムコールexec()およびexecve()を受講しました。これまでのところ、これら2つの違いを見つけることはできません。ウィキペディアでも明確な説明はないため、exec()との間に違いがありますexecve()。
そして、誰かがexecl()、execv()、execle()、execvp()。
使用する - man exec
と読む:
The execv(), execvp(), and execvpe() functions provide an array of pointers to
null-terminated strings that represent the argument list available to the new program.
The first argument, by convention, should point to the filename associated with the file
being executed. The array of pointers must be terminated by a NULL pointer.
execv
int execv(const char *path, char *const argv[]);
したがって、配列をパラメーターとして渡します
int execle(const char *path, const char *arg,
..., char * const envp[]);
ほとんど同じですが、配列としてではなく、値のリスト(文字列)として続き、その後に環境を指定する配列が続きます。
ここに:
int execvp(const char *file, char *const argv[]);
パスなしでファイルを呼び出しているので、呼び出す前にすでに正しいpath
にいることが期待されています。
最後だが大事なことは:
int execve(const char *filename, char *const argv[],
char *const envp[]);
前のものと同様ですが、引数と環境変数用の2つの配列があります。
exec
システムコールはありません。これは通常、すべてのexecXX
コールをグループとして参照するために使用されます。それらはすべて基本的に同じことを行います。新しいプログラムを現在のプロセスにロードし、それに引数と環境変数を提供します。違いは、プログラムの検索方法、引数の指定方法、環境の場所にあります。
名前にv
が含まれる呼び出しでは、配列パラメーターを使用して、新しいプログラムのargv[]
配列を指定します。
名前にl
を含む呼び出しは、新しいプログラムの引数を関数自体への可変長引数リストとして受け取ります。
名前にe
を含む呼び出しは、新しいプログラムの環境を提供するために追加の引数を取ります。それ以外の場合、プログラムは現在のプロセスの環境を継承します。
名前にp
を含む呼び出しは、PATH
環境変数を検索して、ディレクトリが存在しない(つまり、/
文字が含まれていない)プログラムを見つけます。 )。それ以外の場合、プログラム名は常に実行可能ファイルへのパスとして扱われます。
これらの関数はすべてexec()ファミリーに属しているので、extra characters
に応じてdifferentiate
を意味を付けて、
1.exec ve():
p:存在しない=>実行するプログラムの名前はpathname
から取得されます
v:present =>引数はarray
として渡されます
e:現在=>環境はenvp argument
から取得されます
2.exec le():
p:存在しない=>実行するプログラムの名前はpathname
から取得されます
l:present =>引数はlist
として渡されます
e:現在=>環境はenvp argument
から取得されます
3.exec lp():
p:present =>実行するプログラムの名前は、指定されたfilename
から取得されるか、システムがPATH
変数でsearch for program file
を取得します。
l:present =>引数はlist
として渡されます
e:存在しない=>環境はcaller's environ
から取得されます
4.exec vp():
p:present =>実行するプログラムの名前は、指定されたfilename
から取得されるか、システムがPATH
変数でsearch for program file
を取得します。
v:present =>引数はarray
として渡されます
e:存在しない=>環境はcaller's environ
から取得されます
5.exec v():
p:存在しない=>実行するプログラムの名前はpathname
から取得されます
v:present =>引数はarray
として渡されます
e:存在しない=>環境はcaller's environ
から取得されます
6.exec l():
p:存在しない=>実行するプログラムの名前はpathname
から取得されます
l:present =>引数はlist
として渡されます
e:存在しない=>環境はcaller's environ
から取得されます
これらの関数では引数が異なります。
関数execl、execlp、およびexecleでは、新しいプログラムの各コマンドライン引数を個別の引数として指定する必要があります。
Execv、execvp、execve、引数へのポインターの配列を作成する必要があります。この配列のアドレスは、これら3つの関数への引数です。
Execve、execle関数を使用すると、ポインターを環境文字列へのポインターの配列に渡すことができます。他の4つの関数は、呼び出しプロセスでenviron
変数を使用して、既存の環境をプログラムにコピーします。
p
は、関数がファイル名引数を取り、PATH環境変数を使用して実行可能ファイルを見つけることを意味します。l
は、関数が引数のリストを受け取り、文字v
と相互に排他的であることを意味します。つまり、argv []ベクトルを受け取ります。文字e
は、関数がenvp[]
現在の環境を使用する代わりに配列。
新しいプログラムは、呼び出しプロセスから次の追加機能を継承します。
Process ID and the Parent Process ID
Real user ID and Real Group ID
Supplementary group IDs
Process group ID
Session ID
Controlling terminal
Time left until alarm clock
Current working directory
Root directory
File mode creation mask
File locks
Process signal mask
Pending signals
Resource limits
Values for tms_utime, tms_stime, tms_cutime, and tms_cstime.
exec()ファミリーの関数は、既存のプロセスイメージを新しいプロセスイメージに置き換えます。これは、親プロセスと子プロセスがメモリ内で共存するfork()システムコールとの顕著な違いです。
int execv (const char *filename, char *const argv[])
ファイル名は、新しいプロセスイメージのファイルです。
argvはnullで終了する文字列の配列を表します。この配列の最後の要素はnullポインターでなければなりません。
int execl (const char *filename, const char *arg0, …)
Execvと同じですが、引数は配列/ベクトルの代わりに(コンマで区切られた)個別の文字列として提供されます。
int execve (const char *filename, char *const argv[], char *const env[])
Execvと同じですが、新しいプロセスイメージの環境変数を指定できます。
int execle (const char *filename, const char *arg0, …, char *const env[])
Execlと同じですが、新しいプロセスイメージの環境変数を指定できます。
int execvp (const char *filename, char *const argv[])
Execv関数と同じですが、ファイル名にスラッシュが含まれていない場合は、標準の環境変数PATHを検索してファイル名を見つけます。
標準の環境変数のリストは次のとおりです。
https://www.gnu.org/software/libc/manual/html_node/Standard-Environment.html#Standard-Environment
int execlp (const char *filename, const char *arg0, …)
Ifがexecvp関数としてファイル名検索を実行することを除いて、execl関数と同じです。
Linuxシステムでは、シェルまたはターミナルでenv
またはprintenv
と入力すると、標準環境変数のリストが表示されます。
Execファミリーには、機能と呼び出し方法がわずかに異なる関数があります。
名前に文字pが含まれる関数(execvp
およびexeclp
)は、プログラム名を受け入れ、現在の実行パスでその名前でプログラムを検索します。 pを含まない関数には、実行するプログラムの完全パスを指定する必要があります。
名前に文字vを含む関数(execv
、execvp
、およびexecve)は、新しいプログラムの引数リストを、文字列へのポインターのNULL終了配列として受け入れます。文字l(execl
、execlp
、およびexecle)を含む関数は、C言語のvarargs
メカニズムを使用して引数リストを受け入れます。
名前に文字eを含む関数(execve
およびexecle
)は、環境変数の配列である追加の引数を受け入れます。引数は、文字列へのポインターのNULLで終了する配列にする必要があります。各文字列は、VARIABLE=value
の形式にする必要があります。
質問の最初の部分に答えるために、特にLinuxのコンテキストでは、システムコールは1つだけあり、それはexecveです(-execではありません)。いわゆる「execファミリー」の残り(execl、execle、execv、execve、execvpなど)は、カーネルのシステムコール用のすべてのGLIBCラッパー、つまりexecveです。