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/null
GNU 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
할 수 피할 다른 모든 경우에.