Android native进程间通信实例-binder结合共享内存

  在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kernel\drivers\staging\android\ashmem.c。但是本篇文章不是讲解android共享内存的功能实现原理,而是讲怎么运用它。

  1.

  在linux中,不同进程间拥有自己独立的内存空间,32位操作系统中好像一个进程能用的内存大小是4G吧。而且一般不同进程间不能够互相使用各自内存的数据。

  当然不同进程间共享数据方法很多,比如之前说的进程间通信binder,socket等等,不过android出了一个共享内存的概念,为的是不同进程间能够共同操作同一块内存数据,比如进程1001往一块共享内存addr里面写数据“hello world”,进程1009往这块共享内存addr读取出“hello world”,也能够往这块共享内存addr写数据“hello china”。这就是共同享用了一块内存的基本概念了(说白了就是同耕一块田)。讲的够仔细了吧,如果不清楚评论区见。

  注意:好像binder传输的数据实现也是类似于共享内存,读者可以自行去了解。

  

  2.

  先说一下等会写程序的思路:

  首先想想代码编译出两个可执行文件后如何操作,打开两个终端,都进入设备adb shell,第一个终端执行进程a,第二个终端执行进程b。在进程a输入一串数据后,在进程b中可以读出这段数据(也能够改写这段数据,读者可以自行添加这部分功能)。

  然后再想想实现的方式,

  进程a:1. 创建共享内存,设置共享内存大小,这时会得到一个fd。2. 获取共享内存地址。3. 先读取地址数据,然后往地址写入数据。4. 把fd通过binder发送给需要使用的进程。

  进程b:1. 通过binder读取到fd。2. 用fd获取共享内存地址。3. 读取共享内存数据,然后往地址写入数据。

  注意:linux一切皆文件,所以文件描述符fd很重要。  

  

  3.

  3.1

  捋清思路后,就可以开始写代码了(android.mk的编写可以参考之前的文章),进程a,命名为mysharememory_a代码如下:

  

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stddef.h>
#include <linux/ipc.h>
#include <linux/shm.h>

#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>

#define DEVASHMEM "/dev/ashmem"
#define SHNAME "hellomemory"
#define MAXBUFSIZE 1024
#define TRANSFDCODE 1000
#define WRITEDATACODE 1001

using namespace android;

