Ion ABI 변경사항

커널 4.14 이상이 설치된 기기는 다수의 공급업체 그래픽 메모리 할당자(gralloc) HAL(하드웨어 추상화 계층) 구현이 공유 메모리 버퍼를 할당하기 위해 호출하는 Ion 커널 모듈의 주요 리팩터링의 영향을 받습니다. 이 문서에서는 기존 공급업체 코드를 새 버전의 Ion으로 마이그레이션하는 방법을 안내하고 향후 가능한 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 ioctl이 더 이상 관련이 없어져 삭제되었습니다.

Ion 클라이언트 및 핸들 삭제

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

커널 4.12에서 IOC_ION_ALLOC ioctl은 dma-buf fds를 직접 출력합니다. Ion 핸들을 사용하거나 생성하는 모든 ioctl과 함께 중간 Ion 핸들 상태가 삭제되었습니다. dma-buf fds는 특정 Ion 클라이언트에 연결되지 않으므로 IOC_ION_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 정책을 적용할 수 있도록 합니다. 이러한 변경사항이 향후 커널 버전에서 구현되면 이온 ABI를 위반합니다.