실패한 파일 전송을 재개할 수 있는 프로그램은 데이터 추가를 시작할 위치를 어떻게 알 수 있습니까?

실패한 파일 전송을 재개할 수 있는 프로그램은 데이터 추가를 시작할 위치를 어떻게 알 수 있습니까?

일부 파일 복사 프로그램은 실패한 전송/복사를 복구 rsync할 수 있습니다 .curl

이러한 실패에는 여러 가지 원인이 있을 수 있으며 어떤 경우에는 프로그램이 "정리"할 수 있고 어떤 경우에는 그렇지 않을 수 있습니다.

이러한 프로그램이 다시 시작되면 성공적으로 전송된 파일/데이터의 크기를 계산한 다음 소스에서 다음 바이트를 읽고 파일 조각에 추가하기 시작하는 것처럼 보입니다.

예를 들어 대상에 "도착"하는 파일 조각의 크기는 1378바이트이므로 원본 파일의 1379바이트부터 읽어서 조각에 추가하면 됩니다.

내 질문은 바이트가 비트로 구성되어 있고 모든 파일이 데이터를 깨끗한 바이트 크기의 청크로 분할하는 것은 아니라는 사실을 알면서 이러한 프로그램이 데이터 추가를 시작하기로 선택한 지점이 올바른지 어떻게 알 수 있습니까?

대상 파일에 쓸 때 프로그램, 커널 또는 파일 시스템 수준에서 일종의 SQL 데이터베이스와 유사한 버퍼링 또는 "트랜잭션"이 발생하여 깨끗하고 올바른 형식의 바이트만 기본 블록 장치에 전달되도록 합니까?
아니면 프로그램에서 최신 바이트가 불완전할 수 있다고 가정하여 손상되었다고 가정하여 삭제하고 바이트를 다시 복사한 다음 거기에서 추가를 시작합니까?

모든 데이터가 바이트로 표시되는 것은 아니라는 사실을 알면 이러한 추측은 잘못된 것 같습니다.

이러한 프로그램이 "재개"되면 올바른 위치에서 시작되었는지 어떻게 알 수 있습니까?

답변1

명확성을 위해 실제 메커니즘은 더 나은 보안을 제공하기 위해 더 복잡합니다. 다음과 같은 디스크에 쓰기 작업을 상상할 수 있습니다.

  • 신청서 작성바이트(1)
  • 커널(및/또는 파일 시스템 IOSS)이 이를 버퍼링합니다.
  • 버퍼가 가득 차면플러시파일 시스템에:
    • 블록이 할당되었습니다(2)
    • 블록이 작성되었습니다. (3)
    • 파일 및 블록 정보 업데이트(4)

프로세스가 (1)에서 중단되면 디스크에는 아무것도 남지 않으며 파일은 그대로 유지되어 이전 블록에서 잘립니다. 5000바이트를 보내고 디스크에는 4096바이트만 있으며 오프셋 4096에서 전송을 다시 시작합니다.

(2)의 경우 메모리 외에는 아무 일도 일어나지 않습니다. (1)과 동일합니다. (3)의 경우 데이터가 기록됩니다.하지만 그걸 기억하는 사람은 아무도 없어. 9000바이트를 보냈고, 4096바이트가 기록되었으며, 4096바이트가 기록되었습니다.그리고 길을 잃었다, 나머지는 손실됩니다. 전송은 오프셋 4096에서 재개됩니다.

(4) 단계에 있다면 이제 데이터가 디스크에 커밋되어야 합니다. 스트림의 다음 바이트가 손실될 수 있습니다. 9000바이트를 보냈고 8192바이트가 기록되었으며 나머지는 손실되었으며 전송은 오프셋 8192에서 재개되었습니다.

이것은쉽게 한가져가다. 예를 들어 3~4단계의 각 "논리적" 쓰기는 "원자적" 쓰기가 아니지만 청크를 대상 장치(예: 하드 디스크)에 적합한 블록으로 세분화하는 또 다른 시퀀스(#5로 지정)를 생성합니다. )는 장치의 호스트 컨트롤러로 전송됩니다.캐싱 메커니즘도 있습니다., 최종적으로 디스크에 저장됩니다. 이 하위 시퀀스는 항상 시스템에서 완전히 제어할 수 있는 것은 아니므로 데이터를 하드 디스크로 보내는 것은 해당 데이터가 실제로 기록되었고 다시 읽을 수 있다는 것을 보장하지 않습니다.

여러 파일 시스템 구현일기를 쓰다, 가장 취약한 지점(4)이실제로취약한 메타데이터를 작성하면 짐작할 수 있듯이거래(5) 단계에서 무슨 일이 일어나더라도 일관되게 작동합니다.

트랜잭션 중에 시스템이 재설정되면 가장 최근의 전체 체크포인트로 되돌릴 수 있습니다. 작성된 데이터는 (1)과 마찬가지로 여전히 손실되지만 복구하면 이 문제가 해결됩니다. 아니요정보실제로 길을 잃었습니다.

답변2

rsync참고: 다른 파일 전송 유틸리티의 소스는 살펴보지 않았습니다 .

파일 끝으로 점프하여 해당 위치의 위치를 ​​바이트 단위로 가져오는 C 프로그램을 작성하는 것은 쉽습니다.

두 작업 모두 표준 C 라이브러리 함수에 대한 단일 호출로 수행됩니다.lseek()( lseek(fd, 0, SEEK_END)파일 설명자에 대해 열린 파일의 길이를 fd바이트 단위로 반환합니다).

lseek()대상 파일에 대해 이 작업이 수행되면 소스 파일에 대해 유사한 호출을 수행하여 적절한 위치로 이동할 수 있습니다. lseek(fd, pos, SEEK_SET)그런 다음 소스 파일의 이전 부분이 변경되지 않은 것으로 식별되었다고 가정합니다(다른 유틸리티에서는 이를 수행할 수 있음). 다른 방법으로) 해당 시점에서 전송을 계속할 수 있습니다.

