Jak vytvořit pojmenovaného kanálu (mkfifo) v Androidu?

hlasů
11

Mám potíže při vytváření pojmenovaný kanál v Android a níže uvedený příklad ilustruje moje dilema:

res = mkfifo(/sdcard/fifo9000, S_IRWXO);
if (res != 0)
{
    LOG(Error while creating a pipe (return:%d, errno:%d), res, errno);
}

Kód vždy tiskne:

Error while creating a pipe (return:-1, errno:1)

Nemůžu přijít na to, proč se to nezdaří. Aplikace má oprávnění android.permission.WRITE_EXTERNAL_STORAGE. Mohu vytvořit normální soubory s přesně stejným názvem ve stejném místě, ale vytvoření pipe selže. Trubka v otázce by měla být přístupná z několika aplikací.

  1. Domnívám se, že nikdo nemůže vytvořit potrubí v / sdcard. V případě, že by bylo nejlepší místo, aby tak učinily?
  2. Jakém režimu mast je třeba nastavit (2) parametr?
  3. Má aplikace nepotřebuje žádné další oprávnění?
Položena 29/04/2010 v 20:46
zdroj uživatelem
V jiných jazycích...                            


5 odpovědí

hlasů
14

Roosmaa odpověď je správná - mkfifo () právě volá mknod () k vytvoření speciální soubor, a FAT32 nepodporuje.

Jako alternativu, možná budete chtít zvážit použití Linux je „abstraktní jmenném prostoru“ Unix-domain sokety. Měly by být hrubě ekvivalentní k pojmenovanému kanálu. Můžete se k nim podle jména, ale nejsou součástí souborového systému, takže nemusíte řešit různé problémy oprávnění. Upozorňujeme, že zásuvka je obousměrný.

Vzhledem k tomu, že je to zásuvka, možná budete muset INTERNET povolení. Nejste si jisti, o tom.

Zde je rychlý trochu ukázkový kód klient / server:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>

/*
 * Create a UNIX-domain socket address in the Linux "abstract namespace".
 *
 * The socket code doesn't require null termination on the filename, but
 * we do it anyway so string functions work.
 */
int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
{
    int nameLen = strlen(name);
    if (nameLen >= (int) sizeof(pAddr->sun_path) -1)  /* too long? */
        return -1;
    pAddr->sun_path[0] = '\0';  /* abstract namespace */
    strcpy(pAddr->sun_path+1, name);
    pAddr->sun_family = AF_LOCAL;
    *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
    return 0;
}

int main(int argc, char** argv)
{
    static const char* message = "hello, world!";
    struct sockaddr_un sockAddr;
    socklen_t sockLen;
    int result = 1;

    if (argc != 2 || (argv[1][0] != 'c' && argv[1][0] != 's')) {
        printf("Usage: {c|s}\n");
        return 2;
    }

    if (makeAddr("com.whoever.xfer", &sockAddr, &sockLen) < 0)
        return 1;
    int fd = socket(AF_LOCAL, SOCK_STREAM, PF_UNIX);
    if (fd < 0) {
        perror("client socket()");
        return 1;
    }

    if (argv[1][0] == 'c') {
        printf("CLIENT %s\n", sockAddr.sun_path+1);

        if (connect(fd, (const struct sockaddr*) &sockAddr, sockLen) < 0) {
            perror("client connect()");
            goto bail;
        }
        if (write(fd, message, strlen(message)+1) < 0) {
            perror("client write()");
            goto bail;
        }
    } else if (argv[1][0] == 's') {
        printf("SERVER %s\n", sockAddr.sun_path+1);
        if (bind(fd, (const struct sockaddr*) &sockAddr, sockLen) < 0) {
            perror("server bind()");
            goto bail;
        }
        if (listen(fd, 5) < 0) {
            perror("server listen()");
            goto bail;
        }
        int clientSock = accept(fd, NULL, NULL);
        if (clientSock < 0) {
            perror("server accept");
            goto bail;
        }
        char buf[64];
        int count = read(clientSock, buf, sizeof(buf));
        close(clientSock);
        if (count < 0) {
            perror("server read");
            goto bail;
        }
        printf("GOT: '%s'\n", buf);
    }
    result = 0;

bail:
    close(fd);
    return result;
}
Odpovězeno 03/05/2010 v 19:28
zdroj uživatelem

hlasů
8

Výchozí souborový systém z / sdcard je FAT32, který nepodporuje pojmenované kanály.

Na non-zakořeněné zařízení jediným možným místem, kde by se mohl pokusit vytvořit tyto trubky by bylo použití dat adresáře /data/data/com.example/. Poznámka: Neměli byste napevno tuto hodnotu, použijte Context.getApplicationInfo () DataDir..

Ale být vědomi toho, že vždy, když uživatel používá Apps2SD nebo kdykoliv nářadí Google, které podporují oficiálně je potřeba, aby se ujistil, aby uživatel věděl, že aplikace nemůže být uložen na VFAT systému souborů.

Odpovězeno 03/05/2010 v 13:42
zdroj uživatelem

hlasů
1

Chtěl bych připojit k přijatému odpověď:

1) Jsem schopen tuto metodu použít k připojení zásuvky mezi dvěma nativními moduly aplikaci pro Android.

2) write()by měla být ve smyčce protože se nemusí psát v plné výši požadované v prvním cestách. Například by to něco číst takto:

void *p = buffer;
count = 0;
while ((count += write(clientSock, buffer, num_bytes - count)) < num_bytes)
{
    if (count < 0)
    {
        close(clientSock);
        errCode = count;
        break;
    }
    p += count;
}

Manipulace chyba je uvedeno výše, je nedostatečný, protože několik chybových kódů jednoduše označují to zkusit znovu. Naleznete v dokumentaci pro zápis .

Odpovězeno 10/06/2015 v 14:22
zdroj uživatelem

hlasů
1

tam je také /sqlite_stmt_journals(budeme používat pro testování, nevím, jak dlouho tento adresář přežije aktualizace OS)

Pokud potřebujete IPC, osvědčené postupy, používají pojiv

Pokud potřebujete jen inter-thread komunikaci, můžete použít nepojmenované roury přes JNI (to funguje)

Odpovězeno 07/05/2010 v 10:58
zdroj uživatelem

hlasů
0

Pokud toto kódování v Javě, měli byste stačí použít PipedInputStream a PipedOutputStream .

Odpovězeno 08/05/2010 v 09:59
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more