Ion ABI 변경사항

커널 4.14 이상이 설치된 기기는 다수의 공급업체 그래픽 메모리 할당자(gralloc) HAL(하드웨어 추상화 계층) 구현이 공유 메모리 버퍼를 할당하기 위해 호출하는 Ion 커널 모듈의 주요 리팩터링의 영향을 받습니다. 이 문서에서는 기존 공급업체 코드를 새 버전의 Ion으로 이전하는 방법을 안내하고 향후 가능한 Application Binary Interface(ABI) 위반에 관해 설명합니다.

Ion 소개

Ion은 업스트림 커널의 work-in-progress 스테이징 트리의 일부입니다. 스테이징 중에는 주요 커널 버전 간에 Ion의 userspace-to-kernel ABI 위반이 발생할 수 있습니다. Ion ABI 위반이 일반 애플리케이션이나 이미 출시된 기기에 직접 영향을 미치지는 않지만 새로운 주요 커널 버전으로 이전하는 공급업체에는 Ion에 호출되는 공급업체 코드에 영향을 미치는 변경사항이 발생할 수 있습니다. 또한 Android 시스템팀이 스테이징 트리 밖으로 Ion을 이동하기 위해 업스트림을 사용하기 때문에 향후 ABI 위반이 발생할 수 있습니다.

android-4.14의 변경사항

Kernel 4.12는 Ion 커널 코드를 크게 리팩터링하여 다른 커널 프레임워크와 겹치는 Ion 부분을 정리 및 삭제했습니다. 따라서 기존의 많은 Ion ioctl이 더 이상 관련이 없어져 삭제되었습니다.

Ion 클라이언트 및 핸들 삭제

커널 4.12 이전에는 /dev/ion을 열면 Ion 클라이언트가 할당되었습니다. ION_IOC_ALLOC ioctl은 새로운 버퍼를 할당하고 이 버퍼를 Ion 핸들(버퍼를 할당한 Ion 클라이언트에만 의미 있는 불투명 정수)로 사용자 공간에 반환했습니다. 버퍼를 사용자 공간으로 매핑하거나 다른 프로세스와 공유할 수 있도록 ION_IOC_SHARE ioctl을 사용해 Ion 핸들을 dma-buf fds로 다시 내보냈습니다.

커널 4.12에서 ION_IOC_ALLOC ioctl은 dma-buf fds를 직접 출력합니다. Ion 핸들을 사용하거나 생성하는 모든 ioctl과 함께 중간 Ion 핸들 상태가 삭제되었습니다. dma-buf fds는 특정 Ion 클라이언트에 연결되지 않으므로 ION_IOC_SHARE ioctl은 더 이상 필요하지 않고 모든 Ion 클라이언트 인프라가 삭제되었습니다.

캐시 일관성 ioctl 추가

커널 4.12 이전에 Ion은 파일 설명자를 메모리와 동기화하기 위해 ION_IOC_SYNC ioctl을 제공했습니다. 이 ioctl은 제대로 설명되지 않았으며 유연성이 부족했습니다. 따라서 많은 공급업체에서 캐시 유지 관리를 실행하기 위한 맞춤 ioctl을 구현했습니다.

커널 4.12는 ION_IOC_SYNClinux/dma-buf.h에 정의된 DMA_BUF_IOCTL_SYNC ioctl로 교체했습니다. 모든 CPU 액세스의 시작과 끝에서 이러한 액세스가 읽기 또는 쓰기인지 지정하는 플래그로 DMA_BUF_IOCTL_SYNC를 호출합니다. DMA_BUF_IOCTL_SYNCION_IOC_SYNC보다 더 상세하지만 사용자 공간에서 기본 캐시 유지 관리 작업을 더 세부적으로 관리할 수 있게 합니다.

DMA_BUF_IOCTL_SYNC는 커널의 안정적인 ABI의 일부이며 모든 dma-buf fds와 함께 사용할 수 있습니다. 이때 dma-buf fds를 Ion이 할당했는지는 상관없습니다.

공급업체 코드를 android-4.12+로 이전

userspace 클라이언트의 경우 Android 시스템팀에서는 ioctl() 호출을 개방 코딩하는 대신 libion을 사용하는 것을 적극 권장합니다. Android 9부터 libion은 런타임 시 Ion ABI를 자동으로 감지하고 커널 간의 차이점을 마스크하려고 합니다. 그러나 ion_user_handle_t 핸들을 생성하거나 사용했던 모든 libion 함수는 커널 4.12 이후에 더 이상 작동하지 않습니다. 이러한 함수는 dma-buf fds에 관해 동등한 다음 작업으로 교체할 수 있으며 이 작업은 지금까지 커널의 모든 버전에서 작동합니다.

기존 ion_user_handle_t 호출 상응하는 dma-buf fd 호출
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) 해당 사항 없음(dma-buf fds에는 이 호출이 필요하지 않음)
ion_map(ion_fd, buf_handle, ...) mmap(buf_fd, ...)
ion_free(ion_fd, buf_handle) close(buf_fd)
ion_import(ion_fd, buf_fd, &buf_handle) 해당 사항 없음(dma-buf fds에는 이 호출이 필요하지 않음)
ion_sync_fd(ion_fd, buf_fd) If (ion_is_legacy(ion_fd))

ion_sync_fd(ion_fd, buf_fd);

else

ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...);

in-kernel 클라이언트의 경우 Ion이 더 이상 커널 연결 API를 내보내지 않기 때문에 이전에 ion_import_dma_buf_fd()와 함께 in-kernel Ion 커널 API를 사용한 드라이버가 dma_buf_get()과 함께 in-kernel dma-buf API를 사용하도록 변환되어야 합니다.

향후 Ion ABI 위반

Ion이 스테이징 트리 밖으로 이동하기 전에 향후 커널 버전에서 Ion ABI를 다시 위반해야 할 수도 있습니다. Android 시스템팀은 이러한 변경사항이 다음 Android 버전이 설치되어 출시되는 기기에는 영향을 미치지 않을 것으로 예상하지만 후속 Android 버전에서 출시되는 기기에 영향을 줄 수 있습니다.

예를 들어 업스트림 커뮤니티에서는 단일 /dev/ion 노드를 힙당 여러 노드(예: /dev/ion/heap0)로 분할하여 기기에서 각 힙에 다른 SELinux 정책을 적용할 수 있도록 합니다. 이러한 변경사항이 향후 커널 버전에서 구현되면 Ion ABI를 위반합니다.