天天看點

程序間通信--共享記憶體

程序間通信前面已經提到了兩種system V版本的通信機制(消息隊列和信号量)。接下來寫一下另外一種system V的通信機制--共享記憶體

共享記憶體在所有的通信方式裡是最快的,這離不開它的機制;先來看看為什麼共享記憶體的速度這麼快

程式間通信--共享記憶體

共享記憶體原理:同一塊實體記憶體被映射到兩個程序各自的虛拟記憶體空間上,然後兩個程序通路自己的虛拟記憶體相當于通路到了另一方的虛拟記憶體,因為它倆之間不需要建立一個獨立的空間,是以通路速度是非常快的,可以說一個程序可以即時看到另一程序的資料更新。

建立共享記憶體用到的函數是shmget,shmget函數原型:

程式間通信--共享記憶體

第一個參數key不用多數,就是他的唯一辨別。第二個參數就是要申請記憶體的大小。第三個參數和前面兩個通信機制的參數一樣,IPC_CREAT和IPC_EXCL。

删除共享記憶體函數shmctl,函數原型為:

程式間通信--共享記憶體

第一個參數為建立的共享記憶體ID,如果是删除就和以前的一樣IPC_RMID,第三個參數為要删的緩沖區,設定為NULL。

既然共享記憶體是直接有實體記憶體映射的結果,那麼另一個程序更新的資料會立馬被另一個程序看到,是以它不存在同步與互斥機制,這時就要自己加一個互斥機制

       引入的互斥機制為關聯記憶體和去關聯記憶體,函數原型為:

程式間通信--共享記憶體

其中shmat為關聯,第一個參數為建立的共享記憶體ID,第二個參數為NULL, 第三個參數為格式,這裡不需要建立,則設定為0。        shmdt為去關聯,參數為要關聯的位址。

為了驗證共享記憶體的實時性,這裡建立一個server和client,server往裡寫,client讀。

#include "comm.h"

static int commShm(int size, int flags)
{
    key_t _k = ftok(PATHNAME, PROJ_ID);
    if(_k < 0){
        perror("ftok");
        return -1;
    }
    
    int shmid = shmget(_k, size, flags);
    if(shmid < 0){
        perror("shmget");
        return -2;
    }
    return shmid;
}

int creatShm(int size)
{
    return commShm(size, IPC_CREAT|IPC_EXCL|0666);
}

int getShm(int size)
{
    return commShm(size, IPC_CREAT);
}
 
int destroyShm(int shmid)
{
    if(shmctl(shmid, IPC_RMID, NULL) < 0){
        perror("shmctl");
        return -1;
    }   
    return 0; 
}  
           
#ifndef _COMM_H_
#define _COMM_H_

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATHNAME "."
#define PROJ_ID 0x6666

int creatShm(int size);
int destroyShm(int shmid);
int getShm(int size);

#endif
           
#include "comm.h"

int main()
{
    int shmid = creatShm(4097);
    sleep(3);
    char *addr = (char *)shmat(shmid, NULL, 0);   
   
    int i = 0;
    while(1){
        addr[i] = 'A' + i;
        i++;
        addr[i] = 0;
        sleep(1);
    }    
    shmdt(addr);
    destroyShm(shmid);
    return 0;
} 
           

client.c

#include "comm.h"

int main()
{
    int shmid = getShm(0);
    sleep(3);
    char *addr = (char *)shmat(shmid, NULL, 0);
   

    while(1){
        printf("%s\n",addr);    
        sleep(1);
    }
    shmdt(addr);
    return 0;
}
           

通過共享記憶體從server 裡往 client裡從A開始寫,一次增加一個字元,然後從client端讀到的現象為:

程式間通信--共享記憶體

因為是通過system調用,是以它的生命周期是随核心。再來看兩條指令;

檢視系統中的共享記憶體: ipcs -m

程式間通信--共享記憶體

删除共享記憶體 : ipcrm -m ID号

程式間通信--共享記憶體

繼續閱讀