EXECVE(2) | Linux Programmer's Manual | EXECVE(2) |
名前
execve -プログラムを実行する書式
#include <unistd.h>説明
execve() は、 filename によって指定されたプログラムを実行する。 filename は、バイナリ実行形式か、以下の形式の行で始まるスクリプトでなければならない。#! interpreter [optional-arg]
int main(int argc, char *argv[], char *envp[])
- *
- 捕捉されたシグナルの処理方法 (disposition) はデフォルト動作にリセットされる ( signal(7))。
- *
- 代替シグナルスタックはどれも保持されない ( sigaltstack(2))。
- *
- メモリマッピングは保持されない ( mmap(2))。
- *
- 付加された (attached) System V 共有メモリセグメントは分離される ( shmat(2))。
- *
- POSIX 共有メモリ領域はマッピングを解除される ( shm_open(3))。
- *
- オープンされた POSIX メッセージキューディスクリプタはクローズされる ( mq_overview(7))。
- *
- オープンされた POSIX 名前付きセマフォはいずれもクローズされる ( sem_overview(7))。
- *
- POSIX タイマは保持されない ( timer_create(2))。
- *
- オープンされたディレクトリストリームはいずれもクローズされる ( opendir(3))。
- *
- メモリロックは保持されない ( mlock(2), mlockall(2))。
- *
- 終了 (exit) ハンドラは保持されない ( atexit(3), on_exit(3))。
- *
- 浮動小数点関連の環境はデフォルトにリセットされる ( fenv(3) 参照)。
上記のリストのプロセス属性はいずれも POSIX.1-2001 で規定されている。以下に示す Linux 固有のプロセス属性も execve() の前後で保持されない。
- *
- set-user-ID か set-group-ID されたプログラムが実行されている場合、 prctl(2) の PR_SET_DUMPABLE フラグはクリアされる。それ以外の場合、このフラグはセットされる。
- *
- prctl(2) の PR_SET_KEEPCAPS フラグはクリアされる。
- *
- (Linux 2.4.36 以降 / 2.6.23 以降) set-user-ID や set-group-ID されたプログラムが実行された場合、 prctl(2) の PR_SET_PDEATHSIG フラグで設定された parent death シグナルはクリアされる。
- *
- プロセス名は新しい実行ファイルの名前にリセットされる。プロセス名は prctl(2) の PR_SET_NAME で設定でき、 ps -o comm で表示できる。
- *
- SECBIT_KEEP_CAPS の securebits フラグはクリアされる。 capabilities(7) 参照。
- *
- 終了シグナル (termination signal) は SIGCHLD にリセットされる ( clone(2) 参照)。
以下の点についても注意すること:
- *
- 呼び出し元スレッド以外の全てのスレッドは execve() 中に破棄される。 mutex、条件変数、その他の pthread オブジェクトは保持されない。
- *
- setlocale(LC_ALL, "C") 相当の処理がプログラム開始時に実行される。
- *
- POSIX.1-2001 は、動作が無視かデフォルトに設定されている全てのシグナルの処理方法は変更せずそのままにする、と規定している。但し、POSIX.1-2001 には一つ例外があり、 SIGCHLD が無視になっている場合、その処理方法を変更せずにそのままにするか、デフォルト動作にリセットするかは実装依存となっている。 Linux では前者 (変更しない) となっている。
- *
- 完了していない非同期 I/O 操作はキャンセルされる ( aio_read(3), aio_write(3))。
- *
- execve(2) 時のケーパビリティの扱いについては、 capabilities(7) を参照。
- *
- デフォルトでは、ファイルディスクリプタは execve() を行った後でもオープンされたままである。 close-on-exec の印が付いているファイルディスクリプタはクローズされる。 fcntl(2) の FD_CLOEXEC の説明を参照。 (ファイルディスクリプタがクローズされると、このプロセスがファイルディスクリプタに対応するファイルに対して獲得していたレコードのロックが全て解放されることになる。) POSIX.1-2001 では、ファイルディスクリプタ 0, 1, 2 が execve() 成功後にどこかでクローズされ、かつ実行されるファイルに set-user_ID か set-group_ID の許可ビットがセットされていてプロセスが特権を獲得した場合、システムは何らかのファイルをオープンする際にこれらの番号のディスクリプタのどれかを使うことがある、とされている。原則として、移植性が必要なプログラムでは、特権の有無に関わらず、 execve() の前後でこれら 3つのファイルディスクリプタがクローズされたままであることを前提にすることはできない。
インタプリタ・スクリプト
インタプリタ・スクリプトとは、実行許可が有効になっていて、最初の行が以下の形になっているテキストファイルのことである。#! interpreter [optional-arg]
interpreter [optional-arg] filename arg...
引き数と環境変数の合計サイズの上限
ほとんどの UNIX の実装は、新しいプログラムに渡すことができるコマンドライン引き数 ( argv) と環境変数 ( envp) の文字列群の合計サイズに何らかの上限を設けている。 POSIX.1 は、 ARG_MAX 定数を使ってこの上限を決める実装を認めている ( ARG_MAX は <limits.h> で定義されるか、実行時に sysconf(_SC_ARG_MAX) の呼び出しで入手できるかのいずれかである)。返り値
成功すると execve() は返らない。エラーの場合は-1 を返し、 errno を適切に設定する。エラー
- E2BIG
- 環境変数 ( envp) と引き数リスト ( argv) の合計バイト数が大き過ぎる。
- EACCES
- filename やスクリプトインタプリタ名の構成要素に検索許可 (search permission) が与えられていない ( path_resolution(7) も参照すること)。
- EACCES
- ファイルもしくはスクリプトのインタプリタが通常ファイル (regular file) でない。
- EACCES
- ファイルやスクリプトや ELF インタプリタに実行許可 (execute permission) が与えられていない。
- EACCES
- ファイル・システムが noexec でマウントされている。
- EFAULT
- filename がアクセス可能なアドレス空間の外を指している。
- EINVAL
- ELF 実行形式で複数の PT_INTERP セグメントが存在する。 (すなわち複数のインタプリタを指定した。)
- EIO
- I/O エラーが発生した。
- EISDIR
- ELF インタプリタがディレクトリだった。
- ELIBBAD
- ELF インタプリタが理解できるフォーマットでなかった。
- ELOOP
- filename やスクリプトや ELF のインタプリタを解決する際に遭遇したシンボリック・リンクが多過ぎる。
- EMFILE
- そのプロセスがオープンできるファイル数の上限まで既にオープンしている。
- ENAMETOOLONG
- filename が長過ぎる。
- ENFILE
- オープンされたファイルの総数がシステム全体の上限に達していた。
- ENOENT
- ファイル filename かスクリプトや ELF のインタプリタが存在しない。
- ENOEXEC
- 実行ファイルが理解できない形式であるか、違うアーキテクチャのものか、その他のフォーマット・エラーにより実行ができなかった。
- ENOMEM
- カーネルに十分なメモリがない。
- ENOTDIR
- filename やスクリプトや ELF のインタプリタの構成要素がディレクトリでない。
- EPERM
- ファイル・システムが nosuid でマウントされ、ユーザがスーパーユーザでなく、ファイルに set-user-ID あるいは set-group-ID ビットが設定されている。
- EPERM
- プロセスがトレースされ、ユーザがスーパーユーザでなく、ファイルに set-user-ID あるいは set-group-ID ビットが設定されている。
- ETXTBSY
- 実行ファイルを書き込み用にオープンしているプロセスがある。
準拠
SVr4, 4.3BSD, POSIX.1-2001. POSIX.1-2001 には #! 動作についての記述はないが、他は互換性がある。注意
set-user-id プロセスと set-group-ID プロセスは ptrace(2) できない。歴史
UNIX V6 では exec() コールの引き数リストは 0 で終端され、 main の引き数リストは-1 で終端されていた。そのため、 main の引き数リストは、その後の exec() コールには直接使用できなかった。 UNIX V7 以降では、ともに NULL で終端される。例
このプログラムは、以下の二つ目のプログラムから実行するためのものである。コマンドラインを 1行に 1個ずつ表示するだけのプログラムである。/* myecho.c */
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int j;
for (j = 0; j < argc; j++)
printf("argv[%d]: %s\n", j, argv[j]);
exit(EXIT_SUCCESS);
}
以下のプログラムは、コマンドライン引き数で指定した名前のプログラムを実行するのに使う。
/* execve.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
char *newargv[] = { NULL, "hello", "world", NULL };
char *newenviron[] = { NULL };
if (argc != 2) {
fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
exit(EXIT_FAILURE);
}
newargv[0] = argv[1];
execve(argv[1], newargv, newenviron);
perror("execve"); /* execve() only returns on error */
exit(EXIT_FAILURE);
}
二つ目のプログラムを使って一つ目のプログラムを実行するには以下のようにする。
$ cc myecho.c -o myecho
$ cc execve.c -o execve
$ ./execve ./myecho
argv[0]: ./myecho
argv[1]: hello
argv[2]: world
さらに、これらのプログラムを使って、スクリプト・インタプリタの例を示す。このために、「インタプリタ」として先ほど作成したプログラム myecho を使うスクリプトを作成する。
$ cat > script.sh
#! ./myecho script-arg
^D
$ chmod +x script.sh
作成しておいたプログラムを使ってスクリプトを実行する。
$ ./execve ./script.sh
argv[0]: ./myecho
argv[1]: script-arg
argv[2]: ./script.sh
argv[3]: hello
argv[4]: world
関連項目
chmod(2), fork(2), ptrace(2), execl(3), fexecve(3), getopt(3), credentials(7), environ(7), path_resolution(7), ld.so(8)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-10-27 | Linux |