如何创建命名管道(mkfifo子)在Android的? [英] How to create named pipe (mkfifo) in Android?
问题描述
我无法在Android中创建命名管道和下面的例子说明了我的困境:
RES = mkfifo子(/ SD卡/ fifo9000,S_IRWXO);
如果(水库!= 0)
{
LOG(错误,而建立一个管道(返程:%D,错误号:%d),水库,错误号);
}
在code始终打印:
错误,同时创造一个管道(返程:-1,错误号:1)
我想不通究竟为什么失败。该应用程序有android.permission.WRITE_EXTERNAL_STORAGE权限。我可以创建普通文件完全在相同的位置相同的名称,但管道创建失败。有问题的管道应该从多个应用程序访问。
- 我怀疑,没有人可以在/ SD卡的管道。哪里会是这样做的最佳位置?
- 我应该设置什么模式杆(第2参数)?
- 应用程序是否需要任何额外的权限?
Roosmaa的回答是正确的 - mkfifo子()只是调用mknod的()来创建一个特殊的文件,而FAT32不支持。
正如你可能要考虑使用Linux的抽象空间UNIX域套接字替代。他们应该是大致相当于一个命名管道。您可以按名称访问它们,但它们不是文件系统的一部分,所以你不必应对各种权限问题。注意插座是双向的。
因为它是一个插座,您可能需要INTERNET权限。不知道这一点。
下面的客户机/服务器样本code快一点:
的#include< stdio.h中>
#包括< string.h中>
#包括< unistd.h中>
#包括< STDDEF.H>
#包括< SYS / socket.h中>
#包括< SYS / un.h>
/ *
*建立在Linux Unix域套接字地址抽象空间。
*
*插座code不需要空终止的文件名,但
*我们这样做也无妨这样的字符串函数的工作。
* /
INT makeAddr(为const char *的名称,结构sockaddr_un * PADDR中,socklen_t * pSockLen)
{
INT nameLen = strlen的(名字);
如果(nameLen> =(INT)的sizeof(pAddr-> sun_path)-1)/ *太长? * /
返回-1;
pAddr-> sun_path [0] ='\ 0'; / *抽象名字空间* /
的strcpy(pAddr-> sun_path + 1名);
pAddr-> sun_family = AF_LOCAL;
* pSockLen = 1 + nameLen +对offsetof(结构sockaddr_un,sun_path);
返回0;
}
INT主(INT ARGC,字符** argv的)
{
静态为const char *消息=你好,世界!;
结构sockaddr_un套接字地址;
socklen_t的sockLen;
INT结果= 1;
如果(argc个= 2 ||(的argv [1] [0] ='c'的&安培;!&安培;的argv [1] [0] ='s'的)!){
输出(用法:{Ç| S} \ N);
返回2;
}
如果(makeAddr(com.whoever.xfer,&安培; SOCKADDR,&安培; sockLen)℃的)
返回1;
INT FD =插座(AF_LOCAL,SOCK_STREAM,PF_UNIX);
如果(FD&小于0){
PERROR(客户端套接字());
返回1;
}
如果(的argv [1] [0] =='C'){
的printf(CLIENT%S \ N,sockAddr.sun_path + 1);
如果(连接(FD,(const的结构sockaddr *)及SOCKADDR,sockLen)小于0){
PERROR(客户端连接());
GOTO保释金;
}
如果(写(FD,消息,strlen的(消息)1)℃的){
PERROR(客户端的write());
GOTO保释金;
}
}否则如果(的argv [1] [0] =='s'的){
的printf(SERVER%S \ N,sockAddr.sun_path + 1);
如果(绑定(FD,(const的结构sockaddr *)及SOCKADDR,sockLen)小于0){
PERROR(服务器绑定());
GOTO保释金;
}
如果(听(FD,5)℃,){
PERROR(服务器监听());
GOTO保释金;
}
INT clientSock =接受(FD,NULL,NULL);
如果(clientSock℃,){
PERROR(服务器接受);
GOTO保释金;
}
焦炭BUF [64];
诠释计数=读(clientSock,BUF,的sizeof(BUF));
关闭(clientSock);
如果(计数℃,){
PERROR(服务器读);
GOTO保释金;
}
的printf(GOT:%s的\ N,BUF);
}
结果= 0;
保释:
关闭(FD);
返回结果;
}
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);
}
The code always prints:
Error while creating a pipe (return:-1, errno:1)
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.
- I suspect that noone can create pipes in /sdcard. Where would it be the best location to do so?
- What mode mast should I set (2nd parameter)?
- Does application need any extra permissions?
Roosmaa's answer is correct -- mkfifo() just calls mknod() to create a special file, and FAT32 doesn't support that.
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.
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] = '\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;
}
这篇关于如何创建命名管道(mkfifo子)在Android的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!