一、linux 系统进程通信之内存映射

linux下进程间通信方式一般有管道,消息队列,共享内存,信号量,信号,套接字以及有名管道,其中共享内存的效率最高,而内存映射mmap就是共享内存的一种。下面详细介绍一种使用共享内存实现进程间通信的方式。

在Android系统中属性被大量的使用,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以使用property_get/property_set函数进行读取和写入。一般的应用场景如获取产品名称,版本以及产品的相关配置等。

该部分的源码文件在linux系统中:system/core/init/property_service.c ; system/core/init/property_service.h

一般使用方式如下:                                                                                                                                               property_set("name","value")                     //可以用来设定当前service是否准备OK等                                                            property_get("name", "value","defualt_value")    //可以获取在default.prop中加载完成的系统信息

关于property_service的原理解析如下:

1. workspace

 typedef struct {
    void *data;
    size_t size;
    int fd;
} workspace;  //workspace空间存在一个用于存储数据的地址空间;一个size大小;一个文件的句柄(用于内存映射的句柄)

为了避免高效而且所占用的空间不大,对该size等做了限制

#define PA_COUNT_MAX  247------最大的个数是247
#define PA_INFO_START 1024------空间开始写入的地址为1024字节处
#define PA_SIZE       32768     ------最大的Size是32768

初始workspace函数如下:其中data的创建采用内存映射函数mmap,用dev/__properties__的原因是因为dev为tmpfs

static int init_workspace(workspace *w, size_t size)
{
    void *data;
    int fd;

        /* dev is a tmpfs that we can use to carve a shared workspace
         * out of, so let's do that...
         */
    fd = open("/dev/__properties__", O_RDWR | O_CREAT, 0600);
    if (fd < 0)
        return -1;

    if (ftruncate(fd, size) < 0)
        goto out;

    data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); ------内存映射,属性为MAP_SHARED
    if(data == MAP_FAILED)
        goto out;

    close(fd);

    fd = open("/dev/__properties__", O_RDONLY);
    if (fd < 0)
        return -1;

    unlink("/dev/__properties__");

    w->data = data;----workspace的地址空间指向内存映射的区域
    w->size = size;
    w->fd = fd;
    return 0;

out:
    close(fd);
    return -1;
}

系统的启动文件Init.c会相继调用property.c中的函数property_init()和start_property_service();

第一个函数执行的操作是init_property_area(),即调用初始化workspace;接着会load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT); 该函数的目的是将default.prop中的属性加载到内存映射中

第二个函数执行的操作是将/system/build.prop, /system/default.prop, data/local.prop中属性加载到内存映射;同时创建socket并启用listen(fd, 8),监听socket通信;而且该文件中定义void handle_property_set_fd()函数用于轮询send函数

其他进程如何通过上述property_set("name","value");property_get("name", "value","defualt_value")

源码文件如下:system/core/libcutils/properties.c,我们看到会调用send函数,这样通信就建立

猜你喜欢

转载自blog.csdn.net/w1012747007/article/details/79900519