無制限のストリームをファイルに保存する方法は?

無制限のストリームをファイルに保存する方法は?
  • /dev/randomバイナリデータストリーム(例:など)があるとします/dev/zero
  • 最大Nサイズのファイルがあります。
  • Nの単位はギガバイトです。

お持ちですか?エレガントなものは何でもこれを達成するためのLinuxの方法/技術/ハッキング文書連続書き込みの長さは最大Nバイトで、常に最後に書き込んだデータのみ(順番に)含まれますか?これは大きな移動(ファイルからファイルへ、メモリからファイルへ)がなく、最後/最初のデータブロックへの小さな調整のみを意味します。

私が探している秘訣は、ファイルが前方に移動し始めて、古すぎる(ファイルサイズがN以上に増加する)、つまりコンテンツの回転を効果的に忘れてしまうことです。

期待の原理は次のように表現することができる。

inp = fopen(stream, "r");
out = fopen(file, "wN"); // "Special open" with maximal size of N

while (is_reading)
{        
    if (rd = fread(buff, block_size, 1, inp))
    {
        fwrite(buff, rd, 1, out); // Old content forgotten
        fflush(out);              // Allow others to instantly see the current content
    }
}

fclose(inp);
fclose(out);

答え1

Linuxでは、次のものを使用できます。fallocate()ファイルの先頭からデータの割り当てを取り消します。

ファイルスペースの割り当て解除

モードでFALLOC_FL_PUNCH_HOLEフラグ(Linux 2.6.38以降で使用可能)を指定すると、オフセットから始まりlenバイトまで続くバイト範囲でスペースが確保されます(たとえば、穴の作成)。指定された範囲内で、一部のファイルシステムブロックがゼロにクリアされ、ファイルシステムブロック全体がファイルから削除されます。呼び出しが成功した後にこの範囲で後続の読み取りを実行すると、0が返されます。

...

これにより、報告されたファイルサイズなどは変更されませんが、次lsstat理由で物理ディスクの使用量が減少します。ファイルがまれになります。。ファイルの「穴」から読み取ろうとする試みはまだ成功し、0読み込みプロセスに埋められたバイトを返します。

このような:

size_t maxSize = 512UL * 1024UL * 1024UL;
char buffer[ 8 * 1024 ];
struct stat sb;
int in = open( inputFile, O_RDONLY );
int out = open( outputFile, O_WRONLY | O_CREAT | O_APPEND, 0644 );
fstat( out, &sb );
size_t fileSize = sb.st_size;

for ( ;; )
{
    ssize_t bytesRead = read( in, buffer, sizeof( buffer ) );
    if ( bytesRead < 0 )
    {
        break;
    }

    ssize_t bytesWritten = write( out, buffer, bytesRead );
    if ( bytesWritten < 0 )
    {
        break;
    }

    fileSize += bytesWritten;

    if ( fileSize > maxSize )
    {
        fsync( out );
        off_t endOfHole = fileSize - maxSize;
        fallocate( out, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
            0UL, endOfHole );
    }
}

XFS、BTRFS、EXT4、および tmpfs でのみサポートされます。

さらに、より多くのエラーチェックが必要であり、そのままコンパイルされない可能性があります。また、最大サイズに達すると、fallocate()毎回read()/write()サイクルを呼び出し、毎回ファイルの先頭から「穴」を開けるので、非常に非効率的です。

このIOモードにバッファリングされた/を使用することもfread()意味がありません。fwrite()ただread()/write()十分に大きな塊です。

関連情報