天天看點

Linux程序間通信之共享記憶體

一,共享記憶體

  核心管理一片實體記憶體,允許不同的程序同時映射,多個程序可以映射同一塊記憶體,被多個程序同時映射的實體記憶體,即共享記憶體。

  映射實體記憶體叫挂接,用完以後解除映射叫脫接。

1,共享記憶體的特點:

  優點:是最快的IPC。

  缺點:要程式設計者自己實作對共享記憶體互斥通路。如何實作?

2,程式設計模型:具體函數的用法可以用man手冊檢視(強力推薦)

程序A: writeshm.c

     1) 獲得key, ftok()

     2) 使用key來建立一個共享記憶體 shmget()

     3) 映射共享記憶體(得到虛拟位址), shmat()

     4) 使用共享記憶體, 往共享記憶體中寫入資料

     5) 解除映射 shmdt()

     6) 如果共享記憶體不再使用,可以使用shmctl()銷毀共享記憶體

程序B: readshm.c     

  1) 獲得key, ftok()     

  2) 使用key來獲得一個共享記憶體 shmget()     

  3) 映射共享記憶體(得到虛拟位址), shmat()     

  4) 使用共享記憶體, 讀取共享記憶體中的資料     

  5) 解除映射 shmdt()     

3,執行個體

程序A:

// writeshm.c

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>

int main()
{
    // 生成一個key
    key_t key = ftok("./", 66);

    // 建立共享記憶體,傳回一個id
    int shmid = shmget(key, 8, IPC_CREAT|0666|IPC_EXCL);
    if(-1 == shmid)
    {
        perror("shmget failed");
        exit(1);
    }

    // 映射共享記憶體,得到虛拟位址
    void *p = shmat(shmid, 0, 0);
    if((void*)-1 == p)
    {
        perror("shmat failed");
        exit(2);
    }

    // 寫共享記憶體
    int *pp = p;
    *pp = 0x12345678;
    *(pp + 1) = 0xffffffff;

    // 解除映射
    if(-1 == shmdt(p))
    {
        perror("shmdt failed");
        exit(3);
    }
    printf("解除映射成功,點選回車銷毀共享記憶體\n");
    getchar();

    // 銷毀共享記憶體
    if(-1 == shmctl(shmid, IPC_RMID, NULL))
    {
        perror("shmctl failed");
        exit(4);
    }

    return 0;
}      

程序B:

// readshm.c

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>

int main()
{
    // 生成一個key
    key_t key = ftok("./", 66);

    // 擷取共享記憶體,傳回一個id
    int shmid = shmget(key, 0, 0);
    if(-1 == shmid)
    {
        perror("shmget failed");
        exit(1);
    }

    // 映射共享記憶體,得到虛拟位址
    void *p = shmat(shmid, 0, 0);
    if((void*)-1 == p)
    {
        perror("shmat failed");
        exit(2);
    }

    // 讀共享記憶體
    int x = *(int *)p;
    int y = *((int *)p + 1);
    printf("從共享記憶體中都取了:0x%x 和 0x%x \n", x, y);

    // 解除映射
    if(-1 == shmdt(p))
    {
        perror("shmdt failed");
        exit(3);
    }

    return 0;
}      

 運作結果:

writeshma:

Linux程式間通信之共享記憶體

readshma:

Linux程式間通信之共享記憶體

繼續閱讀