2016-07-18 5 views
0

Ich habe ein Beispiel für android Ionen Nutzung geschrieben:android ion, ioctl von ION_IOC_IMPORT return <0, errno = 9

Der Vater Prozess ein Rohr erzeugt, öffnet sich dann "/ dev/ion" -Gerät, ioctl von ION_IOC_ALLOC , ioctl von ION_IOC_MAP und mmap, und schließlich habe ich die von ION_IOC_MAP zurückgegebene fd und die Länge an den untergeordneten Prozess per Pipe übergeben.

Der untergeordnete Prozess liest fd und Länge aus der Pipe, und das Lesen ist in Ordnung, aber wenn ich ION_IOC_IMPORT mache, gab dies -1 zurück, und das errno ist 9, perror ist "Bad file descriptor".

Die beiden Prozesse sind Root-Benutzer und Selinux ist zulässig.

Vater Prozess Schlüsselcode:

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); 

Child Prozess Schlüsselcode:

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; 
} 

Antwort

0

Datei-Deskriptoren (FDS) verstehen sich pro Prozess und kann daher nicht nur zwischen Prozessen gemeinsam genutzt werden, indem ein Beschreiber vorbei (die eine einfache int) - das ist, warum Sie den Fehler bekommen. In Android, können Sie zwei Ansätze, um dies zu lösen: 1. Verwenden Sie Android Binder, indem beide Prozesse realisieren eine Klasse, die IInterface und all diesen Jazz erbt (siehe zum Beispiel: https://github.com/gburca/BinderDemo), aber ich glaube, das ist eine Menge von overkill nur für eine einmalige gemeinsame Nutzung eines fd so ... 2. Ich bevorzuge die Verwendung von gutem altmodischen Unix, das die Möglichkeit bietet, ein fd zu duplizieren, wenn es über einen Socket weitergegeben wird. Einfach googeln Sie das magische Wort: SCM_RIGHTS und Sie sollten Tonnen von Beispielen finden.