2012-12-28 12 views
10

イベントを待つCでプログラムを書いてから、system()関数で外部システムコマンドを実行しました。Cで高速プロデューサ/スローコンシューマ

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

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

だから私は別のプログラムに、非常に重いですsystem機能を、移動することを決めた、だから私は、次のように私のプログラムを変更:

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

と、別のプログラムを書いた:

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

をが、プロデューサー(第1プログラム)が消費者(第2プログラム)よりも速く書くと、消費者はいくらかのデータを逃してしまいます。

この問題を解決する方法はありますか?

+4

スレッドを使用してイベントをキャプチャし、キューに追加し、コンシューマにキューからプルします。 – Falmarri

+0

複数のスレッドを使用して、プロデューサをシングルスレッドにしたまま消費者の負担を軽減することは可能ですか?確かに、それは失われつつある戦いですが、あなたの要件を満たせばあなたを救うのに十分かもしれません。余分なスレッドが余りにも多くなりすぎても、データストアを調べる必要があります。 – pickypg

+0

パイプをどのようにセットアップしますか?もちろん、処理できるデータよりも多くのデータを継続的に取得すると、何かが「与える」ことになります。しかし、パイプを使って大量のデータをゆっくりと処理することは全く可能です。さもなければ、 'cat myprog.c | gcc -o myprog'を実行することはできません - 時にはgccがかなり遅くなるので、catはできるだけ早くパイプにプッシュします。 –

答えて

8

あなたは、あなたがpopen(3)呼び出しでsystem(3)呼び出しを置き換えることを除いて、第2のプログラムを呼び出す—単一のプログラムで元の形—にコードを返す必要があります。これで呼び出しプログラムは、外部プログラムからの行を読み取ってイベント検査の呼び出しをインターリーブすることができます。

Unixパイプメカニズムは、パイプがいっぱいになったときに速いプロデューサが書き込み中に待機するようにします。それは決しては、呼び出し元のプログラムをブロックすることができるように

はまた、外部プログラムの非同期の読み取りを行うためにselect(2)またはpoll(2)と組み合わせfileno(3)機能、に見たいと思うかもしれません。

+0

お返事ありがとうございます。私はLinuxでのCプログラミングに精通していません。サンプルコードを教えてください。ありがとう – Maryam

+0

うわー!それは魅力のように動作します!ありがとう – Maryam

+0

あなたは本当にこのトピックに関する本の1つを得るべきです。ピース単位で学習するのはポイントがありますが、ピックアップする必要のあるゲシュタルトがあります。短期間に多くのことを学ぶだけです。 W. Richard Stevensの* Unix Env​​ironment * 2/eの* Advanced Programmingをお勧めします。他にもそのような本があります。この本の時代には消されないでください。現代のLinuxプログラミングでは初版でさえも95%の有用性があります。カーネルAPIとC標準ライブラリは、その時代にそれほど変わっていません。 –

2

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

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

+0

いいえ、イベントにはいくつかの重要なデータがあり、処理して別の場所に保存する必要があります。 – Maryam

2

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

おそらくイベントループが必要です。 poll(2) syscall(または、のようなイベントループライブラリのpollを使用することもできます)。

コーディングする前に良いadvanced linux programming bookを読むことを強くお勧めします。