Zephyr v3.7.0 · 저장소와 VFS

파일 경로 하나에 겹친 세 경계

fs_open()에 넘기는 문자열은 저장 장치의 주소가 아니다. VFS가 마운트 지점을 고르고, 파일 시스템 백엔드가 이름과 데이터를 해석하며, 그 아래의 flash area 또는 Disk Access가 매체를 만진다. 세 경계를 나눠야 실패 원인과 자원 수명을 추적할 수 있다.

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

기준은 Zephyr v3.7.0, 고정 commit 36940db938a8f4a1e919496793ed439850a221c2다. 해당 파일 시스템 백엔드와 실제 저장 장치 또는 파티션이 빌드·보드에 준비되어 있다는 전제에서 공개 API와 고정 구현을 설명한다. 예시 경로는 구조를 설명하는 가상 구성으로, 어떤 보드에나 그대로 쓸 수 있는 설정값이 아니다. 그림과 표는 이 글을 위해 새로 그렸다.

1. VFS는 경로를 백엔드로 보내지만 매체를 만들지 않는다

Zephyr 파일 시스템 스위치는 여러 fs_mount_t를 등록된 백엔드와 연결한다. 파일 호출은 절대 경로에서 해당 마운트 지점을 찾아 fs_file_system_t의 작업으로 위임한다. 고정 fs.c는 경로 구분자 경계를 확인하고 가장 긴 일치 마운트 지점을 선택한다. 따라서 /data/log는 /data에 속하지만 /database/log를 같은 접두사로 취급하지 않는다. 실제 저장소의 준비와 오류는 선택된 백엔드 아래에서 결정된다.

그림 1. 같은 fs_open, 다른 마운트·매체 경로

↔ 좁은 화면에서는 왼쪽의 호출에서 각 오른쪽 경로까지 이동하세요.

애플리케이션fs_open(&file, path, flags)초기화한 파일 객체·절대 경로·모드
예시: /lfs/reportVFS의 /lfs 마운트 → LittleFS → 지정한 flash area 또는 지원·설정된 block device
예시: /SD:/reportVFS의 FAT 마운트 → FatFS → Disk Access → 해당 디스크 드라이버·매체

경로 이름만 만들면 파일 시스템이 생기는 것은 아니다. 백엔드 등록, 마운트 구조체, 매체 드라이버 또는 파티션이 모두 맞아야 한다. v3.7.0 ELM FAT 경로에는 허용되는 볼륨 이름 제약도 있으므로 위의 /SD:는 사용 가능한 디스크 이름을 가정한 예시다.

근거: 3.7.0 VFS·마운트 API, 경로 경계·최장 일치 선택 및 파일 호출 위임, FAT 마운트 이름 조건.

2. 성공한 fs_mount는 설정 구조체의 수명도 잡는다

fs_mount(&mp)는 타입·마운트 지점·백엔드 데이터·저장소 참조·플래그를 담은 fs_mount_t를 사용한다. 성공하면 VFS가 그 구조체의 참조를 유지하므로 호출자는 같은 포인터의 fs_unmount()가 성공할 때까지 내용을 바꾸거나 수명을 끝내면 안 된다. 마운트 해제 전에 열린 파일을 닫고, 해제의 반환값을 확인해 매체와 상위 코드의 소유권 전환을 맞춘다.

그림 2. 마운트 설명자의 소유권과 포맷 분기

↔ 왼쪽에서 오른쪽으로 설정, 마운트, 사용, 해제 시점을 확인하세요.

① 준비type, mnt_point, fs_data, storage_dev, flags와 매체를 맞춘다.
② 마운트 호출백엔드가 매체를 열고 파일 시스템을 검사한다. 설정에 따라 실패하면 포맷을 시도할 수 있다.
③ 성공한 기간VFS가 mp를 참조한다. 파일 작업 중 구조체나 매체 조건을 임의 변경하지 않는다.
④ 정리열린 파일을 닫고 fs_unmount(&mp) 결과를 확인한 뒤 구조체·매체를 재설정한다.
표 1. 마운트 플래그의 역할과 경계
플래그뜻주의할 경계
FS_MOUNT_FLAG_NO_FORMAT마운트에 실패했을 때 백엔드의 자동 포맷 경로를 막는다.포맷 기능 자체가 없는 백엔드까지 새 기능을 만드는 값이 아니다.
FS_MOUNT_FLAG_READ_ONLY읽기 전용 마운트를 요청하고 VFS의 생성·쓰기 경로를 제한한다.포맷이 필요한 매체는 읽기 전용으로 복구할 수 없으며 오류가 날 수 있다.
FS_MOUNT_FLAG_AUTOMOUNT사전 정의된 fstab 마운트의 시작 시점 자동 마운트 표시다.호출자가 직접 만든 구조체에서는 이 플래그만으로 자동 실행되지 않는다.
FS_MOUNT_FLAG_USE_DISK_ACCESSDisk Access 사용을 요청한다.LittleFS의 block-device 설정·드라이버가 필요하며, 모든 백엔드가 flash 경로와 disk 경로를 둘 다 제공하지 않는다.

