퓨즈 통과

Android 12는 FUSE 오버헤드를 최소화하여 하위 파일 시스템에 대한 직접 액세스에 필적하는 성능을 달성하는 FUSE 통과를 지원합니다. FUSE 패스스루는 android12-5.4 , android12-5.10android-mainline (테스트 전용) 커널에서 지원됩니다. 즉, 이 기능에 대한 지원은 기기에서 사용하는 커널과 기기가 실행 중인 Android 버전에 따라 다릅니다.

  • Android 11에서 Android 12로 업그레이드하는 기기는 이러한 기기의 커널이 고정되어 있고 FUSE 패스스루 변경으로 공식적으로 업그레이드된 커널로 이동할 수 없기 때문에 FUSE 패스스루를 지원할 수 없습니다.

  • Android 12로 출시되는 기기는 공식 커널을 사용할 때 FUSE 패스스루를 지원할 수 있습니다. 이러한 장치의 경우 FUSE 패스스루를 구현하는 Android 프레임워크 코드가 MediaProvider 메인라인 모듈에 포함되어 자동으로 업그레이드됩니다. MediaProvider를 메인라인 모듈로 구현하지 않는 기기(예: Android Go 기기)도 공개적으로 공유되는 MediaProvider 변경 사항에 액세스할 수 있습니다.

FUSE 대 SDCardFS

FUSE(사용자 공간의 파일 시스템)는 FUSE 파일 시스템에서 수행되는 작업을 커널(FUSE 드라이버)에서 작업을 구현하는 사용자 공간 프로그램(FUSE 데몬)으로 아웃소싱할 수 있도록 하는 메커니즘입니다. Android 11은 SDCardFS 를 더 이상 사용하지 않으며 FUSE를 스토리지 에뮬레이션의 기본 솔루션으로 만들었습니다. 이 변경 사항의 일부로 Android는 파일 액세스를 가로채고 추가 보안 및 개인 정보 보호 기능을 적용하고 런타임에 파일을 조작하기 위해 자체 FUSE 데몬을 구현했습니다.

FUSE는 페이지나 속성과 같은 캐시 가능한 정보를 처리할 때 잘 수행되지만, 특히 중저가 장치에서 볼 수 있는 외부 저장소에 액세스할 때는 성능 저하가 발생합니다. 이러한 회귀는 FUSE 파일 시스템의 구현에서 협력하는 구성 요소 체인과 FUSE 드라이버와 FUSE 데몬 간의 통신에서 커널 공간에서 사용자 공간으로의 다중 전환(하위 파일에 대한 직접 액세스와 비교하여)으로 인해 발생합니다. 커널에서 더 간결하고 완전히 구현된 시스템).

이러한 회귀를 완화하기 위해 앱은 접합 을 사용하여 데이터 복사를 줄이고 ContentProvider API 를 사용하여 하위 파일 시스템 파일에 직접 액세스할 수 있습니다. 이러한 최적화 및 기타 최적화 를 사용하더라도 FUSE를 사용할 때 읽기 및 쓰기 작업은 하위 파일 시스템에 대한 직접 액세스와 비교할 때 감소된 대역폭을 볼 수 있습니다. 특히 캐싱이나 미리 읽기가 도움이 되지 않는 임의 읽기 작업에서 그렇습니다. 그리고 레거시 /sdcard/ 경로를 통해 스토리지에 직접 액세스하는 앱은 특히 IO 집약적인 작업을 수행할 때 계속해서 눈에 띄는 성능 저하를 경험합니다.

SDcardFS 사용자 공간 요청

SDcardFS를 사용하면 커널에서 사용자 공간 호출을 제거하여 FUSE의 저장소 에뮬레이션 및 권한 검사 속도를 높일 수 있습니다. 사용자 공간 요청은 사용자 공간 → VFS → sdcardfs → VFS → ext4 → 페이지 캐시/스토리지 경로를 따릅니다.

FUSE 패스스루 SDcardFS

그림 1. SDcardFS 사용자 공간 요청

FUSE 사용자 공간 요청

FUSE는 처음에 저장소 에뮬레이션을 활성화하고 앱이 내부 저장소 또는 외부 sdcard를 투명하게 사용할 수 있도록 하는 데 사용되었습니다. FUSE를 사용하면 각 사용자 공간 요청이 사용자 공간 → VFS → FUSE 드라이버 → FUSE 데몬 → VFS → ext4 → 페이지 캐시/스토리지 경로를 따르기 때문에 약간의 오버헤드가 발생합니다.

퓨즈 통과 퓨즈

그림 2. FUSE 사용자 공간 요청

FUSE 통과 요청 {#fuse-passthrough-requests}

대부분의 파일 액세스 권한은 파일을 열 때 확인되며 해당 파일에서 읽고 쓸 때 추가 권한 확인이 발생합니다. 어떤 경우에는 요청하는 앱이 요청된 파일에 대한 전체 액세스 권한을 갖고 있다는 것을 파일 열기 시간에 알 수 있으므로 시스템이 FUSE 드라이버에서 FUSE 데몬으로 읽기 및 쓰기 요청을 계속 전달할 필요가 없습니다. 데이터를 한 곳에서 다른 곳으로만 ​​이동함).

