由于AllJoyn的join session timeout问题一直无法解决,我们怀疑AllJoyn有些内部变量没有清理干净,因此考虑将AllJoyn相关功能放到一个单独的进程中,一旦join session timeout,就重启该进程。

这就涉及到IPC问题。

因为我们写的是通用模块,需要在DTV(arm平台linux)和Android(NDK)上运行,因此就必须考虑各种IPC手段的可用性了。

一开始我考虑直接使用socket进行IPC(肯定可用),但有人说消息队列、共享内存、管道之类的也可以用。于是俺就mmap+信号量实现了一个简单的IPC类:

/*
* File: ipc.h
* Author: raozf
*
* Created on 2013年9月17日, 上午11:04
*/ #ifndef IPC_H
#define IPC_H #include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h> //semaphore name
const std::string IPC_SEM = "alljoyn_sem";
//mmap length
const size_t IPC_MMAP_LEN = * * ; /*
* helper class for IPC between ****forked**** processes.
* implemented by semaphore and mmap
*/
class IPC
{
public:
IPC():_mutex(NULL), _memory(NULL)
{
//unnamed semaphore should use sem_init() //open named semaphore, shared between processes
_mutex = sem_open(IPC_SEM.c_str(), O_CREAT, O_RDWR, );
if(_mutex == SEM_FAILED || _mutex == NULL)
{
LOGV("[ContextSharing]IPC::IPC() sem_open() failed. semaphore name:%s, %s", IPC_SEM.c_str(), strerror(errno));
return;
} /*
* http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html
*/
//create a anonymous mmap
_memory = (char*)mmap(NULL, IPC_MMAP_LEN, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, , );
if(_memory == MAP_FAILED || _memory == NULL)
{
LOGV("[ContextSharing]IPC::IPC() mmap() failed. %s", strerror(errno));
deinit();
return;
}
} ~IPC()
{
deinit();
} //send msg to other process
//header+message
// int char*
void send(const std::string& msg)
{
*((int*)_memory) = msg.length();
memcpy(_memory + sizeof(int), msg.c_str(), msg.length());
sem_post(_mutex);
} //receive from other process
std::string recv()
{
sem_wait(_mutex);//will block
return std::string(_memory + sizeof(int), (int)(_memory));
} private:
void deinit()
{
if(_mutex != NULL)
{
/* destory an unnamed semaphore, initialized by sem_init()
//sem_destroy(_mutex);
*/ // closes the named semaphore, but still existed in system kernel
sem_close(_mutex);
_mutex = NULL; //remove semaphore from system kernel(if it's reference is 0--which decremented by sem_close())
//removes the named semaphore referred to by name. The semaphore name is removed immediately.
//The semaphore is destroyed once all other processes that have the semaphore open close it.
sem_unlink(IPC_SEM.c_str());
} if(_memory != NULL)
{
munmap(_memory, IPC_MMAP_LEN);
_memory = NULL;
}
} private:
sem_t* _mutex;
char* _memory;
}; #endif /* IPC_H */

辅助类,封装一个线程专门等待信号量、接收数据:

/*
* File: ThreadedIPC.h
* Author: raozf
*
* Created on 2013年9月17日, 下午3:21
*/ #ifndef THREADEDIPC_H
#define THREADEDIPC_H #include "Common/ThreadManager.h"
#include "delegate.h"
#include "ipc.h" static const OID OID_ThreadedIPC = { 0x8f52a31f, 0x51d5, 0x462b, { 0xa9, 0x8d, 0x40, 0x70, 0xa3, 0xf6, 0xb5, 0x7f } };
class ThreadedIPC
:public CObjectRoot<CObjectMultiThreadModel>
,public IThreadClient
{
public:
PSFRESULT FinalConstruct()
{
PSFRESULT res = PSF_E_FAIL; CHK_PSFRESULT(_listen_thread.Initialize());
_listen_thread.AddTask(this, NULL); CLEANUP:
return res;
} void FinalRelease()
{
_listen_thread.Terminate();
} void Send(const std::string& msg)
{
_sharer.send(msg);
} private:
void OnExecute(void* pArg)
{
while(true)
{
_delegate_recv(_sharer.recv());
}
} void OnTerminate(void* pArg)
{
} public:
delegate::Delegate<void(std::string)> _delegate_recv; private:
CTaskWorker _listen_thread;
IPC _sharer; BEGIN_OBJECT_INTERFACE_MAP()
OBJECT_INTERFACE_ENTRY(OID_ThreadedIPC, this);
END_OBJECT_INTERFACE_MAP()
}; #endif /* THREADEDIPC_H */

这里面用到了我们自己写的delegate和thread类(先忽略之)。

但在android上运行时却报错:

IPC::IPC() sem_open() failed. semaphore name:alljoyn_sem, Function not implemented

看来信号量在NDK下是用不了的。

而且,不仅仅信号量,共享内存、消息队列在NDK下都不能用

参见讨论:https://groups.google.com/forum/#!topic/android-ndk/FzJIsJIxCX4

http://stackoverflow.com/questions/18603267/cross-process-locking-with-android-ndk