근거: 3.7.0 마운트 계약·플래그, 고정 공개 헤더의 fs_mount_t, LittleFS 포맷 분기.

3. LittleFS와 FatFS는 같은 VFS 아래의 다른 저장 경로다

고정 LittleFS 구현은 기본 flash-area 경로와, CONFIG_FS_LITTLEFS_BLK_DEV를 갖춘 block-device 경로를 구분한다. 마운트의 storage_dev가 가리키는 대상과 USE_DISK_ACCESS 플래그가 일치해야 한다. FatFS는 Disk Access가 제공하는 볼륨에 접근한다. SD 카드뿐 아니라 flash-disk처럼 flash 파티션을 block device로 바꿔 제공할 수도 있지만, 그것이 LittleFS의 flash-area 경로와 동일하다는 뜻은 아니다.

그림 3. 백엔드 아래에서 갈라지는 저장 장치 인터페이스

↔ 오른쪽으로 이동하며 각 백엔드의 전제와 끝점을 비교하세요.

경로
백엔드
매체 인터페이스
실제 준비물
A · flash
LittleFSflash 경로
Flash mapflash_area_*
파티션flash 장치·영역·지우기/쓰기 단위
B · block
LittleFSblock 지원 빌드 + disk 플래그
Disk Access섹터 read/write/ioctl
볼륨호환 block device와 포맷
C · FAT
FatFSFAT 볼륨 이름
Disk Accessdiskio 계층
볼륨SD 또는 flash-disk 등 지원 장치
표 2. LittleFS·FatFS의 매체 조건
선택매체 준비마운트에 실패할 때 확인할 점
LittleFS · flashFlash map 영역과 맞는 fs_littlefs 설정NO_FORMAT·READ_ONLY가 없으면 고정 백엔드는 실패 후 포맷을 시도할 수 있다.
LittleFS · blockCONFIG_FS_LITTLEFS_BLK_DEV, Disk Access 볼륨, USE_DISK_ACCESS장치·block 크기·기존 on-disk 형식이 맞는지 확인한다.
FatFS허용되는 볼륨 이름과 Disk Access 장치; 매체별 구성CONFIG_FS_FATFS_MOUNT_MKFS가 켜진 경우에만, 해당 조건에서 자동 포맷 경로가 생긴다. NO_FORMAT은 이를 막는다.

데이터가 남아 있는 매체에서는 포맷 설정부터 검토한다. LittleFS 예시 문서는 호환되지 않는 파티션 내용이 빈 파일 시스템으로 바뀔 수 있다고 설명한다. FAT 예시도 마운트에 실패하면 설정에 따라 재포맷될 수 있다고 경고한다. 이것은 모든 마운트 실패가 데이터 손상이라는 뜻도, 모든 실패가 자동 복구된다는 뜻도 아니다.

근거: LittleFS flash/block 분기·포맷 분기, FatFS Disk Access·조건부 포맷, 3.7.0 LittleFS 매체 예시, 3.7.0 FAT 예시 경고, Disk Access와 flash-disk.

4. 파일 객체의 수명은 open과 close 사이에 있다

fs_file_t_init()로 파일 객체를 초기화한 뒤 절대 경로와 모드 플래그를 fs_open()에 준다. 성공한 객체는 사용 후 fs_close()로 닫는다. FS_O_CREATE는 없는 파일 생성, FS_O_APPEND는 쓰기 전 끝으로 이동, FS_O_TRUNC는 열 때 길이를 0으로 만드는 요청이며, truncate에는 쓰기 모드와 백엔드 지원이 필요하다. 모드 0은 파일이 있어도 읽기·쓰기 권한을 주지 않는다.

