1. 程式人生 > >一、linux 系統程序通訊之記憶體對映

一、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函式,這樣通訊就建立