파일은 다음과 같습니다.조각난하지만 파일 시스템은 애플리케이션이 파일을 연속된 바이트 시퀀스로 인식하도록 보장합니다.


주석의 비트 및 바이트에 대한 논의와 관련하여: 디스크에 쓸 수 있는 데이터의 가장 작은 단위는바이트. 바이트에는 최소한 하나의 바이트가 필요합니다.막힌디스크에 할당할 데이터입니다. 블록 크기는 파일 시스템 유형에 따라 다르며 관리자가 파일 시스템을 초기화할 때 사용하는 매개변수에 따라 달라질 수 있지만 일반적으로 범위는 512바이트에서 4KiB입니다. 쓰기는 커널, 기본 C 라이브러리 또는 애플리케이션 자체에 의해 버퍼링될 수 있으며 최적화를 위해 디스크에 대한 실제 쓰기는 적절한 블록 크기의 배수로 발생할 수 있습니다.

파일에 단일 비트를 쓰는 것은 불가능하며 쓰기 작업이 실패하면 파일에 "반쯤 쓰여진 바이트"가 남지 않습니다.

답변3

컬과 rsync와 같은 프로그램은 매우 다르기 때문에 기본적으로 두 가지 질문입니다.

컬과 같은 HTTP 클라이언트의 경우 현재 파일 크기를 확인한 다음 Content-Range요청과 함께 헤더를 보냅니다. 서버는 206(성공적으로) 대신 상태 코드(부분 콘텐츠) 가 포함된 파일 범위를 전송 200하고 다운로드를 재개하거나, 헤더를 무시하고 처음부터 시작하여 HTTP 클라이언트가 모든 것을 다시 다운로드할 수 밖에 없게 만듭니다.

또한 서버는 Content-Length헤더를 보낼 수도 있고 보내지 않을 수도 있습니다. 일부 다운로드에서는 백분율과 파일 크기가 표시되지 않는 것을 알 수 있습니다. 이러한 다운로드에서 서버는 클라이언트에게 길이를 알려주지 않으므로 클라이언트는 다운로드 양만 알고 후속 바이트 수는 알 수 없습니다.

Content-Range다음으로 시작하는 헤더를 사용하세요 .그리고일부 다운로드 관리자는 중지 지점을 사용하여 여러 소스에서 파일을 한 번에 다운로드하고, 각 미러 자체가 네트워크 연결보다 느린 경우 전송 속도를 높입니다.

반면에 rsync는 증분 파일 전송을 위한 고급 프로토콜입니다. 서버와 클라이언트에 있는 파일 부분의 체크섬을 생성하여 어떤 바이트가 동일한지 감지합니다. 그런 다음 차이점을 보냅니다. 즉, 다운로드를 재개할 수 있을 뿐만 아니라 파일을 다시 다운로드할 필요 없이 매우 큰 파일 중간에 몇 바이트를 변경하면 변경된 바이트도 다운로드할 수 있다는 의미입니다.

전송을 재개하기 위한 또 다른 프로토콜은 BitTorrent입니다. .torrent이 프로토콜에는 파일에 있는 블록의 체크섬 목록이 포함되어 있어 블록을 다른 소스에서 순서에 관계없이 병렬로 다운로드하고 확인할 수 있습니다.

rsync 및 bittorent는 디스크의 일부 데이터를 확인하지만 HTTP 다운로드를 재개하면 확인하지 않습니다. 따라서 일부 데이터가 손상된 것으로 의심되면 최종 파일의 체크섬을 사용하여 무결성을 확인해야 합니다. 그러나 단순히 다운로드를 중단하거나 네트워크 연결이 끊어지는 경우에는 일반적으로 일부 파일이 손상되지 않지만 전송 중 정전이 발생할 수 있습니다.

답변4

전송에 사용되는 프로토콜에 따라 다릅니다. 그러나 컬은 파일에 나타나는 순서대로 데이터를 순차적으로 전송하는 http를 사용합니다. 따라서 부분적으로 완료된 전송의 파일 크기에 따라 컬을 재개할 수 있습니다. 실제로 길이가 N인 파일을 생성하고 파일을 부분적으로 완료된 다운로드로 처리하도록 요청하여 첫 번째 N 바이트를 건너뛰도록 속일 수 있습니다(그런 다음 첫 번째 N 바이트를 삭제합니다).

관련 정보