1

私は約10bから16000bのチャンクでファイルに書き込んでいますが、突然すべてのチャンクが約4050バイト(具体的には、4050、4051、4074バイトの順)で切断されます。これは、後続の書き込みによって、書き込まれるはずのデータが上書きされ、データが台無しになることを意味します。4050b未満のチャンクはすべて正常に書き出されます。

残念ながら再現できません。私が持っているのはめちゃくちゃなファイルだけなので、これを引き起こす何かを探してデバッグしています。

デバッグすると、cのwrite()関数が内部で呼び出され(これはJavaコードのFileChannel.write()ですが、標準ライブラリはcのwriteを呼び出し、書き込まれたバイト数が0より大きいことのみをチェックします)、そのドキュメントが要求されたすべてのデータが書き出されることを保証するのではなく、書き込まれた量がわかるだけです。

私はJavaランドで書き戻されたバイトをチェックしません(しかし、私はそれを取得します、関数シグネチャはほとんど同じです)ので、修正は非常に簡単です。ただし、これを再現できないため、実際の問題を修正したかどうかはわかりません。したがって、私は、cの第一人者が、私がクラックを吸っている、またはwrite()が一度に約4050バイトを超えて書き込むことができない正当な状況があることを教えてくれることを望んでいます。

これは、64ビットLinuxカーネルバージョン3.0.0-26で実行されています。

編集:以下のコメントに従って展開するには:

通常のファイルシステムファイルに書き込んでいます。このコンテキストで非ブロッキングが何を意味するのかわかりません。コールバックなどを使用していませんが、OSにディスクにフラッシュするように明示的に指示することはチャンクごとに行われません。ファイルは、JavaのRandomAccessFile、「rw」モードを使用して開かれます。

4

3 に答える 3

5

差出人man 2 write

   The number of bytes written may be less than  count  if,  for  example,
   there  is  insufficient space on the underlying physical medium, or the
   RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)),  or  the
   call was interrupted by a signal handler after having written less than
   count bytes.  (See also pipe(7).)

差出人man 2 setrlimit

   RLIMIT_FSIZE
          The maximum size of files that the process may create.  Attempts
          to extend a file beyond this  limit  result  in  delivery  of  a
          SIGXFSZ  signal.   By default, this signal terminates a process,
          but a process can catch this signal instead, in which  case  the
          relevant  system  call  (e.g., write(2), truncate(2)) fails with
          the error EFBIG.

これらの制限は、次のコマンドを使用して確認できます。

ulimit -Sf
ulimit -Hf

または、このCプログラムを使用して:

#include <stdio.h>
#include <errno.h>
#include <sys/resource.h>

int main()
{
    struct rlimit rl;
    if (getrlimit(RLIMIT_FSIZE, &rl) == 0) {
        printf("%d %d\n", rl.rlim_cur, rl.rlim_max);
    } else {
        fprintf(stderr, "error: %d\n", errno);
    }
    return 0;
}
于 2012-10-09T08:34:29.147 に答える
4

Linuxプログラマーズマニュアルのwrite(1)について:「write()は ファイルに最大 カウントバイトを書き込みます...」

書き込まれる量は、何に書き込んでいるか、および同期書き込みを使用しているかどうかによって異なります。

たとえば、パイプまたはソケットの場合、パイプ/ソケットバッファがいっぱいになるまで書き込むことはできません(同期モードの場合:バッファで使用可能なものより多く)。

于 2012-10-09T08:36:56.067 に答える
2

問題を再現する最も簡単な方法は、消費者が遅いことです。これにより、write()を呼び出すと、送信バッファーがほぼいっぱいになります。つまり、指定したすべてのデータを書き込むことができるわけではありません。この問題をより明確にするために、送信バッファと受信バッファのサイズを減らすことができます。

于 2012-10-09T08:31:41.563 に答える