LoginSignup
0
0

More than 5 years have passed since last update.

ぷろぐらむを実行

Last updated at Posted at 2015-02-03

注: 安易に実行しないでください。メモ書きデス。

exeve(2)


#include <unistd.h>
int execve(const char *filename, char *const argv[], char *const envp[]);  

 呼び出し元プロセスを filename で指定したプロセスに置き換える。
成功すると呼び出し元プロセスには帰ってこない。

引数
filename
 実行可能なバイナリ・ファイルまたはスクリプトを絶対パスで渡す。
 execve(2)は環境変数を自動的に調べてはくれないため、絶対パスで渡す必要がある。

argv
 実行するプログラムへの引数を渡す。
 このリストの最後はNULLで終わる必要がある。

evnp
 環境変数を渡す。
 このリストの最後はNULLで終わる必要がある。

戻り値
 成功すると帰えらない。
 失敗すると呼び出し元に -1 を返す。

extern char** environ


#include <unistd.h>
extern char** environ

 環境変数が入った文字列へのポインタ配列。libc, glibcで宣言されている。
この変数はNULLで終わる。
この変数はユーザープログラムの内で宣言する必要がある。

注意

これらの中には、明らかにセキュリティ上の危険が存在する。
ユーザーが IFS や LD_LIBRARY_PATH に異常な値を与えたことによって、
これまで多くのシステムコマンドがだまされて、 システムをひどい目にあわせてきた。

デモ・コード


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

int main(void)
{
  extern char **environ;
  const char* path = "/bin/ls";
  char *const arg[] = {"ls", ".", NULL};

  execve(path, arg, environ);

  return 0;
}

次の部分。


char *const arg[] = {"ls", ".", NULL};

arg[0] に "ls" と書いているのは無くてもかまわない。慣例らしい。

Note:
環境変数は上位に配置される(x86)


 int main(int argc, char *const argv[], const char* env[]) { ... }

fork(2)


#include <unistd.h>
pid_t fork(void);  

・fork()システムコールを発行するプロセス(親プロセス)は自身のプロセスのコピーを作成する。
・親プロセスのメモリ情報、次に実行するステップなど、あらゆる情報をコピーする(PIDは異なる)。
・子プロセスは新しいメモリ空間に割り当てられる。

 fork()を呼んだプロセスは実行ステップを一時中断、子プロセスへ実行権限を委譲する。
親プロセスは子プロセスの正常終了を待つ。

 fork()の戻り値として、親プロセスには子プロセスのPID。子プロセスには0(ゼロ)が帰る。

 子プロセスはexecve(2)を実行すると、親プロセスからコピーされたメモリ空間を開放。
新たなメモリ空間を割り当て、そこへ指定したプログラムを引き当てる。

 親プロセスはfork()を発行後、wait(2)で子プロセスを監視する。
子プロセスが終了すると、親プロセスは子プロセスのリソースを開放し、wait(2)で子プロセスが引き継いた管理情報をクリアする。

kill(2)は終了シグナルを配送するが必ずしもプロセスを終了するとは限らない。
その場合「ソンビ」になって残る。この管理情報はinitが面倒をみてくれる。

wait(2)

子プロセスの状態監視。子プロセスの管理情報の削除。


#include <sys/types.h> 
#include <sys/wait.h>

pid_t wait(int *status);

引数

 取得するステータス

戻り値

  終了した子プロセスのPID。
  エラーの場合 -1。

デモ・コード


#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <stdio.h>

int main(void)
{
  int state=0;
  pid_t child;
  pid_t parent = getpid();

  if((child=fork()) == -1) {  /* 子プロセスの終了後ここから再開 */
    perror("fork");
    _exit(1);
  }
  if(cpid==0) { /* 子プロセス */
    extern char **environ;
    const char* path = "/bin/ls";
    char *const arg[] = {"ls", ".", NULL};
    execve(path, arg, environ);
  }
  if((wait(&status)) == -1) { /* wait(2)の発行 */
     perror("wait");
     _exit(2)
  }
  printf("Parent PID %x\n", paretn);
  printf("Child PID %x Exit Status %x\n", child, status);

  retrun 0;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0