美文网首页
共享内存ASharedMemory

共享内存ASharedMemory

作者: 赛非斯 | 来源:发表于2022-05-28 16:08 被阅读0次
    • 本文将模拟进程间共享内存的实现,用多线程模拟
      看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里面放置的内容在消费端就能直接拿到,因为是同一块内存区域

    相关文章

      网友评论

          本文标题:共享内存ASharedMemory

          本文链接:https://www.haomeiwen.com/subject/chwiprtx.html