(但管道可用?http://stackoverflow.com/questions/8471552/porting-c-code-which-uses-fork-to-android

Android源代码中的文档说明:http://www.netmite.com/android/mydroid/1.6/bionic/libc/docs/SYSV-IPC.TXT

(该文件在Android4。3中似乎已经移出该文档)

Android does not support System V IPCs, i.e. the facilities provided by the
following standard Posix headers: <sys/sem.h> /* SysV semaphores */
<sys/shm.h> /* SysV shared memory segments */
<sys/msg.h> /* SysV message queues */
<sys/ipc.h> /* General IPC definitions */ The reason for this is due to the fact that, by design, they lead to global
kernel resource leakage.

原因就是防止内核资源泄露。

更重要的问题在于:fork()也尽量不要用。

道理很简单:我们不应该控制android的底层,这些api会造成系统的不稳定。

https://groups.google.com/forum/#!msg/android-platform/80jr-_A-9bU/nkzslcgVrfYJ

“Bear in mind that the Dalvik VM doesn't like fork() much, and goes into
conniptions if you try to do *any* work between the fork() and the
exec(). ”

https://groups.google.com/forum/#!topic/android-ndk/FzJIsJIxCX4

悲催!

----------------------------

ps:学到了一个命令“ipcs”,查看系统中共享内存、信号量状态:

$ ipcs

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status

------ Semaphore Arrays --------
key semid owner perms nsems

------ Message Queues --------
key msqid owner perms used-bytes messages

NDK下IPC问题的更多相关文章

  1. C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN

    同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...

  2. Android NDK 下的宽字符编码转换及icu库的使用(转)

    原贴http://topic.csdn.net/u/20101022/16/1b2e0cec-b9d2-42ea-8d9c-4f1bb8320a54.html?r=70149216 ,看过并动手实现, ...

  3. 20155202 张旭 课下作业: Linux下IPC机制

    20155202张旭 Linux下IPC机制 IPC机制定义 在linux下的多个进程间的通信机制叫做IPC(Inter-Process Communication),它是多个进程之间相互沟通的一种方 ...

  4. 20155239吕宇轩 Linux下IPC机制

    20155239吕宇轩 Linux下IPC机制 - 共享内存 原理:把所有需要使用的共享数据都存放在共享内存 区域中,任何想要访问这些共享数据的进程都必须在自己的进程地址空间中新增加一块内存区域,用来 ...

  5. 2017-2018-1 20155307 《信息安全系统设计基础》第十周课上未完成补充以及课下IPC作业

    课上内容2:stat命令的实现-mysate 学习使用stat(1),并用C语言实现 提交学习stat(1)的截图 man -k ,grep -r的使用 伪代码 产品代码 mystate.c,提交码云 ...

  6. Linux下IPC机制

    Linux下IPC机制 实践要求 研究Linux下IPC机制:原理,优缺点,每种机制至少给一个示例,提交研究博客的链接 共享内存 管道 FIFO 信号 消息队列 IPC 进程间通信(IPC,Inter ...

  7. NDK下 将Platinum SDK 编译成so库 (android - upnp)

    Platinum UPnP SDK 是一个跨平台的C++库,利用该库,可以很容易就构建出DLNA/UPnP控制点(DLNA/UPnP Control Point)和DLNA/UPnP设备(DLNA/U ...

  8. NDK下编译JNI

    NDK环境下编译JNI 下载demo.tar.gz然后解压 弄个套路 1.编辑build.sh设置好NDK目录 2.把cpp文件放到code下面 运行sh build.sh即可

  9. 【记录一个问题】没用任何用处的解决了libtask的context.c在32位NDK下的编译问题

    32位下用ndk编译libtask出现这样的错误: [armeabi-v7a] Compile thumb : task <= context.c /Users/ahfu/code/androi ...

随机推荐

  1. 风情万种awk

    awk是基于列的文本处理工具,所有的文件都是由单词和各种空白字符组成.这里"空白字符"包括空格.tab以及连续的空格和tab,每个非空白的部分叫做"域",从左到 ...

  2. 解决lazarus 多线程报错问题

    很多人都在Windows中使用线程技术,然后同样的代码移植到Linux下一运行就出错.一开始不解其中的奥妙.既然Lazarus提供了TThread类,也没注明非要在Windows下使用.没道理在Lin ...

  3. ExtJs之组件(window)

    Ext.create('Ext.window.Window',{    title:'',    width:400,    height:300,    constrain:true,//限制窗口不 ...

  4. 洛谷——P1165 日志分析

    P1165 日志分析 题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志.该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次 ...

  5. 第4天:Ansible模块

    Ansible对远程服务器的实际操作实际是通过模块完成的,其工作原理如下: 1)将模块拷贝到远程服务器 2)执行模块定义的操做,完成对服务器的修改 3)在远程服务器中删除模块 需要说明的是,Ansib ...

  6. [LOJ6191][CodeM]配对游戏(概率期望DP)

    n次向一个栈中加入0或1中随机1个,如果一次加入0时栈顶元素为1,则将这两个元素弹栈.问最终栈中元素个数的期望是多少. 首先容易想到用概率算期望,p[i][j][k]表示已加入i个数,1有j个,总长为 ...

  7. xcoj 1103 插线板(树链刨分求最大子段和)

    1103: 插线板 时间限制: 1 Sec  内存限制: 128 MB提交: 14  解决: 7 标签提交统计讨论版EditTestData 题目描述 从前有一堆古老的插线板,任意两个插线板之间只有一 ...

  8. BZOJ 4327 JSOI2012 玄武密码(后缀自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4327 [题目大意] 求每个子串在母串中的最长匹配 [题解] 对母串建立后缀自动机,用每 ...

  9. 【最小生成树】【kruscal】【贪心】CDOJ1636 梦后楼台高锁,酒醒帘幕低垂

    首先,考虑到,我们需要找到一条路径,使它的最小边尽量大,最大边尽量小 然后,考虑到m比较小,我们可以去寻找一个m^2或者m^2logm的算法 考虑枚举最小边,那么我们就需要在m或者mlogm的时间内找 ...

  10. [HihoCoder1259]A Math Problem

    题目大意: 有一个函数f(n),满足3f(n)*f(2n+1)=f(2n)*(1+3f(n)),f(2n)<6f(n). 我们用g(t)表示f(i)%k=t的i的个数,其中1<=i< ...