web-dev-qa-db-ja.com

fork、exec、waitを正しく使用する方法

私が書いているシェルは、ユーザーから与えられたプログラムを実行する必要があります。これは私のプログラムの非常に短縮された簡略版です

int main()
{
    pid_t pid = getpid(); // this is the parents pid

    char *user_input = NULL;
    size_t line_sz = 0;
    ssize_t  line_ct = 0; 

    line_ct = getline(&user_input, &line_sz, stdin); //so get user input, store in user_input

    for (;;)
    {
        pid_t child_pid = fork(); //fork a duplicate process

        pid_t child_ppid = getppid(); //get the child's parent pid

        if (child_ppid == pid) //if the current process is a child of the main process
        {
            exec(); //here I need to execute whatever program was given to user_input
            exit(1); //making sure to avoid fork bomb
        }

        wait(); //so if it's the parent process we need to wait for the child process to finish, right?

    }
}
  1. 新しいプロセスを分岐し、それが正しく子プロセスであるかどうかを確認しましたか
  2. 私がしようとしていることのために、ここでどのexecを使用できますか?最も簡単な方法は何ですか
  3. 待つ私の議論は何ですか?私が見ているドキュメントはあまり役に立たない

ユーザーがls、ps、pwdなどを入力すると仮定します

ありがとう。

編集:

const char* hold = strdup(input_line);
char* argv[2]; 

argv[0] = input_line;
argv[1] = NULL;

char* envp[1];
envp[0] = NULL;

execve(hold, argv, envp);
22
Collin

シンプルで読みやすいソリューションを次に示します。

pid_t parent = getpid();
pid_t pid = fork();

if (pid == -1)
{
    // error, failed to fork()
} 
else if (pid > 0)
{
    int status;
    waitpid(pid, &status, 0);
}
else 
{
    // we are the child
    execve(...);
    _exit(EXIT_FAILURE);   // exec never returns
}

子は、親のPIDを知る必要がある場合(この例ではわかりませんが)、保存された値parentを使用できます。親は単に子が終了するのを待ちます。事実上、子は親内で「同期的に」実行され、並列性はありません。親はstatusを照会して、子がどのように終了したか(成功、失敗、またはシグナルで)を確認できます。

49
Kerrek SB