무제한 스트림을 파일에 저장하는 방법은 무엇입니까?

무제한 스트림을 파일에 저장하는 방법은 무엇입니까?
  • /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으로 지워지고 전체 파일 시스템 블록이 파일에서 제거됩니다. 호출이 성공한 후 이 범위에서 후속 읽기를 수행하면 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()충분히 큰 덩어리입니다.

관련 정보