10

イベントを待機し、system()関数ごとに外部システムコマンドを実行するプログラムをCで作成しました。

while( true ){
    wait_for_event();
    system("cmd");
}

私はこれに重大な問題を抱えています。これcmdは重いコマンドであり、完了するまでに数秒かかります。私のアプリはこの時間枠内のいくつかのイベントを見逃しています。

そこで、非常に重い関数を別のプログラムに移動することにしましたsystem。そこで、プログラムを次のように変更しました。

while( true ){
    wait_for_event();
    write_to_fifo("cmd");
}

そして別のプログラムを書きました:

while(true){
    system(read_from_pipe());
}

しかし、プロデューサー(1番目のプログラム)がコンシューマー(2番目のプログラム)よりも速く書き込む場合、コンシューマーは一部のデータを見逃すため、役に立ちません。

この問題を処理する方法はありますか?

4

3 に答える 3

8

system(3)呼び出しを呼び出しに置き換えることを除いて、コードを元の形式(つまり、2番目のプログラムを呼び出す単一のプログラム)に戻す必要がありpopen(3)ます。これで、呼び出し側プログラムは、外部プログラムからの読み取り行を使用して、イベントチェックの呼び出しをインターリーブできます。

Unixパイプメカニズムにより、低速のコンシューマーにより、高速のプロデューサーがパイプがいっぱいになったときに書き込みを待機するようになります。

また、外部プログラムからの読み取りを非同期にするために、またはそれfileno(3)と組み合わせて関数を調べて、呼び出し元のプログラムをブロックしないようにすることもできます。select(2)poll(2)

于 2012-12-28T23:19:58.900 に答える
2

fork(2)execve(2)waitpid(2)、そしておそらくpipe(2)dup2(2)、その他のシステムコールを使用して、外部プログラムを明示的に開始できます。

おそらくイベントループが必要です。poll(2)システムコール(または、を使用するlibevのようなイベントループライブラリ)を使用できpollます。

コーディングする前に、優れた高度なLinuxプログラミングの本を読むのに何時間もかかることを強くお勧めします。

于 2012-12-29T08:30:32.377 に答える
2

イベントの数だけが必要な場合は、グローバルカウンターを使用できます。競合状態を回避するために、代わりにセマフォを使用する必要がある場合があります。もちろん、2つのスレッドが必要になります。

イベントには重要なものが含まれているため、リスト(または十分な数のスロットを持つ配列)を使用して着信データを格納できます。ミューテックスを使用して、このリストを保護できます。

于 2012-12-28T23:19:18.437 に答える