UNIXプログラミング入門~プロセス編(2/4)~
c/c++でunix系osプログラミングを行うときに使うunistd.h
やその周辺のライブラリのお話その4です。
このメモでは、プロセス周りのシステムコールAPIに関して取り上げます。
プロセスを別のプロセスに置き換える-execvp(3)-
execvp
のプロトタイプはunistd.h
に以下のように定義されています。
int execvp(const char *file, char *const argv[]);
第一引数、file
に指定したプログラムを第二引数argv[]
で実行する。
argv[]
の最後にはNULL
を入れる必要があります。
NULLターミネート
新たなプロセスを作成するのではなく、現在のプロセスを指定したプログラムに置き換える点に注意してください。
つまり新しいプロセスを作る訳ではないのでプロセスIDは変化しません。
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc < 1) {
return 0;
}
execvp(argv[1], &argv[2]);
return 0;
}
引数に与えられたコマンドを実行するプログラムです。
このままでは、あまり意味のあるようには思えませんが、前回紹介したfork
関数と組み合わせると面白いことが出来そうです。
自作bash風プログラム
まずは、プロセス編で紹介した関数を簡単におさらいします。
fork(2)
現在のプロセスを複製して新しいプロセスを作成するwaitpid(2)
子プロセスの完了を待つexecvp(3)
現在のプロセスを別のプログラムに置きかえる
前回とここまでの内容を踏まえて自作のbash
風プログラムを作ってみたいと思います。
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <stdio.h>
#define BUF_LEN 1024
int main(int argc, char const *argv[])
{
printf("welcome to my bash!\n");
for(;;)
{
fprintf(stderr, ">>");
char buf[BUF_LEN];
fgets(buf, BUF_LEN, stdin);
char *sep = " \n";
char *exec = strtok(buf, sep);
if(exec == NULL)
continue;
char *tkn[BUF_LEN];
for(int i = 0;;++i)
{
tkn[i] = strtok(NULL, sep);
if (tkn[i] == NULL) break;
}
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "fork failed\n");
}
else if (pid > 0)
{
int stat;
waitpid(pid, &stat, 0);
}
else
{
execvp(exec, tkn);
}
}
return 0;
}
パイプやリダイレクトなどもともとのbash
にある機能はありませんが、とりあえずそれっぽいプログラムが出来ました。
次回以降パイプやリダイレクトに関して話を進めていこうと思います。