Autore Topic: Usare la Shared Memory Android  (Letto 1201 volte)

Offline angelfire

  • Nuovo arrivato
  • *
  • Post: 3
  • Respect: 0
    • Mostra profilo
Usare la Shared Memory Android
« il: 08 Novembre 2011, 12:31:42 CET »
0
Ciao a tutti gli amici del forum.
Vi spiego il mio problema. Sono riuscito sotto Linux a far comunicare due processi via shared memory. Ora mi servirebbe farlo con Android. Mi potete dire come fare? Per caso devo usare Ashmem?
Grazie  :-)

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Usare la Shared Memory Android
« Risposta #1 il: 08 Novembre 2011, 12:38:26 CET »
0
Quando a suo tempo esplorai l'argomento, trovai che in Android di fatto la shared memory funziona solo all'interno dello stesso processo (volutamente).

Non mi ricordo dove l'ho letto ne' come ritrovarlo, ma ci arrivai con Google.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Usare la Shared Memory Android
« Risposta #2 il: 08 Novembre 2011, 13:02:51 CET »
0
Le shared memory nel kernel di Linux usato da Android si chiamano "ashmem" e differiscono da quelle ufficiali di Linux per un API semplificata e con meno consumo di memoria.

I dettagli del funzionano:

Android Kernel Features - eLinux.org
cs736-android / ASHMEM

Non mi risulta la limitazione nell'uso nello stesso processo (servo appunto per condividere zone di memoria tra processi diversi).


adb logcat | tee /tmp/logcat | grep TAG

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Usare la Shared Memory Android
« Risposta #3 il: 08 Novembre 2011, 14:05:33 CET »
0
Non mi risulta la limitazione nell'uso nello stesso processo (servo appunto per condividere zone di memoria tra processi diversi).

Interfaccia applicativo su shared memory - Android Developers Italia
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Usare la Shared Memory Android
« Risposta #4 il: 08 Novembre 2011, 22:13:40 CET »
0
Ho esaminato meglio la Android shared memory. Serve a condividere zone di memoria tra processi ma non tra due programmi (o applicazioni Java) separate. La condivisione avviene solo attraverso un handle ma non attraverso il nome.

Questo è un esempio molto semplice in C (serve NDK per compilarlo):

Codice: [Seleziona]
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/mman.h>

#include <linux/ashmem.h>

#define SM_NAME "NAME"

int status = 0;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *server(void *arg)
{
    int ret, size;
    char *data;

    int fd = (int)arg;
    char message[] = "Hello word";

    pthread_mutex_lock(&mut);

    size = ioctl(fd, ASHMEM_GET_SIZE, 0);
    if (size < 0) {
        fprintf(stderr, "Error get size");
        return (void *)1;
    }

    data = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (data == MAP_FAILED) {
        fprintf(stderr, "Error mmap");
        return (void *)1;
    }

    strncpy(data, message, sizeof(message));

    status = 1;

    pthread_cond_broadcast(&cond);

    pthread_mutex_unlock(&mut);
   
    return (void *)0;
}

void *client(void *arg)
{
    int ret, size;
    char *data;

    int fd = (int)arg;
    char buffer[ASHMEM_NAME_LEN];
   
    pthread_mutex_lock(&mut);

    while (status == 0) {
        pthread_cond_wait(&cond, &mut);
    }

    printf("Client\n");

    ret = ioctl(fd, ASHMEM_GET_NAME, buffer);
    if (ret < 0) {
        fprintf(stderr, "Error get name");
        return (void *)1;
    }

    printf("  name \"%s\"\n", buffer);

    size = ioctl(fd, ASHMEM_GET_SIZE, 0);
    if (size < 0) {
        fprintf(stderr, "Error get size");
        return (void *)1;
    }

    printf("  size %d\n", size);

    data = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (data == MAP_FAILED) {
        fprintf(stderr, "Error mmap");
        return (void *)1;
    }

    printf("  message: \"%s\"\n", data);

    pthread_mutex_unlock(&mut);

    return (void *)0;
}

int main(int argc, char **argv)
{
    int fd, ret;
    size_t size = 100;
    char buffer[ASHMEM_NAME_LEN];

    struct data shared;

    pthread_t thread1, thread2;

    fd = open("/" ASHMEM_NAME_DEF, O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "Error open \"%s\"\n", ASHMEM_NAME_DEF);
        return 1;
    }

    strncpy(buffer, SM_NAME, sizeof(buffer));

    ret = ioctl(fd, ASHMEM_SET_NAME, buffer);
    if (ret < 0) {
        fprintf(stderr, "Error set name \"%s\"\n", SM_NAME);
        close(fd);
        return 1;
    }

    ret = ioctl(fd, ASHMEM_SET_SIZE, size);
    if (ret < 0) {
        fprintf(stderr, "Error set size");
        close(fd);
        return 1;
    }

    if (pthread_create( &thread1, NULL, server, (void *)fd) < 0) {
        fprintf(stderr, "Error create thread 1\n");
        return 1;
    }

    if (pthread_create( &thread2, NULL, client, (void *)fd) < 0) {
        fprintf(stderr, "Error create thread 2\n");
        return 1;
    }

    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);

    close(fd);

    return 0;
}

