场景描述:在JNI层使用mkfifo,并且读写数据,同时在Android Java层读写fifo数据。
Android Java层读写fifo数据,获取fifo路径后,new File能够成功,说明路径是对的,但是然后用各种Stream,都无法成功获得可用的流,进而无法继续操作。暂时的结论,Java层读写fifo数据比较有困难,new 各种Stream时会阻塞住出不来,有空了再试,可能的原因可以看完本文,可能与底层申请只读权限不会成功有关系。
先说说在JNI层使用mkfifo,首先,FIFO的路径怎么确定,不是随便给个路径就能mkfifo成功的,经过试验,路径可以这样确定,在ANDROID JAVA层写如下代码:
String fifoName="my_test_fifo";
String seprator = File.separator;
//get full fifo auto
String dataDir=context.getApplicationInfo().dataDir;
String fullFifoPath=dataDir+seprator+fifoName;//this is the full path you want!!!
获取到完整的FIFO路径(fullFifoPath)后,便可以通过JNI接口传入底层C/C++代码,底层利用这个完整的路径进行mkfifo,open,write,read等操作:
//fifo操作自己本身需要的几个头文件,其它需要的头文件自己看着加
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int fd_fifo;//fifo handle
char *fifoPath="your fifo path";//不要hard code,换成你自己的fifo路径
if (mkfifo(fifoPath, 0666)<0 && errno != EEXIST)
{
//LOGI("can't create fifo ");
return;
}
//mkfifo success
fd_fifo=open(fifoPath, O_RDONLY | O_NONBLOCK);
if( fd_fifo<0)
{
// LOGI("fd=%d,can't open fifoPath%s",fd_fifo,fifoPath);
return;
}
else
{
// LOGI("fd=%d,Success open fifoPath=%s",fd_fifo,fifoPath);
}
需要额外提醒大家一点的就是,在进行open操作的时候,关于权限问题,这是在ANDROID上调用底层代码特有的一个诡异的地方,还没找到具体的原因,大家注意一下就行了:
如果打开时权限参数为只写,会失败,如下代码:
fd_fifo=open(fifoPath, O_WRONLY | O_NONBLOCK);
返回值fd_fifo会是-1,代表失败,如果把O_NONBLOCK去掉,则会一直阻塞住出不来。但是如果打开权限是可读写(O_RDWR)和只读(O_RDONLY)都会成功,同时,一个诡异的地方,一旦申请过O_RDWR,后面再用O_WRONLY就会成功了,下面是我依次以不同权限open的返回值结果:
2020-12-10 19:00:30.005 5327-5383/com.example.myapplication I/log_c: testfd_wo=-1 //O_WRONLY | O_NONBLOCK,失败
2020-12-10 19:00:30.005 5327-5383/com.example.myapplication I/log_c: testfd_wr=94//O_RDWR | O_NONBLOCK,成功
2020-12-10 19:00:30.005 5327-5383/com.example.myapplication I/log_c: testfd_ro=95//O_RDONLY | O_NONBLOCK,成功
2020-12-10 19:00:30.005 5327-5383/com.example.myapplication I/log_c: testfd_w=96//O_WRONLY | O_NONBLOCK,成功,因为前面以O_RDWR的权限open过,所以这里成功了!
呼应文章开头,JAVA层new各种stream会阻塞住出不来的现象,暂时能得到的原因是:java里面new stream的时候默认是以阻塞方式去new 的,虽然路径存在,但是申请不到,就一直阻塞住。
至于为什么会申请不到,有可能是没有以读写权限申请过,恰好我申请的时候申请的是各种OutStream类,是write权限。可能的解决办法:在底层以读写权限先open一下,或者在java层new 有读写权限的Stream。有空了我再试一下,大家如果有兴趣也可以尝试以下,有结果了可以告诉我,互相交流。