如何在 Android 中创建命名管道 (mkfifo)? [英] How to create named pipe (mkfifo) in Android?
问题描述
我在 Android 中创建命名管道时遇到了麻烦,下面的示例说明了我的困境:
I am having trouble in creating named pipe in Android and the example below illustrates my dilemma:
res = mkfifo("/sdcard/fifo9000", S_IRWXO);
if (res != 0)
{
LOG("Error while creating a pipe (return:%d, errno:%d)", res, errno);
}
代码总是打印出来:
Error while creating a pipe (return:-1, errno:1)
我无法弄清楚这失败的确切原因.该应用程序具有 android.permission.WRITE_EXTERNAL_STORAGE 权限.我可以在同一位置创建具有完全相同名称的普通文件,但管道创建失败.有问题的管道应该可以从多个应用程序访问.
I can't figure out exactly why this fails. The application has android.permission.WRITE_EXTERNAL_STORAGE permissions. I can create normal files with exactly the same name in the same location, but pipe creation fails. The pipe in question should be accessible from multiple applications.
- 我怀疑没有人可以在/sdcard 中创建管道.这样做的最佳地点在哪里?
- 我应该设置什么模式桅杆(第二个参数)?
- 应用程序是否需要任何额外权限?
推荐答案
Roosmaa 的回答 是正确的 -- mkfifo()只是调用 mknod() 来创建一个特殊的文件,而 FAT32 不支持.
Roosmaa's answer is correct -- mkfifo() just calls mknod() to create a special file, and FAT32 doesn't support that.
作为替代方案,您可能需要考虑使用 Linux 的抽象名称空间"UNIX 域套接字.它们应该大致相当于命名管道.您可以按名称访问它们,但它们不是文件系统的一部分,因此您不必处理各种权限问题.注意套接字是双向的.
As an alternative you may want to consider using Linux's "abstract namespace" UNIX-domain sockets. They should be roughly equivalent to a named pipe. You can access them by name, but they're not part of the filesystem, so you don't have to deal with various permission issues. Note the socket is bi-directional.
由于它是一个套接字,您可能需要 INTERNET 权限.不确定.
Since it's a socket, you may need INTERNET permission. Not sure about that.
这里有一些客户端/服务器示例代码:
Here's a quick bit of client/server sample code:
#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] = ' '; /* 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}
");
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
", 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
", 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'
", buf);
}
result = 0;
bail:
close(fd);
return result;
}
这篇关于如何在 Android 中创建命名管道 (mkfifo)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!