int  main(int argc, char *argv[])
{
    int fd = open(DEVASHMEM, O_RDWR);
    if(fd < 0)
    {
        return -1;
    }

    int ret = ioctl(fd, ASHMEM_SET_NAME, SHNAME);
    if(ret < 0){
        close(fd);
        return -1;
    }

    char *get_sh_addr_write = NULL;
    ret = ioctl(fd, ASHMEM_SET_SIZE, MAXBUFSIZE);
    if(ret < 0){
        close(fd);
        return -1;
    }

    get_sh_addr_write = (char*)mmap(NULL, MAXBUFSIZE , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(NULL == get_sh_addr_write)
    {
        return -1;
    }
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->checkService(String16("mybindertag"));
    Parcel data, reply;

    data.writeDupFileDescriptor(fd);
    binder->transact(TRANSFDCODE, data, &reply);

    char input_data[MAXBUFSIZE] = {0};
    while(1)
    {
        printf("read share memory buf is %s\n", get_sh_addr_write);
        printf("please input data to buf :");
        scanf("%s", input_data);
        getchar();

        strcpy(get_sh_addr_write,input_data);
        binder->transact(WRITEDATACODE, data, &reply);
    }
    return ret;
}

  3.2

  mysharememory_b代码如下:

  

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stddef.h>
#include <linux/ipc.h>
#include <linux/shm.h>

#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>

#define DEVASHMEM "/dev/ashmem"
#define SHNAME "hellomemory"
#define MAXBUFSIZE 1024
#define TRANSFDCODE 1000
#define WRITEDATACODE 1001

using namespace android;

int g_sh_fd = 0;
class MyBinderService : public BBinder{
            status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
            {
                int ret;
                char *get_sh_addr_read = NULL;
                int get_sh_size;

                printf("songsong!! **** onTransact ***** code = %d \n",code);
                switch(code)
                {
                    case TRANSFDCODE:
                        g_sh_fd = data.readFileDescriptor();
                        break;

                    case WRITEDATACODE:
                        get_sh_size = ioctl(g_sh_fd, ASHMEM_GET_SIZE,NULL);
                        if(get_sh_size > 0)
                        {
                            get_sh_addr_read = (char*)mmap(NULL, get_sh_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_sh_fd, 0);
                        }
                        else
                        {
                            printf("mmap failed %d\n", get_sh_size);
                            return -1;
                        }
                        printf("what is in the share memory: %s\n", get_sh_addr_read);
                        break;
                    default:

                        break;
                }
                return NO_ERROR;
            }
};

int  main(int argc, char *argv[])
{
    defaultServiceManager()->addService(String16("mybindertag"), new MyBinderService());

    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

  3.3

  回收关闭部分代码可选择添加在mysharememory_b中,如下:

  

    int ret;
    ret = munmap((void*)get_sh_addr_read, get_sh_size);
    if(ret == -1)
    {
        return -1;
    }

    ret = close(g_sh_fd);
    if(ret == -1)
    {
        return -1;
    }

  

  3.4

  演示截图:

  

  4. 为了骗取评论,我不再解释代码,心累。不过您可以把代码直接拷贝去编译执行,再通过调试去理解代码的精髓,也是没问题的。

  

原文地址:https://www.cnblogs.com/songsongman/p/11249974.html

时间: 2024-08-27 21:09:04

Android native进程间通信实例-binder结合共享内存的相关文章

Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务. 传送门: Android native进程间通信实例-binder篇之——简单的单工通信 这次可以用到这个命令了! 1. 随机选取一个java层的服务. adb shell 中输入命令 service list,选取一个服务来做研究,这次看中的是 textservices, 注意第一个服务 by

嵌入式 Linux进程间通信(八)——共享内存

嵌入式 Linux进程间通信(八)--共享内存 一.共享内存 共享内存允许两个或更多进程共享给定的内存区,数据不需要在不同进程间进行复制,是最快的进程间通信方式.使用共享内存唯一需要注意的是多个进程之间对给定存储区的同步访问,但共享内存本身没有提供同步机制,通常使用信号量来实现对共享内存访问的同步. 共享内存编程流程:创建共享内存.映射共享内存.使用共享内存.撤销映射操作.删除共享内存 1.创建共享内存 #include <sys/ipc.h> #include <sys/shm.h&g

(转载)linux下的僵尸进程处理SIGCHLD信号Linux环境进程间通信(五): 共享内存(下)

Linux环境进程间通信(五): 共享内存(下) 在共享内存(上)中,主要围绕着系统调用mmap()进行讨论的,本部分将讨论系统V共享内存,并通过实验结果对比来阐述两者的异同.系统V共享内存指的是把所有共享数据放在共享内存区域(IPC shared memory region),任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面. 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内

进程间通信(三)&mdash;&mdash;共享内存区

1.概述 共享内存区是IPC中最快的,当内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核. 但是这需要某种形式的同步,最常用的是信号量. 不再涉及内核:进程不再通过执行任何进入内核的系统调用来彼此传递数据.内核必须建立允许各个进程共享该内存区的内存映射关系,然后一值管理该内存区.   管道,FIFO和消息队列的问题是,两个进程要交换信息时,这些信息必须经由内核传递. 共享内存区可以绕过这个问题,但是一般必须同步数据.   使用内存映射文件的特性,所有的I/O都不再有内核直接参与

linux进程间通信之System V共享内存详解及代码示例

共享内存是最快最为高效的进程间通信方式,当共享内存映射到共享它的某个进程的地址空间后,进程间的数据传递就不再牵扯到内核,进程可以直接读取内核,不需要通过内核系统调用进行数据拷贝.一般使用情况,从共享内存中写入或读取数据的进程间需要做同步,例如通过信号量,互斥锁去同步. 共享内存有System V 共享内存和Posix共享内存,本文介绍System V 共享内存.System V共享内存头文件及相关函数原型:#include <sys/shm.h> int shmget(key_t key, s

进程间通信(四)—共享内存

我会用几篇博客总结一下在Linux中进程之间通信的几种方法,我会把这个开头的摘要部分在这个系列的每篇博客中都打出来 进程之间通信的方式 管道 消息队列 信号 信号量 共享存储区 套接字(socket) 进程间通信(三)—信号量传送门:http://www.cnblogs.com/lenomirei/p/5649792.html 进程间通信(二)—消息队列传送门:http://www.cnblogs.com/lenomirei/p/5642575.html 进程间通信(一)—管道传送门:http:

进程间通信第二课--信号量 共享内存 消息队列

信号量 程序中存在一部分临界代码,要确保只有一个进程(或一个执行线程)可以进入临界区代码,并拥有对资源的独占式访问权 我们需要一种方法,通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域 这里讲的信号量比在线程的调用中使用的互斥量和信号量更加通用 P:等待,好像位于进入临界区域之前的检查点 V:给予或者释放,好像放弃对临界区域的控制权 P(sv):要是sv的值大于零,就减去1,如果它的值等于零,就挂起该进程的执行 V(sv):要是其他进程因等待sv而被挂起,就让它恢复运行,

Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划中, 我们简要介绍了Android系统的匿名共享内存机制,其中,简要提到了它具有辅助内存管理系统来有效地管理内存的特点,但是没有进一步去了解它是如何实 现的.在本文中,我们将通过分析Android系统的匿名共享内存

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机