i due thread ricevano handle, uno scrive un messaggio nella zona di memoria, l'altro lo visualizza e poi escono.

API è semplificata, non ha un sistema di protezione, quindi può essere usata solo all'interno dello stesso programma.
adb logcat | tee /tmp/logcat | grep TAG

Offline angelfire

  • Nuovo arrivato
  • *
  • Post: 3
  • Respect: 0
    • Mostra profilo
Re:Usare la Shared Memory Android
« Risposta #5 il: 09 Novembre 2011, 15:56:24 CET »
0
Ok qualcosa adesso mi è più chiaro ma eseguendo il codice postato da iceweasel trovo un errore facendo #include <linux/ashmem.h> (File o directory non esistente).
Ci sono esempi sull'uso di memoryfile?
Cmq grazie a tutti, mi state aiutando molto!  ;-)
« Ultima modifica: 09 Novembre 2011, 16:14:51 CET da angelfire »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Usare la Shared Memory Android
« Risposta #6 il: 09 Novembre 2011, 16:17:52 CET »
0
Siccome devo fare una relazione con tanto di esempio, vorrei sapere cosa significa che MemoryFile è un wrapper del driver ashmem di Linux.
Cmq grazie a tutti, mi stato aiutando molto!  ;-)

C'è una differenza sostanziale, MemoryFile lo usi con l'SDK (quindi programmi in Java e il tutto gira all'interno della Dalvik), per l'esempio di iceweasel devi usare l'NDK (programmi in C ed esegui all'esterno della Dalvik).
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Usare la Shared Memory Android
« Risposta #7 il: 09 Novembre 2011, 17:24:08 CET »
0
Ci sono esempi sull'uso di memoryfile?

Intendi il "memory mapped file" dei sistemi operativi POSIX ? In C si utilizza la classica "mmap", esempi per Android si trovano nei sorgenti di Android stesso nel codice nativo chiamato via JNI dal codice Java (classe FileChannel).
adb logcat | tee /tmp/logcat | grep TAG

Offline angelfire

  • Nuovo arrivato
  • *
  • Post: 3
  • Respect: 0
    • Mostra profilo
Re:Usare la Shared Memory Android
« Risposta #8 il: 09 Novembre 2011, 21:34:40 CET »
0
Uso Eclipse ed ho provato a compilare il codice di iceweasel ma mi da quell'errore su file non trovato.
Siccome è la prima volta che mi avvicino ad android, ti chiedo se mi puoi darmi una mano su come usare eclipse con Android.
esempi per Android si trovano nei sorgenti di Android stesso nel codice nativo chiamato via JNI dal codice Java (classe FileChannel).
si mi riferivo al memory mapped file. Mi spieghi una cosa. Io so che Android utilizza diversi meccanismi IPC per i diversi processi, dipende con quali caratteristiche di tale processo è necessario interagire con i terminali tramite JNI/Java API.
1)Per il codice nativo, per lo più usando il meccanismo IPC del kernel Linux 2.6.
2)Per il codice scritto in Java, usano le socket.
3)Chiamate Binder.
Quindi se ho capito bene: per il punto 1 si usa ashmem, per il punto 2 si usa JNI e quindi la classe memoryfile e per il punto 3 si usa IBinder.
Per far comunicare due processi posso scegliere uno di questi?
Se sbaglio mi dovete scusare ma ho troppa confusione in testa!  :-(
Grazie

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Usare la Shared Memory Android
« Risposta #9 il: 09 Novembre 2011, 22:30:43 CET »
0
ADT di Google non ha il supporto per NDK, devi essere un vero esperto per usarlo con Eclipse. Io non ho usato Eclipse ma la linea di comando per compilarlo e VIM per editarlo.

1) IPC classici di Linux non sono tutti disponibili nel kernel di Linux usato da Android, come documentato in un link precedente.
Ashmem è l'implementazione di Android delle shared memory ma IPC non è solo shared memory.
2) I socket da Java alla fine sono implementati via JNI ma non solo l'unico modo per comunicare tra processi in Java.
3) Binder è un RPC (uno dei tanti), la sua implementazione è fatta in kernel-space e non in user-space.

adb logcat | tee /tmp/logcat | grep TAG