Я написал пример использования ионов Android:
Процесс-отец создает канал, затем открывает устройство «/ dev / ion», ioctl из ION_IOC_ALLOC, ioctl из ION_IOC_MAP и mmap, и, наконец, я доставил fd, возвращенный ION_IOC_MAP, и длину для дочернего процесса по каналу.
Дочерний процесс читает fd и length из pipe, и чтение в порядке, но когда я делаю ION_IOC_IMPORT, это возвращает -1, а errno равно 9, perror — «Bad file descriptor».
Эти два процесса — пользователь root, а selinux — разрешительный.
Код ключа процесса отца:
ion_fd = open("/dev/ion", O_RDONLY);
if (ion_fd < 0) {
ALOGE("Failed to open ion device\n");
return -EIO;
}
alloc_data.len = 0x1000;
alloc_data.align = 0x1000;
alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
alloc_data.flags = ION_SECURE;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
ALOGE( "Failed to allocate uspace ion buffer\n");
goto uimp_alloc_err;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc < 0) {
ALOGE("unable to ion map buffer\n");
goto uimp_map_err;
}
map_fd = fd_data.fd;
addr = mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED , map_fd, 0);
if (!addr) {
ALOGE("mmap failed\n");
rc = -EIO;
goto uimp_mmap_err;
}
write_pattern((unsigned long)addr, alloc_data.len);
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc < 0) {
ALOGE( "unable to share ion buffer\n");
goto uimp_share_err;
}
itoa(fd_data.fd, ubuf, sizeof(int) * 8);
if (0 > sock_write(wr_fd, ubuf, sizeof(int) * 8))
goto uimp_sock_err;
itoa(alloc_data.len, ubuf, sizeof(int) * 8);
if (0 > sock_write(wr_fd, ubuf, sizeof(int) * 8))
goto uimp_sock_err;
do {
tpid = wait(&child_status);
} while (tpid != child_pid);
Код ключа дочернего процесса:
if (0 > sock_read(fd, cbuf, sizeof(int) * 8))
return -EIO;
fd_data.fd = atoi(cbuf);
/* receive buf length */
if (0 > sock_read(fd, cbuf, sizeof(int) * 8))
return -EIO;
size = atoi(cbuf);
ion_fd = open("/dev/ion", O_RDONLY);
if (ion_fd < 0) {
rc = -EINVAL;
goto child_args_err;
}
rc = ioctl(ion_fd, ION_IOC_IMPORT, &fd_data); // it failed here
if (rc) {
ALOGE( "ION_IOC_IMPORT failed %d errno %d\n", rc, errno);
perror("ioctl");
rc = -EIO;
goto child_imp_err;
}
addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd_data.fd, 0);
if (!addr) {
perror("mmap");
rc = -EIO;
goto child_mmap_err;
}
Вместо rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);,
использование rc = ioctl(ion_fd, **ION_IOC_SHARE**, &fd_data);
Это решит это.
ссылка: https://groleo.wordpress.com/2012/07/24/ion-buffer-sharing-mechanism/
Файловые дескрипторы (fds) предназначены для каждого процесса и, следовательно, не могут быть разделены между процессами просто путем передачи дескриптора (который является простым int) — вот почему вы получаете ошибку.
В Android вы можете использовать два подхода для решения этой проблемы:
1. Используйте Android Binder, так как оба процесса реализуют класс, который наследует IInterface и весь этот джаз (см., Например: https://github.com/gburca/BinderDemo) Тем не менее, я считаю, что это слишком много просто для того, чтобы разделить ФД на один раз, так что …
2. Я предпочитаю использовать старый добрый Unix, который предоставляет средства для дублирования fd, если он пропущен через сокет. Просто наберите волшебное слово: SCM_RIGHTS, и вы сможете найти множество примеров.