Linux에서 cp
또는 명령과 같은 명령이 완료 dd
되었다고해서 데이터가 장치에 기록 된 것은 아닙니다. 예를 들어, sync
드라이브에서 "안전하게 제거"또는 "꺼내기"기능을 호출하거나 호출해야합니다.
그러한 접근 방식의 철학은 무엇입니까? 왜 한 번에 데이터가 기록되지 않습니까? I / O 오류로 인해 쓰기가 실패 할 위험이 있습니까?
Linux에서 cp
또는 명령과 같은 명령이 완료 dd
되었다고해서 데이터가 장치에 기록 된 것은 아닙니다. 예를 들어, sync
드라이브에서 "안전하게 제거"또는 "꺼내기"기능을 호출하거나 호출해야합니다.
그러한 접근 방식의 철학은 무엇입니까? 왜 한 번에 데이터가 기록되지 않습니까? I / O 오류로 인해 쓰기가 실패 할 위험이 있습니까?
답변:
그러한 접근 방식의 철학은 무엇입니까?
효율성 (디스크 특성을보다 잘 사용함) 및 성능 (쓰기 후 즉시 응용 프로그램을 계속 사용할 수 있음).
왜 한 번에 데이터가 기록되지 않습니까?
주요 이점은 OS가 연속적인 쓰기 작업을 자유롭게 재정렬하고 병합하여 대역폭 사용을 개선 할 수 있다는 것입니다 (작업이 적고 탐색이 적음). 응용 프로그램에 많은 수의 작은 작업이 필요한 경향이있는 반면, 적은 수의 큰 작업이 요청되면 하드 디스크의 성능이 향상됩니다. 또 다른 명확한 최적화는 OS가 동일한 블록을 짧은 시간에 여러 번 쓸 때 마지막 쓰기를 제외한 모든 쓰기를 제거하거나 영향을받는 파일이 그 동안 제거 된 경우 일부 쓰기를 모두 제거 할 수 있다는 것입니다.
이 비동기 쓰기가 완료 후write
시스템 호출이 돌아왔다. 이것이 두 번째로 가장 눈에 띄는 장점입니다. 비동기 쓰기는 데이터가 실제로 디스크에있을 때까지 기다리지 않고 작업을 계속할 수 있으므로 응용 프로그램의 속도를 높입니다. 동일한 종류의 버퍼링 / 캐싱도 최근 또는 자주 읽은 블록이 디스크에서 다시 읽히지 않고 메모리에 유지되는 읽기 작업에 대해서도 구현됩니다.
IO 오류로 인해 쓰기가 실패 할 위험이 있습니까?
반드시 그런 것은 아닙니다. 사용 된 파일 시스템과 중복성에 따라 다릅니다. 데이터를 다른 곳에 저장할 수 있으면 I / O 오류는 무해 할 수 있습니다. ZFS와 같은 최신 파일 시스템은 불량 디스크 블록을 자체 치료합니다. 또한 I / O 오류는 최신 OS와 충돌하지 않습니다. 데이터 액세스 중에 발생하면 영향을받는 응용 프로그램에보고됩니다. 구조적 메타 데이터 액세스 중에 파일 시스템이 위험에 처해 파일 시스템이 위험에 노출되면 읽기 전용으로 다시 마운트되거나 액세스 할 수 없게됩니다.
OS 충돌, 정전 또는 하드웨어 오류가 발생할 경우 약간의 데이터 손실 위험이 있습니다. 이것이 데이터가 디스크에 있는지 100 % 확신해야하는 응용 프로그램 (예 : 데이터베이스 / 금융 응용 프로그램)이 덜 효율적이지만보다 안전한 동기 쓰기를 수행하는 이유입니다. 성능 영향을 완화하기 위해 많은 응용 프로그램은 여전히 비동기 쓰기를 사용하지만 사용자가 명시 적으로 파일 (예 : vim, 워드 프로세서)을 저장할 때 동기화 쓰기를 사용합니다.
반면에, 대부분의 사용자와 응용 프로그램은 동기 쓰기가 제공하는 안전성을 필요로하거나 신경 쓸 필요가 없습니다. 충돌이나 정전이 발생하면 마지막 30 초 동안 최악의 데이터가 손실 될 수 있습니다. 시간이 30 초 이상 걸리는 금융 거래 나 이와 유사한 것이 없다면 (비 현상이 아니라 실제적인) 비동기식 쓰기의 큰 이득은 위험을 크게 능가합니다.
마지막으로 동기 쓰기는 데이터 쓰기를 보호하기에 충분하지 않습니다. 응용 프로그램에서 데이터가 손실되지 않도록 반드시 확인해야하는 경우 화재, 홍수 등과 같은 재해에 대비하기 위해 여러 디스크 및 여러 지리적 위치에 데이터 복제를 수행해야합니다.
쓰기가 완료 될 때까지 실제로 기다릴 필요가없는 프로그램에 속도의 환상을 제공합니다. 파일 시스템을 동기화 모드로 마운트하면 (즉석 쓰기 기능이 제공됨) 모든 것이 느리게 진행됩니다.
때때로 파일은 일시적으로 만 존재합니다 ... 프로그램은 약간의 작업을 수행하고 작업이 완료된 직후 파일을 삭제합니다. 당신이 그 글을 연기했다면, 처음에 글을 쓰지 않은 채 도망 칠 수도 있습니다.
IO 오류로 인해 쓰기가 실패 할 위험이 있습니까?
아 절대적으로 이 경우 일반적으로 전체 파일 시스템이 읽기 전용 모드가되고 모든 것이 끔찍합니다. 그러나 일반적으로 성능상의 이점을 잃어 버리는 데는 아무런 의미가 없습니다.
리눅스 이전과 심지어 유닉스 이전에도 비동기식 버퍼 I / O가 사용되었다. 유닉스는 그것을 가지고 있었고 모든 파생물을 가지고 있습니다.
다음은 Ritchie와 Thompson이 CACM 백서 인 UNIX 시간 공유 시스템에 작성한 내용입니다 .
사용자에게는 파일 읽기와 쓰기가 모두 동 기적이며 버퍼되지 않은 것으로 보입니다. 즉, 읽기 호출에서 복귀 한 직후에 데이터를 사용할 수 있으며 반대로 쓰기 후 사용자의 작업 공간을 재사용 할 수 있습니다. 실제로 시스템은 파일에 액세스하는 데 필요한 I / O 작업 수를 크게 줄이는 다소 복잡한 버퍼링 메커니즘을 유지 관리합니다.
귀하의 질문에, 당신은 또한 썼습니다 :
IO 오류로 인해 쓰기가 실패 할 위험이 있습니까?
예, 쓰기에 실패 할 수 있으며 프로그램에서 알지 못할 수도 있습니다. 결코 좋은 일은 아니지만, I / O 오류로 인해 시스템 패닉이 발생하는 경우에는 이로 인한 영향을 최소화 할 수 있습니다 (일부 OS에서는 패키징 대신 시스템을 계속 실행할 수는 있지만 영향을받는 파일 시스템은 마운트 해제 또는 마운트 된 읽기 전용). 그런 다음 해당 파일 시스템의 데이터가 의심스러운 것으로 사용자에게 알릴 수 있습니다. 그리고 디스크 드라이브를 사전에 모니터링하여 증가 된 결함 목록 이 빠르게 증가하고 있는지 확인할 수 있으며 이는 드라이브가 실패했음을 나타냅니다.
BSD는 fsync
시스템 호출을 추가하여 프로그램이 진행하기 전에 파일 데이터가 디스크에 완전히 기록되었는지 확인할 수 있었고 후속 Unix 시스템은 동기 쓰기를 수행하는 옵션을 제공했습니다. GNU dd에는 conv=fsync
명령이 종료되기 전에 모든 데이터가 기록되도록 하는 옵션 이 있습니다. 버퍼링 된 데이터를 기록하는 데 몇 분이 걸릴 수있는 느린 이동식 플래시 드라이브에 쓸 때 유용합니다.
파일 손상의 또 다른 원인은 갑작스러운 시스템 종료 (예 : 전원 손실)입니다. 사실상 모든 현재 시스템 은 파일 시스템에서 clean / dirty 플래그를 지원합니다 . 쓸 데이터가 더 이상없고 일반적으로 시스템이 종료되는 동안 또는 수동으로 호출하여 파일 시스템을 마운트 해제하려고하면 플래그가 정리 되도록 설정됩니다 umount
. fsck
파일 시스템이 완전히 종료되지 않은 것을 감지하면 시스템은 일반적 으로 재부팅시 실행 됩니다.
많은 좋은 답변이지만 다른 것을 추가하겠습니다. 유닉스는 다중 프로세스 및 다중 사용자 시스템이므로 잠재적으로 많은 사용자가 (거의) 파일 작업을 수행하려고 할 것입니다. 같은 시간. 네트워크에 마운트 된 오래된 느린 하드 디스크를 사용하면 시간이 오래 걸리고 (기본적으로 프로그램이 잠기고 사용자가 기다려야 함), 읽기 / 쓰기 헤드를 많이 움직입니다. 디스크 앞뒤로.
대신 쓰기 대기중인 파일은 메모리에 잠시 동안 보관되어 디스크에서 종료되어야하는 위치와 버퍼가 가득 찼을 때 정렬 되었거나 디스크 동기화 디먼이 필요한 초 수 (보통 약 30 초라고 생각합니다)-전체 버퍼가 디스크에 "순서대로"쓰여졌습니다. 쓰기 헤드는 하나의 연속 스위핑 동작 만 수행하면됩니다. 그것은 도처에 뛰어 내리는 대신에 갔다.
솔리드 스테이트 장치는 말할 것도없이 오늘날의 빠른 디스크로 꾸준히 증가하면서, 한 번에 한 명의 사용자 만 작업하는 소수의 프로그램 만있는 홈 리눅스 시스템에서는 이득이 훨씬 적습니다.
어쨌든, 요청한 것보다 더 많이 (캐시 / 버퍼로) 읽음으로써 읽기를 예상하고, 쓰기를 기다리는 데이터를 정렬하여 "한 번의 동작"으로 쓰여질 수있었습니다. 실제로는 시간, 특히 많은 사용자들이 읽고 쓰는 시스템이 많은 경우.
Linux에만 국한된 것이 아니며 페이지 캐시 (Linux가 잘 수행하는)라고합니다. 참조 http://linuxatemyram.com/ ; 따라서 파일이 작성되면 몇 초 후에 다시 읽기 때문에 디스크 I / O가 필요하지 않은 경우가 많습니다.
주요 이점은 많은 시스템에 많은 RAM이 있으며 일부는 커널에서 캐시로 사용할 수 있다는 것입니다. 따라서 일부 파일 작업은이 캐싱을 활용합니다. 또한 디스크 I / O 시간은 RAM보다 훨씬 느립니다 (일반적으로 SDD의 경우 수천 번, 기계식 하드 디스크의 경우 거의 백만 배 느립니다).
응용 프로그램 코드는이 캐싱에 대한 힌트를 제공 할 수 있습니다. 예를 들어 posix_fadvise (2) & madvise (2)를 참조하십시오.
회전 플래터가 RAM보다 느립니다. 우리는이 사실을 '숨기기'위해 읽기 / 쓰기 캐싱을 사용합니다.
쓰기 IO의 유용한 점은 디스크에서 읽기가 완료 될 때까지 데이터를 사용자에게 반환 할 수없는 읽기와 달리 디스크 IO가 즉시 발생하지 않는다는 것입니다.
따라서 쓰기는 소프트 타임 제약 조건에서 작동합니다. 지속적인 처리량이 디스크의 처리량을 초과하지 않는 한 쓰기 캐시에서 많은 성능 저하를 숨길 수 있습니다.
또한 캐시를 작성해야합니다. 회전 디스크는 비교적 느립니다. 그러나 최신 RAID 유형을 사용하면 작동에 큰 페널티가 있습니다.
예를 들어, 하나의 쓰기 IO를 완료하려면 RAID 6이 다음을 충족해야합니다.
따라서 각 쓰기 작업은 실제로 6 개의 IO 작업입니다. 특히 큰 SATA 드라이브와 같은 느린 디스크가있는 경우 비용이 매우 비쌉니다.
그러나 쓰기 쉬운 통합 솔루션이 있습니다. 버퍼에 '전체 스트라이프'쓰기를 작성할 수 있으면 디스크에서 패리티를 읽을 필요가 없습니다. 메모리에있는 내용에 따라 계산할 수 있습니다.
더 이상 쓰기 증폭이 없으므로이 작업을 수행하는 것이 매우 바람직합니다. 실제로 RAID 1 + 0보다 쓰기 패널티가 낮아질 수 있습니다.
치다:
RAID 6, 8 + 2-10 스핀들.
쓰기위한 8 개의 연속 데이터 블록-캐시에서 패리티를 계산하고 각 디스크에 하나의 블록을 씁니다. 8 개당 10 개의 쓰기는 1.25의 쓰기 패널티를 의미합니다. RAID 1 + 0의 디스크 10 개는 여전히 쓰기 패널티가 2입니다 (각 서브 미러에 기록해야하기 때문에). 따라서이 시나리오에서는 실제로 RAID 6이 RAID1 + 0보다 나은 성능을 발휘할 수 있습니다. 실제 사용 환경에서는 혼합 IO 프로파일이 조금 더 있습니다.
따라서 쓰기 캐싱은 RAID 세트의 인식 된 성능과 큰 차이를 만듭니다. RAM 속도로 쓰기가 가능하고 쓰기 패널티가 낮으므로 처리량을 늘릴 경우 지속적인 처리량이 향상됩니다.
그렇지 않으면 SATA의 성능 저하로 고통을 겪지 만 6을 곱하고 경합을 추가하십시오. 쓰기 캐싱이없는 10 웨이 SATA RAID-6은 RAID가없는 단일 드라이브보다 약간 빠르지 만 그다지 많지는 않습니다.
주의하십시오. 전원 손실은 데이터 손실을 의미합니다. 캐시 플러시주기, 캐시 배터리 백업 또는 SSD 또는 기타 비 휘발성 캐시를 사용하여이를 완화 할 수 있습니다.
다른 답변들 중 어느 것도 지연된 할당을 언급하지 않았다 . XFS, ext4, BTRFS 및 ZFS는 모두이를 사용합니다. XFS는 ext4가 존재하기 전부터 사용 했으므로 예제로 사용하겠습니다.
XFS 는 쓰기 전까지 데이터를 어디에 둘지 결정하지 않습니다. 할당 지연 은 할당 자에게 결정에 기반을 둔 훨씬 더 많은 정보를 제공합니다. 파일을 처음 작성할 때는 4k 파일인지 1G 및 계속 증가하는 파일인지 알 방법이 없습니다. 어딘가에 10G의 연속 여유 공간이 있으면 4k 파일을 시작 부분에 두는 것은 좋지 않습니다. 큰 여유 공간의 시작 부분에 큰 파일을 넣으면 조각화가 줄어 듭니다.
여기에있는 다른 모든 대답은 최소한 정상적인 경우에는 거의 정확하며 내 앞에서 읽기를 권장하지만 dd 및 dd에는 쓰기 캐싱과 관련이없는 일반적인 사용 사례가 있다고 언급했습니다. 쓰기 캐싱은 주로 파일 시스템 수준에서 구현됩니다. 원시 장치는 일반적으로 쓰기 캐싱을 수행하지 않습니다 (raid 또는 lvm과 같은 여러 장치 드라이버는 왁스의 또 다른 공입니다). dd는 종종 원시 블록 장치와 함께 사용되므로 원시 장치에서 더 나은 성능을 위해 큰 쓰기를 허용하는 bs 및 관련 옵션을 제공합니다. 두 엔드 포인트가 모두 일반 파일 인 경우에는 유용하지 않습니다 (이 경우 큰 쓰기는 더 적은 시스템 호출을 사용하지만). 이것이 특히 눈에 띄는 다른 곳은 사용자 공간 파일 시스템 구현 인 mtools 패키지입니다. 플로피 드라이브에 mtools를 사용하면 도구가 완전히 동기화되고 플로피 드라이브가 매우 느리기 때문에 항상 느리게 느껴집니다. 플로피 마운트 및 커널 팻 파일 시스템 사용은 동기식 인 umount를 제외하고 훨씬 응답 성이 뛰어납니다 (특히 플로피와 같은 이동식 장치의 경우 데이터 손실을 방지하는 것이 매우 중요합니다). 특별히 구성된 데이터베이스 (자체 쓰기 캐싱을 구현하는), tar 및 chdsk, mkfs 및 mt와 같은 특수 장치 및 파일 시스템 도구와 같은 원시 장치와 함께 정기적으로 사용되는 것으로 알고있는 다른 프로그램이 거의 없습니다. 플로피 마운트 및 커널 팻 파일 시스템 사용은 동기식 인 umount를 제외하고 훨씬 응답 성이 뛰어납니다 (특히 플로피와 같은 이동식 장치의 경우 데이터 손실을 방지하는 것이 매우 중요합니다). 특별히 구성된 데이터베이스 (자체 쓰기 캐싱을 구현하는), tar 및 chdsk, mkfs 및 mt와 같은 특수 장치 및 파일 시스템 도구와 같은 원시 장치와 함께 정기적으로 사용되는 것으로 알고있는 다른 프로그램이 거의 없습니다. 플로피 마운트 및 커널 팻 파일 시스템 사용은 동기식 인 umount를 제외하고 훨씬 응답 성이 뛰어납니다 (특히 플로피와 같은 이동식 장치의 경우 데이터 손실을 방지하는 것이 매우 중요합니다). 특별히 구성된 데이터베이스 (자체 쓰기 캐싱을 구현하는), tar 및 chdsk, mkfs 및 mt와 같은 특수 장치 및 파일 시스템 도구와 같은 원시 장치와 함께 정기적으로 사용되는 것으로 알고있는 다른 프로그램이 거의 없습니다.
O_DIRECT
캐시를 우회하려면 사용해야 합니다. dd oflag=direct
. IIRC, 일부 유니스는 기본적으로 블록 장치에서 I / O를 지시합니다. (그리고 어쨌든 페이지 캐시를 작성하기 때문에 리눅스가 아닌 정렬 된 블록을 읽고 쓰는 것이 필요하다.)
철학은 기본적으로 안전하지 않습니다.
가능한 합리적이고 확실한 두 가지 전략이 있습니다. 즉, 디스크에 즉시 쓰기를 플러시하거나 쓰기를 지연시킵니다. 유닉스는 역사적으로 후자를 선택했다. 안전을 얻으려면 fsync
나중에 전화해야합니다 .
그러나 옵션을 사용하여 장치를 마운트 sync
하거나 파일을 사용하여 파일을 열어 안전을 미리 지정할 수 있습니다 O_SYNC
.
UNIX는 컴퓨터 전문가를 위해 설계되었습니다. "기본적으로 안전"은 고려되지 않았습니다. 안전은 I / O 속도가 느리다는 것을 의미하며 초기 시스템은 실제로 I / O 속도가 느려 가격 비율이 높습니다. 불행히도, 이것이 변경되지 않았음에도 불구하고 UNIX 나 Linux는 기본값으로 안전하게 전환되지 않았습니다.
처리량을 크게 늘리기 위해 소량의 안정성을 거래합니다.
예를 들어 비디오 압축 프로그램을 가정하십시오. 쓰기 지연 ( "write back")시 :
대
두 번째 버전은 CPU와 디스크를 동시에 사용할 수 있기 때문에 두 배 빠릅니다. 첫 번째 버전은 항상 하나를 기다리고 있습니다.
일반적으로 스트리밍 작업 및 대량 파일 작업을위한 후기 입과 데이터베이스 및 데이터베이스 유사 응용 프로그램을위한 연속 기입을 원합니다.
많은 응용 프로그램에서 저장 장치는 간헐적으로 데이터를 읽는 중입니다. 스토리지 장치가 데이터를 읽느라 바쁘지 않을 때까지 시스템이 항상 쓰기를 연기 할 수있는 경우, 애플리케이션의 관점에서 쓰기가 완료되는 데 시간이 걸리지 않습니다. 쓰기가 즉각적이지 않은 유일한 상황은 다음과 같습니다.
쓰기 버퍼는 실제로 쓰기가 완료 될 때까지 더 이상 지연된 쓰기 요청을 수락 할 수없는 수준까지 채 웁니다.
쓰기 보류중인 장치를 종료하거나 제거해야합니다.
응용 프로그램은 실제로 쓰기가 실제로 완료되었다는 확인을 요청합니다.
실제로, 위의 요구 사항 때문에 글쓰기가 실제로 이루어져야합니다. 반면에 일반적으로 장치가 유휴 상태 일 때 보류중인 쓰기를 수행하지 않는 이유는 없으므로 많은 시스템에서이를 수행합니다.