我们需要在android native层实现两个进程间的通信,这两个进程一个是native c 进程,一个是apk,两者需要传递一张几百K的图片,natice c 程序写该图片,apk读该图片,而且,这个读写的过程是一直持续的
首先,根据linux提供的几个进程通信的方法一个一个的来看:
1 信号,显然不合适,这个是系统进程和用户进程通信的方法,显然对我们来说不合适
2 管道 , 说实话,本身很不喜欢这个概念,因为不容易懂,管道有份同一个父进程和不同父进程的通信,经尝试,失败,原因记不清了,好像是android没有实现管道这个东东
3 共享内存, android没有实现该方法,它使用的是匿名共享内存,经google,发现,提供的接口非常复杂,不容易懂,放弃
4 socket, 实现了该方法后,可以通信,但是很郁闷的是socket通信对数据大小是有要求的,如果是64K以下,那用这个很easy,但是我们传递的是图片,将近一兆的大小,在用socket的时候,发现,传递的图片,有的时候是正确的,有的时候不正确,在图片的结尾或者头部有一些数据损失,经观察,每次传递的数据大小也不一致,这个显然是不能接受的。虽然,socket传递大数据是有很多方法的,比如说分批次传递,压缩传递,但是,就我们这样规模的一个工程,而且是在本机传递,用得着这样大动干戈吗?即使费劲九牛二虎之力做到了,一方面,花费的时间,由于复杂度过大引起bug的可能性,这两个原因让我选择放弃该方法。
5 经过这么多的失败,必须停下来思考下了,开始看书,无意中发现linux有一个对文件加锁的机制,这个很棒。我们最终就是要让两个不同的进程安全的访问一个文件,既然可以对文件加锁,那么数据安全的问题就解决了,而在android本地创建一个文件,也不需要太麻烦,ok,思路来了:
a 创建一个公共文件,native c写该文件,apk程序读该文件,对文件的加锁解锁都用c做,apk程序通过jni的方式去加锁解锁
b 关于数据安全性,native c程序在写该文件的时候,其他程序不能读或者写,apk层文件需要读该文件的时候,其他进程不能写
c 关于公共文件的存放位置,经过与大牛沟通后,决定放在android的tmpfs上,怎么查看android文件系统里,哪些目录是tmpfs呢,busybox mount 后,看看吧;关于什么是tmpfs,可以google下详细了解,简单的说,它其实就是物理内存的一块地方,既然这样,那么访问速度就会很快,原先担心的频繁读取IO会低效的顾虑也打消了
有了思路开始实施,一切还算顺利,除了一个问题,关于公共文件在什么时候创建的问题。 首先,如果将我们的程序安装到一个android设备上的时候,不能指望人家文件系统就已经给你创建好了该文件吧,所以,需要在我们的程序里面去创建该文件。所以,有这样的一个程序步骤,如果该文件不存在,则创建。
但是,事与愿违, 文件虽然创建了,但是使用文件的时候,总是提示有问题,好像是文件无法被访问的提示,于是乎,查看一下该公共文件的权限,的确跟其他文件不一样啊,原来是linux的权限机制在捣乱。所以改变文件权限是核心问题,因为在程序中创建文件时,需要指定权限,但是,当时给的权限是可读写,但是,创建出来却不是这样的,所以 ,放弃该方法。在折腾的过程中发现一个问题,我手动adb进去,切换到root权限,手动创建的文件,权限是ok的,但是,使用我们的程序创建就不行。
好在我们有一个系统启动时执行的脚本文件,我们自己写的,该脚本文件的执行是加在init.rc文件里的,所以,在该脚本文件中加入两行:
touch myfile
chmod 777 myfile
执行脚本,加载程序,一切ok
经过这几天的折腾,总结经验如下:
1 做产品,解决问题使用的方法必须考虑到时间因素,解决方案的复杂性,并不是难度大的解决方案就是最好的,因为难度大,采用的流程多,代码量高,造成隐藏的bug量就大
2 采用简单好理解,易维护的解决方案
3 在android底层写程序,遇见问题的时候,考虑下权限问题
4 不拘泥于传统的方法,白猫黑猫能抓到老鼠的就是好猫
欢迎大家提出意见和建议