Schreiben ashmem / warum ist android kostenlos ashmem?
Ich möchte Daten zwischen zwei (ndk-)Prozesse. Für diese verwende ich ashmem mit dieser Quelle.
Ein Prozess ist kontinuierlich zu Lesen (read_mem
) und ein Prozess ist das schreiben eine Zeit (write_mem
).
Das problem ist, dass der Lesevorgang ist nicht immer die Werte des Schriftstellers.
UND
Durch die Beobachtung der Karten der reader ich fand, dass android löscht die shared-memory-Datei direkt nach ashmem_create_region
.
read_mem.c
//read_mem.c
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include "ashmem.h"
#define SHM_NAME "test_mem"
int main(int argc, char **argv) {
int shID = ashmem_create_region(SHM_NAME, 2);
if (shID < 0)
{
perror("ashmem_create_region failed\n");
return 1;
}
//right here /dev/ashmem/test_mem is deleted
printf("ashmem_create_region: %d\n", shID);
char *sh_buffer = (char*)mmap(NULL, 2, PROT_READ | PROT_WRITE, MAP_SHARED, shID, 0);
if (sh_buffer == (char*)-1)
{
perror("mmap failed");
return 1;
}
printf("PID=%d", getpid());
do
{
printf("VALUE = 0x%x\n", sh_buffer[0]);
}
while (getchar());
return 0;
}
write_mem.c
//write_mem.c
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include "ashmem.h"
#define SHM_NAME "test_mem"
int main(int argc, char **argv) {
int shID = ashmem_create_region(SHM_NAME, 2);
if (shID < 0)
{
perror("ashmem_create_region failed\n");
return 1;
}
printf("ashmem_create_region: %d\n", shID);
char *sh_buffer = (char*)mmap(NULL, 2, PROT_READ | PROT_WRITE, MAP_SHARED, shID, 0);
if (sh_buffer == (char*)-1)
{
perror("mmap failed");
return 1;
}
printf("PID=%d\n", getpid());
int ch = getchar();
sh_buffer[0] = ch;
printf("Written 0x%x\n", ch);
munmap(sh_buffer, 2);
close(shID);
return 0;
}
Dies ist die Ausgabe:
Lesen
130|shell@mako:/data/local/tmp $ ./read_mem
ashmem_create_region: 3
PID=29655
VALUE = 0x0
Schreiben
shell@mako:/data/local/tmp $ ./write_mem
ashmem_create_region: 3
PID=29691
A
Written 0x41
Lesen wieder VALUE = 0x0
(durch drücken des zeilenschalters)
Gerade die Karten des Lesers:
shell@mako:/$ cat /proc/29655/maps | grep test_mem
b6ef5000-b6ef6000 rw-s 00000000 00:04 116213 /dev/ashmem/test_mem (deleted)
wie Sie sehen können test_mem
gelöscht WÄHREND read_mem
ist noch am Leben.
Weitere Informationen
Beide Dateien sind kompiliert, die als ausführbare Datei mit dem android - ndk-build
Befehl
Gerät: LG Nexus 4 (AOSP Lollypop)
Ich überprüfte /dev/ashmem
vorhanden.
ashmem entnommen hier
- Die Karte ist noch vorhanden, es zeigt nur "(gelöscht)" in der Bezeichnung?
- Ich bin immer noch in der Lage zu Lesen und zu schreiben der Puffer ja. Aber es scheint, dass die Daten nicht geschrieben werden.
msync
macht keine Unterschiede.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ashmem funktioniert nicht wie die normalen shared memory unter Linux, und es gibt einen guten Grund dafür.
Lassen Sie uns zuerst versuchen zu erklären, die "(gelöscht)" Teil, dies ist eine Implementierung detail, wie ashmem ist im kernel implementiert. Was es wirklich bedeutet, ist, dass ein Datei Eintrag erstellt wurde, in das /dev/ashmem/- Verzeichnis, dann später entfernt, sondern dass die entsprechenden i-node noch existiert, weil es mindestens eine offene Datei-Deskriptor für Sie.
Könnte man tatsächlich mehrere ashmem Regionen mit dem gleichen Namen, und Sie alle werden als "/dev/ashmem/<name> (gestrichen)", sondern jeder von Ihnen entspricht eine andere i-node und damit eine verschiedenen Speicher region. Und wenn du dir unter /dev/ashmem/Sie würden sehen, dass das Verzeichnis immer noch leer ist.
Deshalb ist der name eines ashmem region ist wirklich nur für das Debuggen verwendet. Es gibt keine Möglichkeit zum "öffnen" eine vorhandene region mit Namen.
Einer ashmem i-node und die entsprechenden Speicher, wird automatisch zurückgefordert, wenn die Letzte Datei-Deskriptor ist es geschlossen. Dies ist nützlich, weil es bedeutet, dass, wenn der Prozess stirbt durch einen Unfall, der Speicher wird freigegeben werden, die vom kernel automatisch. Dies ist nicht der Fall mit regelmäßigen SysV shared memory (ein Absturz Prozess, verliert den Speicher!!! Etwas inakzeptabel, auf einem embedded-system wie Android).
Ihre test-Programme erstellen, die zwei unterschiedliche ashmem Regionen mit dem gleichen Namen, das ist, warum Sie nicht funktionieren, wie Sie denken sollten. Was Sie stattdessen brauchen, ist:
1) Erstellen Sie eine einzelne ashmem region in einem Prozess.
2) führen Sie eine neue Datei-Deskriptor für die region, aus der erste Prozess den zweiten.
Einen Weg, das zu tun, ist die Gabel der erste Prozess, um die zweite (dies wird automatisch doppelte Datei-descriptors), aber das ist generell keine gute Idee unter Android.
Eine bessere alternative ist die Verwendung von sendmsg() und recvmsg() zum senden der Datei-Deskriptor über ein Unix-domain-socket zwischen den beiden Prozessen. Dies ist in der Regel schwierig, aber als Beispiel haben Sie einen Blick auf die SendFd() und ReceiveFd () - Funktionen in die folgende Quell-Datei wurde geschrieben für den NDK:
https://android.googlesource.com/platform/ndk/+/android-5.0.0_r7/sources/android/crazy_linker/tests/test_util.h
Voila, ich hoffe, das hilft
/dev/ashmem/
Ordner, dort ist eine/dev/ashmem
Geräte-Datei, und es gibt/dev/ashmem/<name> (deleted)
Einträge in/proc/<pid>/maps
das sind nur Namen.