출력 파일이 / dev / null 일 때 tar가 파일 내용을 건너 뛰는 이유는 무엇입니까? 읽을 수 있는지 확인하고 싶었다

400 GiB 이상의 데이터가있는 디렉토리가 있습니다. 내가 생각하는 간단한 방법은이었다, 그래서 모든 파일이 오류없이 읽을 수 있는지 확인하고 싶었다 tar/dev/null. 그러나 대신 다음과 같은 동작이 나타납니다.

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

위의 세 번째 명령은 이미 오랫동안 실행 된 후 Ctrl+에 의해 강제로 중지되었습니다 C. 또한 처음 두 명령이 작동하는 동안 포함 된 저장 장치의 활동 표시기 .는 거의 항상 유휴 상태였습니다. 세 번째 명령으로 표시등이 계속 켜져있어 매우 바쁩니다.

따라서 tar출력 파일이임을 알 수있을 때 /dev/null, 즉 /dev/null파일 핸들을 tar쓰기 위해 직접 열면 파일 본문이 건너 뛴 것처럼 보입니다. ( v옵션을 추가 tar하면 디렉토리에있는 모든 파일이 tar‘빨간색’으로 인쇄됩니다 .)

그래서 왜 이것이 그렇게 궁금합니까? 그것은 일종의 최적화입니까? 그렇다면 왜 tar그런 특별한 경우에 대해 모호한 최적화를 원할까요?

Linux 4.14.105 amd64에서 glibc 2.27과 함께 GNU tar 1.26을 사용하고 있습니다.



답변

그것은 이다 문서화 된 최적화 :

에 아카이브를 만들 때 /dev/nullGNU tar는 입력 및 출력 작업을 최소화하려고합니다. GNU tar와 함께 사용되는 Amanda 백업 시스템에는이 기능을 사용하는 초기 크기 조정 단계가 있습니다.


답변

이것은 다양한 프로그램에서 발생할 수 있습니다 cp file /dev/null. 내 디스크 읽기 속도를 추정하는 대신 몇 밀리 초 후에 명령이 리턴되었습니다.

내가 기억하는 한, 그것은 Solaris 또는 AIX에 있었지만 원칙은 모든 종류의 유닉스 시스템에 적용됩니다.

옛날에는 프로그램이 파일을 어딘가에 복사 할 때 read디스크 (또는 파일 설명자가 참조하는 모든 것)에서 메모리로 데이터를 가져 오는 호출 (메모리가 read반환 될 때 모든 것이 보장됨 )과 write호출 사이에서 번갈아 나타납니다 (메모리 청크를 가져 와서 내용을 대상으로 보냅니다).

그러나 동일한 방법으로 달성 할 수있는 두 가지 새로운 방법이 있습니다.

  • Linux에는 시스템 호출 copy_file_range(다른 유닉스에 이식 가능하지 않음) 및 sendfile(휴대용; 원래 파일을 네트워크로 보내려고하지만 현재 모든 대상을 사용할 수 있음)이 있습니다. 전송을 최적화하기위한 것입니다. 프로그램이 그 중 하나를 사용하면 커널이 대상을 인식 /dev/null하고 시스템 호출을 no-op로 바꿉니다.

  • 프로그램은 mmap대신 파일 내용을 가져 오는 데 사용할 수 있습니다 read. 이는 기본적으로 “시스템 호출이 반환 될 때 데이터가 있는지 확인하십시오”대신 “메모리에 액세스하려고 할 때 데이터가 있는지 확인하십시오”를 의미합니다. 따라서 프로그램은 mmap소스 파일을 생성 한 다음 write매핑 된 메모리 청크 를 호출 할 수 있습니다 . 그러나 쓰기 /dev/null가 쓰여진 데이터에 액세스 할 필요가 없으므로 “있는지 확인”조건이 트리거되지 않으므로 파일을 읽을 수 없습니다.

gnu tar가 쓰기를 감지 할 때이 두 가지 메커니즘 중 어떤 메커니즘을 사용하는지 확실하지 /dev/null않지만, 읽기 속도를 검사하는 데 사용되는 프로그램 이 | cat > /dev/null대신 실행 되어야하는 > /dev/null이유입니다. | cat > /dev/null할 수 피할 다른 모든 경우에.


답변