write()
はスレッドセーフです(実装上のバグはありません...)。 Per the POSIX write()
standard(強調鉱山): 。
The write()
function shall attempt to writenbyte
bytes from the buffer pointed to by buf
to the file associated with the open file descriptor, fildes
.
...
RETURN VALUE
Upon successful completion, these functions shall return the number of bytes actually written ...
ありますが、部分的write()
を取得しないという保証はありませんので、個々のwrite()
呼び出しがアトミックであったとしても、それは必ずしも完全ではありませんので、それはそれ以上かかることがありますので、あなたはまだインターリーブされたデータを得ることができますすべてのデータを完全に書き込むには、write()
への1回の呼び出しよりも時間がかかります。
write()
コールが比較的小さい場合は、部分的にwrite()
が表示されることはほとんどありません。「小さい」と「可能性があります」の値は実装によって異なります。ログエントリその後、write()
1回のコールでエントリ全体を構築する -
は私が日常のロギングのパフォーマンスを改善するためにO_APPEND
で開いた定期的なファイルのロックを解除単一write()
呼び出しを使用するコードを届けてきました。私はを一度も受け取りませんは、多くのプロセスが同じログファイルに書き込む場合でも、LinuxシステムとSolarisシステムでほぼ2〜30年にわたって部分的またはインタリーブされた結果です。しかしもう一度、それはテキストログファイルであり、部分的またはインターリーブされたwrite()
が行われた場合、実際にダメージを与えたり、データを失ったりすることはありません。
しかし、この場合、カーネル構造にいくつかのバイトを「書いています」。あなたはIllumos.orgのSolaris /dev/poll
カーネルドライバのソースコードを掘り下げ、write()
部分の可能性を確認することができます。私はそれが事実上不可能だと思うだろう - 私はちょうど戻って、私が10年前に私の会社のソフトウェアライブラリのために書いたマルチプラットフォームのポールクラスを見た。 Solarisでは、複数のスレッドから/dev/poll
を呼び出し、ロックを解除したwrite()
を呼び出します。そして、それは十年のために正常に動作しています...
のSolarisの/ dev /プールデバイスドライバのソースコードの解析
(オープン)、Solarisのソースコードはここで見つけることができます:http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/io/devpoll.c#628
dpwrite()
関数は実際に "書き込み"操作を実行する/dev/poll
ドライバのコードです。実際には書き込み操作ではないので、引用符を使用します。データが、ポーリングされているファイル記述子のセットを表すカーネルのデータが更新された分だけ転送されるわけではありません。
データは、ユーザ空間からカーネル空間にコピーされ、kmem_alloc()
で得られたメモリバッファにコピーされます。私は部分的なコピーになる可能性のある方法は見当たりません。割り当てが成功したかどうか。カーネル構造へのアクセスを排他的にwrite()
待つので、何かをする前にコードが中断することがあります。その後
は、最後のリターンコールが終わりにある - とエラーがない場合は、全体の呼び出しが成功したとマークされ、または全体の呼び出しがエラーで失敗:
995 if (error == 0) {
996 /*
997 * The state of uio_resid is updated only after the pollcache
998 * is successfully modified.
999 */
1000 uioskip(uiop, copysize);
1001 }
1002 return (error);
1003}
は、Solarisを通して掘る場合カーネルコードを使用すると、成功した呼び出しの後にwrite()
によって返される値になるのはuio_resid
です。
したがって、呼び出しは確かにすべてかどうかのようです。複数のディスクリプタが渡されたときに、以前のディスクリプタを正常に処理した後、コードがファイルディスクリプタにエラーを返す方法があるようですが、コードは部分的な成功指示を返すようには見えません。
一度に1つのファイル記述子しか処理していない場合、/dev/poll
write()操作は完全にスレッドセーフで、複数のファイル記述子への更新を「書き込み」するのはスレッドセーフです。運転手が部分的な結果を返す明白な方法はありませんwrite()
私はあなた自身の同期を行う必要があると確信しています。マルチスレッドアプリケーションでのI/Oの経験は、I/Oがスレッドセーフではないということです。 http://stackoverflow.com/questions/19974548/are-functions-in-the-c-standard-library-thread-safeにはスレッドセーフとC標準ライブラリについての議論がありますが、 'write()'については触れません。具体的には、この記事、write()、スレッドの安全性、POSIXのhttps://lwn.net/Articles/180387/ –
'write()'はスレッドセーフです。しかし、同じファイル記述子への複数のスレッドからの 'write()'の同時実行が原子的であるかどうかは別の問題です。ファイルの各部分を区切る 'pwrite()'はおそらく 'writev()'です。 – EOF
'write()'はPOSIXのリストの中にあります。「2つのスレッドがそれぞれこれらの関数の1つを呼び出すと、それぞれの呼び出しは、他の呼び出しの指定されたすべての効果を見るか、どちらも表示されません。 http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_07 –