0

メインプロセスが互いに協力する4つの子プロセスにフォークするプログラムがあります:

process0 は FIFO ファイル (O_WRONLY) を開き、読み取り関数を使用して STDIN から一度に 1 バイトを読み取り、書き込みを使用して FIFO に書き込み、FIFO ファイルを閉じます。

プロセス1は共有メモリが空になるのを待っています(共有メモリテーブルif(tab [0] == 0)の最初のバイトを使用して空かどうかを確認しています)FIFOファイル(O_RDONLY)を開き、そこから読み取り、これを変換します1 バイトを 16 進数に変換し、共有メモリに保存します。次に、fifo をクローズし、共有メモリ テーブルであるタブ [0] を 1 に設定します。

タブ[0] == 1の場合、プロセス2は共有メモリから読み取ります。読み取り後、パイプにデータを書き込みます

process3 はパイプから読み取り、STDIN に書き込みます

これはすべて完璧に機能します。問題は、信号を追加したいときに始まりました。セマフォを使用して p0 と p1 を同期し、シグナルを使用して p1 と p2 を同期し、メッセージ キューを使用して p2 と p3 を同期しています。たとえば、プロセス1がスリープモードになっている場合を除いて、正常に動作します。fifoから読み取りたいときにこのモードに入り、データが転送されるのを待つ必要があります..と思います。私はそれについて読んでいます。

プロセス階層

原因と思われるものを以下に示します。

「プロセスがユーザー モードでシステム コールを行うと (1)、プロセスは状態 2 に移行し、カーネル モードでの実行が開始されます。この時点で、行われたシステム コールがハードディスク上のファイルを読み取るためのものであると仮定します。読み取りがすぐに実行されない場合、プロセスはスリープ状態になり、システムがディスクを読み取り、データの準備ができたというイベントを待ちます. 現在、状態 4 です. データの準備ができている場合、プロセスは目覚めます. このすぐに実行されるという意味ではなく、メイン メモリで再び実行する準備ができていることを意味します (3)。」

私はそれを理解していると思いますが、どうすればこれを回避できますか?プログラムが常にシグナルに反応するようにします。「kill」を介してシグナルを送信したときに、プロセスの状態をスリープから実行に変更する方法はありますか? 「システムがディスクを読み取り、データの準備ができたというイベントを待機する」ことを停止するようにプロセスに指示できますか?

誰かが見たい場合の私のコードは次のとおりです。

プログラムのコード

4

2 に答える 2

1

私があなたの質問を正しく理解していれば、プロセス 1 は 442 行目 (ソース) でハングアップしており、シグナルに応答していませんread

明らかな答えは、ブロッキングをしないことread()です。記述子をチェックして、読み取るものがあるかどうかを確認し、ない場合は次に進みます。fcntl/を読んioctlで、ノンブロッキング読み取りを行う方法を確認してください。

于 2012-09-17T14:22:45.443 に答える
1

あなたの観察では、(ほとんどの) システム コールは、シグナルが発生した場合にデフォルトで再起動する可能性があります。簡単に言うと、システム コールでスタックしているコードは、シグナルが配信されるとユーザー空間に復帰しますが、シグナル ハンドラが実行された後にシステム コールを再開します。

signal() 関数の代わりにsigaction () を使用してシグナル ハンドラーを確立すると、システム コールはシグナルがキャッチされたときに再起動せず、失敗して errno を EINTR に設定します。つまり、シグナルが配信されたためにシステムコールがどこでも「失敗」する可能性があるという事実を処理する必要があります。

(デフォルトでは、signal() は Linux の再起動時にシステム コールを引き起こします。これは、signal.h ヘッダーを含める前に、いくつかの機能マクロによって制御できます。sigaction() によってシステム コールが再起動されるかどうかは、シグナルを確立するときにフラグ SA_RESTART によって制御されます。ハンドラ)

于 2012-09-17T14:33:37.130 に答える