Android native inter-process communication instance -binder combination of shared memory

  Driven by android source directory, usually have shared memory associated implementation source directory is: kernel \ drivers \ staging \ android \ ashmem.c. But this article is not to explain android shared memory function realization principle, but in terms of how to use it.

  1. 

  In linux, different processes have their own separate memory space, 32-bit operating system, the process can seem a 4G memory size is right. And generally can not use their own memory data between different processes from each other.

  Of course, the process of sharing data between different many ways, such as inter-process communication said before binder, socket and so on, but the android out the concept of a shared memory, in order to be able to co-operation between different processes the same memory data, such as to process 1001 addr inside a shared memory data write "hello world", process 1009 to this shared memory addr read "hello world", it is possible to write data to this shared memory addr "hello china". This is common to enjoy the basic concept of the piece of memory (it means a field with plow). Talking about it carefully enough, if not clear, see the comments section.

  Note: if the data transmission is achieved binder is similar to shared memory, readers can get to know yourself.

  

  2.

  Let me talk about the idea and so will write the program:

  First, consider how the code is compiled executables two operations to open the two terminals have entered the device adb shell, the first terminal performs a process a, a second terminal performs processes b. After the process in a series of data input a, b in the process of this data can be read out (this data can be rewritten, readers can add their own function of this part).

  Then think of ways to achieve,

  Process a:. 1 to create a shared memory, set the shared memory size, then you get a fd. 2. Get shared memory address. 3. After the first reading address data, and write data to the address. 4. The process requires the use of fd sent through the binder.

  Process b:. 1 fd read through the binder. 2. Get shared memory address with fd. 3. The shared memory data is read, and write data to the address.

  Note: linux everything is a file, the file descriptor fd is very important.  

  

  3. 

  3.1

  After the stroke clear ideas, you can start writing code (written android.mk can reference previous article), process a, named mysharememory_a code is as follows:

  

#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 code is as follows:

  

#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

  Alternatively recovered part of the code off mysharememory_b added as follows:

  

    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 

  Demo screenshot:

  

 

 

   4. To cheat a comment, I will not explain the code, tired heart. However, you can directly copy the code to the compiler implementation, and through commissioning to understand the essence of the code is not the problem.

  

Guess you like

Origin www.cnblogs.com/songsongman/p/11249974.html