4

割り当てのために、私は時間認識シェルの作成に取り組んでいます。シェルはコマンドをフォークして実行し、設定された時間以上実行された場合はそれらを強制終了します。例えば。

 input# /bin/ls
 a.out code.c
 input# /bin/cat
 Error - Expired After 10 Seconds.
 input#

さて、私の質問は、プログラムの処理でエラーが発生した場合、つまり、exevce が -1 を返した場合にアラームが開始されないようにする方法はありますか?

子プロセスは別々に実行され、何時間もの実験と研究の後で、このタイプのタスクについて議論したり、示唆したりするものをまだ見つけていないため、不可能かもしれないと感じています. 本当に不可能な場合、次のようなことが起こらないようにするにはどうすればよいですか...

 input# /bin/fgdsfgs
 Error executing program
 input# Error - Expired After 10 Seconds.

文脈のために、これは私が現在取り組んでいるコードであり、これを自分で行う試みは削除されています。事前に助けてくれてありがとう!

while(1){
    write(1, prompt, sizeof(prompt)); //Prompt user
    byteCount = read(0, cmd, 1024); //Retrieve command from user, and count bytes
    cmd[byteCount-1] = '\0';    //Prepare command for execution

    //Create Thread
    child = fork();

    if(child == -1){
        write(2, error_fork, sizeof(error_fork));
    }

    if(child == 0){ //Working in child
        if(-1 == execve(cmd,arg,env)){  //Execute program or error
            write(2, error_exe, sizeof(error_exe));
        }   
    }else if(child != 0){   //Working in the parent
        signal(SIGALRM, handler);   //Handle the alarm when it goes off
        alarm(time);
        wait();
        alarm(0);
    }
}
4

2 に答える 2

7

マニュアルページによると:

説明

alarm() 関数は、秒で指定されたリアルタイム秒数が経過した後、システムにプロセスの SIGALRM シグナルを生成させます。プロセッサのスケジューリング遅延により、プロセスは信号が生成されるとすぐに処理できなくなる場合があります。

seconds が 0 の場合、保留中のアラーム要求があればキャンセルされます。

アラーム要求はスタックされません。この方法でスケジュールできる SIGALRM 生成は 1 つだけです。SIGALRM シグナルがまだ生成されていない場合、呼び出しにより、SIGALRM シグナルが生成される時刻が再スケジュールされます。

alarm() と setitimer()、ualarm()、または usleep() のいずれかとの間の相互作用は規定されていません。

したがって、アラームをキャンセルするには: alarm(0). サンプルコードにも存在します。

主な問題

ところで、ここで重要な部分が欠けています。

if(child == 0){ //Working in child
    if(-1 == execve(cmd,arg,env)){  //Execute program or error
        write(2, error_exe, sizeof(error_exe));
        _exit(EXIT_FAILURE);  // EXIT OR A FORKED SHELL WILL KEEP GOING
    }   
}else if(child != 0){   //Working in the parent
于 2012-04-19T23:51:20.217 に答える
1

システムコールはwait()引数を取ります。ソース ファイルの正しいヘッダーと、宣言されていない関数に対するコンパイラの警告 (できればエラー) を使用してコンパイルしないのはなぜですか? または、そのような警告が表示された場合は、StackOverflow などの場所でレビューのためにコードを送信する前に注意してください。

execve()(またはexec*()関数のいずれか)からの戻りステータスをテストする必要はありません。返された場合は失敗です。

失敗時にエラーを書くのは良いことです。while (1)子プロセスも終了した方が良いでしょう。そうすれば、入力データを求めてメイン シェルと競合してループに戻らないからです。

if (child == 0)
{
    execve(cmd, arg, env);
    write(2, error_exe, sizeof(error_exe));
    exit((errno == ENOEXEC) ? 126 : 127);
}

実際、あなたの問題の主な原因は、あなたの子供が出てこないことです。子が終了していないため、アラームが鳴るまで待機は戻りません。表示される終了ステータスは、POSIX シェル仕様に一致するように意図されています。

于 2012-04-20T00:10:16.333 に答える