Linux下进程通信 命名管道FIFO

2021-01-09  本文已影响0人  凯玲之恋

Linux下进程通信 匿名管道pipe

3 命名管道(FIFO/named PIPE)

有名管道的创建可以使用mkfifo函数,函数的使用类似于open函数的使用,可以指定管道的路径和打开的模式。

3.1 什么是命名管道

3.2 命名管道的读写规则

3.3 命名管道的安全问题

相比TCP通信方式

命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的。相比TCP通信方式,效率更高,但比共享内存要低点。

Android JNI之命名管道(FIFO/mkfifo)的使用

场景描述:在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 的,虽然路径存在,但是申请不到,就一直阻塞住。

参考

命名管道文件的使用
使用命名管道实现进程间通信
Android JNI之命名管道(FIFO/mkfifo)的使用(2)

上一篇 下一篇

猜你喜欢

热点阅读