- 本文将模拟进程间共享内存的实现,用多线程模拟
看api描述,他是创建了一个共享的内存区域,并返回一个文件描述符,这个描述符可以被mmap映射
我们在mmp的时候可以使用flag: PROT_READ | PROT_WRITE | PROT_EXEC
仅支持android26以上
/**
* Create a shared memory region.
*
* Create shared memory region and returns an file descriptor. The resulting file descriptor can be
* mmap'ed to process memory space with PROT_READ | PROT_WRITE | PROT_EXEC. Access to shared memory
* region can be restricted with {@link ASharedMemory_setProt}.
*
* Use close() to release the shared memory region.
*
* Use {@link android.os.ParcelFileDescriptor} to pass the file descriptor to
* another process. File descriptors may also be sent to other processes over a Unix domain
* socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and cmsg(3) man pages for more information.
*
* If you intend to share this file descriptor with a child process after
* calling exec(3), note that you will need to use fcntl(2) with FD_SETFD
* to clear the FD_CLOEXEC flag for this to work on all versions of Android.
*
* Available since API level 26.
*
* \param name an optional name.
* \param size size of the shared memory region
* \return file descriptor that denotes the shared memory; -1 and sets errno on failure, or -EINVAL if the error is that size was 0.
*/
int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
1、消费端
-
首先我们构造一个结构体,表示要共享的数据。os_thread_helper用于实现同步机制
typedef struct utils { int id; char name[1024]; struct os_thread_helper oth; };
-
然后我们为他创建一块共享内存区域,mFd是这块内存的描述符。outPtr是我们消费端对这块内存的mmap映射
struct utils *mUtil =(struct utils*) malloc(sizeof(struct utils)); mSharedPtr = FF::ASharedMemory::create("util",sizeof(mUtil),(void **)&mUtil); FileUtilPtr = FF::FileUtil::create(); FileUtilPtr->setSharedData(mUtil);
ASharedMemory::ASharedMemory(const char* name,size_t size,void ** outPtr){
mFd = ASharedMemory_create(name, size);
const int access =PROT_READ | PROT_WRITE;
const int flags =MAP_SHARED;
void *ptr = mmap(NULL,size,access,flags,mFd,0);
if(ptr==NULL){
throw runtime_error("failed to create shared memory");
}
*outPtr = ptr;
}
-
我们还需要开启一个线程,循环去这块内存读取数据。消费数据端的工作基本完成了
void FileUtil::setSharedData(struct utils *util) { mUtil = util; os_run_func_t func = waitThread; os_thread_helper_init(&mUtil->oth); os_thread_helper_start(&mUtil->oth, func, mUtil); }
void* FileUtil::waitThread(void *ptr){
struct utils *util = reinterpret_cast<struct utils*>(ptr);
while (os_thread_helper_is_running(&util->oth)){
if(ptr!=NULL) {
LOGE("os_thread_helper_wait_locked");
os_thread_helper_lock(&util->oth);
os_thread_helper_wait_locked(&util->oth);
LOGE("readSharedData mUtil.name = %s ,id= %d", util->name, util->id);
os_thread_helper_unlock(&util->oth);
}
}
}
2、生产端
-
接着,我们开始创建生产消息的线程
这个线程我们在java里面创建,每隔2s往共享内存里面写数据
class myRunnable implements Runnable { @Override public void run() { while (true) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } clientSendMessage("发送到共享内存时间:" + SystemClock.elapsedRealtime()); } } }
接着我们映射了生产端的内存区域,就是mUtilClient。这样我们在mUtilClient里面放置的内容在消费端就能直接拿到,因为是同一块内存区域