드라이브 정책이 "빠른 제거"로 설정되어 있어도 소용량 FAT (FAT12) 형식의 USB 플래시 드라이브에서 FAT에 대한 쓰기 지연이 발생합니다. (이것은 SurpriseRemovalOK
깃발이 설정 되었음을 의미한다고 생각합니다 ). USB를 통해 드라이브로 전송되는 SCSI 명령을 캡처했습니다. 파일 잘림 쓰기가 즉시 발생하고 전체 파일 (2 512 바이트 섹터 길이)이 그 직후에 기록되지만 FAT보다 20-90 초 지연됩니다. 파일 쓰기를 반영하도록 업데이트됩니다.
드라이브의 크기가 중요합니다. 크기가 15MB 이하인 FAT 파일 시스템에서 테스트 한 결과 문제가 있습니다. 16MB 이상에서는 쓰기가 지연되지 않습니다. 16MB는 Windows에서 드라이브를 포맷 할 때 FAT12와 FAT16을 사용할 때 나타나는 중단 점입니다. (나중에 추가 된 참고 사항 : 그러나 FAT12 / FAT16 중단 점은 절대 파일 시스템 크기가 아니라 클러스터 수에 따라 다릅니다.)
16MB 이상에서 Windows는 Prevent/Allow Medium Removal
쓰기 전에 SCSI 명령을 전송 하여 장치를 제거하지 않도록 요청합니다. USB 스틱은 실제로 이러한 요청에서 실패를 반환하지만 (제거가 보장되지 않기 때문에) Windows는 어쨌든 시도합니다. 15MB 이하의 트레이스는 명령을 표시 하지 않습니다 Prevent/Allow Medium Removal
.
(파이썬 코드를 포함하는 작은 FAT 파일 시스템을 지원하는 마이크로 컨트롤러 보드를 사용하는 동안이 문제를 발견했습니다. 마이크로 컨트롤러가 파일 시스템에 대한 쓰기를 감지하면 쓰기가 완료 될 때까지 약간 기다렸다가 자동으로 다시 시작하여 새로 작성된 Python 코드를 실행합니다. 그러나 마이크로 컨트롤러는 쓰기 지연으로 인해 손상된 코드 또는 파일 시스템이 손상되었습니다.)
"빠른 제거"가 설정되어 있는데도 FAT에 대한 쓰기가 왜 그렇게 오래 지연됩니까? 드라이브에서 "이젝트"를 수행하여 쓰기를 강제 할 수 있지만 "빠른 제거"의 가능성을 상실합니다. 드라이브를 일찍 꺼내면 잘못된 FAT 테이블이 생깁니다. 아래의 스크린 샷에서 "하드웨어 안전하게 제거"를 사용할 필요가 없다는 내용입니다. 이것은 버그입니까, 아니면 뭔가 빠졌습니까? 수동 "Eject"없이 모든 쓰기를 즉시 수행 할 수있는 방법이 있습니까?
다음은 Wireshark / USBPcap 추적에서 정리 된 추출물로 문제를 보여줍니다. 기존 파일을 자른 다음 새 사본을 작성합니다. 에 의견을 추가했습니다 ###
. USB 드라이브에 대한 대부분의 쓰기는 트레이스에서 5 초 정도 걸리지 만 최종 FAT 쓰기는 26 초가되지 않습니다.
No. Time Source Destination Protocol Length Info
### write directory entry to truncate file
13 5.225586 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
14 5.225838 host 1.2.2 USB 4123 URB_BULK out
### write FAT entries to truncate file
16 5.230488 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
17 5.230707 host 1.2.2 USB 539 URB_BULK out
19 5.235110 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
20 5.235329 host 1.2.2 USB 539 URB_BULK out
### write directory entry for
22 5.252672 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
23 5.252825 host 1.2.2 USB 4123 URB_BULK out
### write out file data (2 sectors of 512 bytes)
25 5.257416 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x000000c1, Len: 2)
26 5.257572 host 1.2.2 USB 1051 URB_BULK out
### 20 second delay
### finally, write FAT entries to indicate used sectors
79 26.559964 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
80 26.560191 host 1.2.2 USB 539 URB_BULK out
82 26.560834 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
83 26.560936 host 1.2.2 USB 539 URB_BULK out
일반 플래시 드라이브와 Windows 7 및 Windows 10 모두에서 작은 USB MSC 드라이브를 에뮬레이트하는 마이크로 컨트롤러 보드를 사용하여 이와 같은 추적을 생성했습니다.
분명히, 이것은 Windows 포맷 도구에서 "FAT"라고하는 FAT12 포맷 드라이브입니다.
main.py
파일이 작성된 것을 감지하면 자동 재설정 및 실행 또는 유사한 파일로 설정됩니다. 쓰기가 완료 될 때까지 지연되지만 수십 초는 아닙니다. 이 자동 재시작을 비활성화 할 수 있지만 적시에 쓰기가 완료되도록하려면 드라이브를 "꺼내기"해야합니다. 사용자에게 꺼내기를 요구하는 것은 성가신 일입니다. 우리는 그것을 피하고 싶습니다.