표 3. 파일 객체의 API·수명
단계API와 반환호출자의 책임
객체 준비fs_file_t_init(&file)처음 사용 전에 초기화한다. 같은 열린 객체에 다시 open하면 -EBUSY다.
열기fs_open(&file, path, flags); 0 또는 음수 오류절대 경로·마운트·모드·백엔드 지원을 구분한다.
읽기fs_read; 실제 읽은 바이트 수 또는 음수 오류요청한 길이보다 짧은 성공을 처리한다.
쓰기fs_write; 실제 쓴 바이트 수 또는 음수 오류짧은 쓰기와 남은 데이터 처리·오류를 확인한다.
정리fs_close(&file); 0 또는 음수 오류성공한 뒤 파일 객체를 재사용한다. v3.7.0은 백엔드 close가 실패하면 file.mp를 비우지 않으므로, 실패를 닫기 완료로 취급하지 않는다.

근거: 초기화·open·close·read·write 계약, 고정 VFS의 핸들·권한·백엔드 위임.

5. 오류 번호는 어느 경계에서 막혔는지 말해 준다

열기 실패를 모두 “매체가 없다”로 해석하면 진단이 틀어진다. 경로 문법, 마운트 검색, 읽기 전용 제한, 백엔드 미구현, 파일 부재는 각각 다른 단계다. fs_read()와 fs_write()의 0 이상 값은 요청 전체가 처리됐다는 뜻이 아니라 실제 처리한 바이트 수다. v3.7.0 문서는 짧은 쓰기에서 전역 errno도 확인하도록 안내한다. 장치에 영속 반영되는 시점은 백엔드마다 달라질 수 있으므로 성공한 write만으로 전원 장애 내구성을 선언하지 않는다.

표 4. 오류 코드별 점검 경계
관찰우선 확인할 경계다음 행동
fs_open → -EINVAL절대 경로와 유효한 파일 이름호출 인자와 경로 문법을 확인한다.
fs_open → -ENOENT마운트 지점 또는 요청 파일 부재마운트 성공·생성 플래그·파일 존재를 구분한다.
fs_open → -EROFS읽기 전용 마운트의 생성·쓰기 요청마운트 플래그와 열기 모드를 확인한다.
fs_open → -ENOTSUP백엔드의 해당 작업 미구현파일 시스템 드라이버와 옵션을 확인한다.
fs_read/write → n < 요청 길이정상적인 짧은 읽기 또는 쓰기 실패·용량 문제읽기 종료와 쓰기 잔량을 별도로 처리한다.

근거: 3.7.0 API 반환값·짧은 I/O, VFS 검사 순서, FAT 매체 전원·분리 경고.

6. 보드에 넣기 전에는 구성과 수명을 함께 점검한다

표 5. 보드 적용 전 구성·수명 점검
질문확인할 대상놓치면 생기는 일
어느 마운트에 들어가는가?절대 경로·마운트 이름·해당 백엔드 등록잘못된 매체로 이동하거나 -ENOENT
매체 경로가 맞는가?LittleFS flash area/block, FatFS Disk Access 및 드라이버마운트 실패 또는 설정과 다른 장치 접근
포맷이 허용되는가?NO_FORMAT 및 FatFS 포맷 Kconfig기존 내용이 빈 파일 시스템으로 바뀔 수 있음
파일과 마운트는 누가 닫는가?fs_close 뒤 fs_unmount의 반환매체를 분리할 때 미반영 데이터·수명 경합
성공한 I/O 길이가 충분한가?fs_read/write의 바이트 수와 오류부분 데이터가 전체 처리로 오인됨

테스트는 새 매체와 기존 데이터가 있는 매체를 따로 준비하고, 예상한 백엔드의 마운트 성공·실패, 읽기 전용, 용량 부족, 짧은 I/O, 안전한 분리 순서를 확인한다. 이 글의 그림은 고정 버전의 계약을 설명하는 자료이며 특정 보드의 신뢰성·전원 장애 복구를 실험한 결과는 아니다.

7. 고정 버전 근거와 이어 읽기

공개 계약은 Zephyr 3.7.0 File Systems와 v3.7.0 fs.h, 경로·핸들 동작은 fs.c, 저장 경로는 LittleFS와 FatFS에 고정했다. 매체 조건과 포맷 경고는 해당 버전의 LittleFS 예시·FAT 예시·Disk Access 문서와 대조했다.