FUSE 통과를 사용하면 열기 요청을 처리하는 FUSE 데몬이 작업이 허용되고 모든 후속 읽기 및 쓰기 요청이 하위 파일 시스템으로 직접 전달될 수 있음을 FUSE 드라이버에 알릴 수 있습니다. 이것은 사용자 공간 FUSE 데몬이 FUSE 드라이버 요청에 응답하기를 기다리는 추가 오버헤드를 방지합니다.

FUSE 및 FUSE 통과 요청의 비교는 아래에 나와 있습니다.

FUSE 통과 비교

그림 3. FUSE 요청 대 FUSE 통과 요청

앱이 FUSE 파일 시스템 액세스를 수행하면 다음 작업이 발생합니다.

  1. FUSE 드라이버는 요청을 처리하고 대기열에 넣은 다음 /dev/fuse 파일의 특정 연결 인스턴스를 통해 해당 FUSE 파일 시스템을 처리하는 FUSE 데몬에 요청을 제공합니다. 이 인스턴스는 FUSE 데몬이 읽지 못하도록 차단됩니다.

  2. FUSE 데몬은 파일 열기 요청을 받으면 해당 특정 파일에 대해 FUSE 통과를 사용할 수 있는지 여부를 결정합니다. 사용 가능한 경우 데몬:

    1. 이 요청에 대해 FUSE 드라이버에 알립니다.

    2. 열린 /dev/fuse 의 파일 설명자에서 수행해야 하는 FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl을 사용하여 파일에 대한 FUSE 통과를 활성화합니다.

  3. ioctl은 다음을 포함하는 데이터 구조를 (매개변수로) 받습니다:

    • 통과 기능의 대상인 하위 파일 시스템 파일의 파일 설명자.

    • 현재 처리 중인 FUSE 요청의 고유 식별자입니다(열린 상태이거나 생성 후 열기여야 함).

    • 비워 둘 수 있고 향후 구현을 위한 추가 필드입니다.

  4. ioctl이 성공하면 FUSE 데몬이 열기 요청을 완료하고 FUSE 드라이버가 FUSE 데몬 응답을 처리하며 하위 파일 시스템 파일에 대한 참조가 커널 내의 FUSE 파일에 추가됩니다. 앱이 FUSE 파일에 대한 읽기/쓰기 작업을 요청하면 FUSE 드라이버는 하위 파일 시스템 파일에 대한 참조를 사용할 수 있는지 확인합니다.

    • 참조를 사용할 수 있는 경우 드라이버는 하위 파일 시스템 파일을 대상으로 하는 동일한 매개변수를 사용하여 새 VFS(가상 파일 시스템) 요청을 생성합니다.

    • 참조를 사용할 수 없는 경우 드라이버는 요청을 FUSE 데몬으로 전달합니다.

위의 작업은 일반 파일의 읽기/쓰기 및 읽기 반복/쓰기 작업과 메모리 매핑된 파일의 읽기/쓰기 작업에 대해 발생합니다. 주어진 파일에 대한 FUSE 패스스루는 해당 파일이 닫힐 때까지 존재합니다.

FUSE 통과 구현

Android 12를 실행하는 기기에서 FUSE 패스스루를 활성화하려면 대상 기기의 $ANDROID_BUILD_TOP/device/…/device.mk 파일에 다음 줄을 추가하세요.

# Use FUSE passthrough
PRODUCT_PRODUCT_PROPERTIES += \
    persist.sys.fuse.passthrough.enable=true

FUSE 패스스루를 비활성화하려면 위의 구성 변경을 생략하거나 persist.sys.fuse.passthrough.enablefalse 로 설정하십시오. 이전에 FUSE 통과를 활성화한 경우 비활성화하면 장치에서 FUSE 통과를 사용할 수 없지만 장치는 계속 작동합니다.

장치를 플래싱하지 않고 FUSE 패스스루를 활성화/비활성화하려면 ADB 명령을 사용하여 시스템 속성을 변경하십시오. 아래에 예가 나와 있습니다.

adb root
adb shell setprop persist.sys.fuse.passthrough.enable {true,false}
adb reboot

추가 도움말은 참조 구현 을 참조하십시오.

FUSE 통과 검증

MediaProvider가 FUSE 통과를 사용하고 있는지 확인하려면 logcat 에서 디버깅 메시지를 확인하십시오. 예를 들어:

adb logcat FuseDaemon:V \*:S
--------- beginning of main
03-02 12:09:57.833  3499  3773 I FuseDaemon: Using FUSE passthrough
03-02 12:09:57.833  3499  3773 I FuseDaemon: Starting fuse...

FuseDaemon: Using FUSE passthrough 가 사용 중인지 확인합니다.

Android 12 CTS에는 FUSE 통과를 트리거하는 테스트가 포함된 CtsStorageTest 가 포함되어 있습니다. 테스트를 수동으로 실행하려면 아래와 같이 test를 사용하십시오.

atest CtsStorageTest