2013-07-02 17 views
10

read(またはwrite、またはその両方)を同じファイル記述子の2つの異なるスレッドで呼び出すとどうなりますか?ソケットファイルディスクリプタ)、明示的に同期メカニズムを使用しないでください。Cの読み取りとスレッドの安全性(Linux)

読み取りと書き込みはsyscallなので、単一のコアCPUでは、2つの読み取りが「同時に」実行されるのはおそらく不幸です。しかし、複数のコアを使用すると...

Linuxカーネルは何をしますか?

もう少し一般的です:他のカーネル(BSDなど)の動作は常に同じですか?

編集:close documentationによると、ファイルディスクリプタが他のスレッドのシステムコールで使用されていないことを確認する必要があります。したがって、ファイルディスクリプタを閉じる前に明示的な同期が必要であることを縫い合わせています(それを呼び出すスレッドがまだ実行中の場合は読み取り/書き込みが行われます)。

+2

同期メカニズムを使用することはできません。カーネルはすでにあなたのためにそれをしています。 –

+0

私は、明示的に使っています。だから、カーネルは自分自身で全仕事をしているし、両方の読み書き/呼び出しは明示的な同期を必要としない? –

+0

私が知る限り、はい。私は実際にはLinuxカーネルの専門家ではありませんが、そうでないとは想像できません。たぶん、より具体的な知識を持つ人が来るでしょう。 –

答えて

11

すべてのシステムレベル(syscall)ファイル記述子アクセスは、すべてのメインストリームのUNIXライクなOSでスレッドセーフです。 年齢にもよるが、必ずしも信号安全ではない。

read,write,acceptなどを2つの異なるタスクのファイル記述子で呼び出すと、カーネルの内部ロック機構によって競合が解決されます。

各バイトは読み取り専用ですが、書き込みは未定義の順序で行われます。

stdioライブラリ関数freadfwriteおよびco。また、デフォルトではコントロール構造上の内部ロックがありますが、フラグを使用することでそれを無効にすることは可能です。

+1

こんにちは。これらの関数をスレッドセーフとしてマークする公式の文書を投稿できますか? – felknight

+1

read/write/acceptとfread/fwriteの両方の公式文書へのリンクを追加できれば本当にうれしいです:) –

+0

libpthreadとリンクしていない限り、glibcはスレッドセーフでfread、fwriteでは安全でないと確信しています。もちろん、スレッドを使用している場合は、それはすでに正しいはずです。 –

0

結果は、その特定の瞬間にスレッドがどのように実行されるかによって異なります。

マルチスレッドで未定義の動作を回避する方法の1つは、メモリ操作を行っていると想定することです。例えば。リンクリストの更新や変数の変更など。

mutex/semaphores/lockなどの同期メカニズムを使用する場合は、意図した通りに動作するはずです。

2

closeについてのコメントは、他のスレッドがファイルディスクリプタを使用しようとしている状況で、ファイルディスクリプタを閉じるのには意味がないためです。したがって、カーネルに関する限り安全ですが、コーナーケースを診断するのは奇妙で困難です。

2番目のスレッドが読み込みを試みているときにスレッドがファイルディスクリプタを閉じると、2番目のスレッドで予期しないEBADFエラーが発生することがあります。さらに悪いことに、3番目のスレッドが新しいファイルを同時に開いていると、同じfdを再割り当てして2番目のスレッドが誤って新しいファイルを読み込んでしまう可能性があります...

1

あなたの足跡に従う人

ミューテックスセマフォでファイル記述子を保護することは、完全に正常です。カーネルの動作に依存することがなくなり、メッセージの境界が確実になります。あなたはなぜミューテックスが必要でないのかを説明する15,489行のマンページの最後の段落を引用する必要はありません(私は誇張していますが、私の意味がわかります)

また、ファイルディスクリプタが複数のスレッドによって使用されていることを示すコード。

フリンジベネフィット

そのようミューテックスを使用する付加給付があります。異なるスレッドから異なるメッセージが来ているとし、それらのメッセージのいくつかが他のスレッドよりも重要であるとします。スレッドの優先度を設定して、メッセージの重要度を反映させるだけです。そうすれば、OSは、あなたのメッセージを最小限の労力で重要度の順に送信するようにします。