5

wait()ビジー待機またはビジースリープループを使用する以外に、システムコールをタイムアウトで使用する方法はありますか?

forkそれ自体とexec子の実行可能ファイルである親プロセスがあります。次に、子が終了するのを待ち、適切な手段で出力を取得して、さらに処理を実行します。プロセスが一定時間内に終了しない場合は、実行がタイムアウトしたと見なされ、別の処理が実行されます。残念ながら、問題の性質上、このタイムアウト検出は必要です。

4

3 に答える 3

6

タイムアウトを取る待機呼び出しはありません。

代わりにできることは、SIGCHLD のフラグを設定するシグナル ハンドラーをインストールし、select() を使用してタイムアウトを実装することです。select() はシグナルによって中断されます。

static volatile int punt;
static void sig_handler(int sig)
{
    punt = 1;
}

...

struct timeval timeout = {10,0};
int rc;

signal(SIGCHLD, sig_handler);

fork/exec stuff
//select will get interrupted by a signal

rc = select(0, NULL,NULL,NULL, &timeout ); 
if (rc == 0) {
// timed out
} else if (punt) {
    //child terminated
}

ただし、処理する必要がある他の信号がある場合は、さらにロジックが必要です

于 2013-08-27T22:11:04.610 に答える
4

オプション、スリープとwaitpid併用できます。WNOHANG

while(waitpid(pid, &status, WNOHANG) == 0) {
    sleep(1);
}

しかし、これはアクティブな睡眠になります。ただし、このwaitタイプの関数を使用する方法は他にありません。

于 2013-08-27T21:59:41.197 に答える
3

Linux では、 を使用してこの問題を解決することもできますsignalfdsignalfd基本的に一連のシグナルを受け取り、読み取り可能な fd を作成します。読み取った各ブロックは、発火したシグナルに対応しています。(これらのシグナルが実際に送信されないように、これらのシグナルを sigprocmask でブロックする必要があります。)

の利点は、 、、またはでsignalfdfd を使用できることです。これらはすべてタイムアウトを許可し、他のものも待機できるようにします。selectpollepoll

1 つの注意: 対応する信号struct signalfd_siginfoが読み取られる前に同じ信号が 2 回発火した場合、1 つの通知しか受信しません。したがって、指示を取得したら、-1 が返されるまで繰り返すSIGCHLD必要があります。waitpid(-1, &status, &WNOHANG)

FreeBSD では、 との typeを使用kqueueして、より直接的に同じ効果を得ることができます。(SIGCHLD イベントを kqueue することもできますが、EVFILT_PROC を使用すると、すべての子に対してグローバルにではなく、子 pid でイベントを指定できます。) これは Mac OS X でも動作するはずですが、試したことはありません。keventEVFILT_PROC

于 2013-08-27T23:40:49.637 に答える