Linux 進程間通信【共享內存】

共享內存

  • 什麼是共享內存
    共享內存就是允許兩個不相關的進程訪問同一個邏輯內存。共享內存是在兩個正在運行的進程之間共享和傳遞數據的一種非常有效的方式。不同進程之間共享的內存通常安排爲同一段物理內存。進程可以將同一段共享內存連接到它們自己的地址空間中,所有進程都可以訪問共享內存中的地址,就好像它們是由用C語言函數malloc()分配的內存一樣。而如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。
    特別提醒:共享內存並未提供同步機制,也就是說,在第一個進程結束對共享內存的寫操作之前,並無自動機制可以阻止第二個進程開始對它進行讀取。所以我們通常需要用其他的機制來同步對共享內存的訪問,例如前面說到的信號量。
  • 共享內存的使用
    與信號量一樣,在Linux中也提供了一組函數接口用於使用共享內存,而且使用共享共存的接口還與信號量的非常相似,而且比使用信號量的接口來得簡單。它們聲明在頭文件 sys/shm.h 中。
    • shmget()函數
      該函數用來創建共享內存,它的原型爲:
      int shmget(key_t key, size_t size, int shmflg);
      成功時返回一個與key相關的共享內存標識符(非負整數),用於後續的共享內存函數。調用失敗返回-1.
    • shmat()函數
      第一次創建完共享內存時,它還不能被任何進程訪問,shmat()函數的作用就是用來啓動對該共享內存的訪問,並把共享內存連接到當前進程的地址空間。它的原型如下:
      void *shmat(int shm_id, const void *shm_addr, int shmflg);
      成功時返回一個指向共享內存第一個字節的指針,如果調用失敗返回-1.
    • shmdt()函數
      該函數用於將共享內存從當前進程中分離。注意,將共享內存分離並不是刪除它,只是使該共享內存對當前進程不再可用。它的原型如下:
      int shmdt(const void *shmaddr);
      調用成功時返回0,失敗時返回-1.
    • shmctl()函數
      與信號量的semctl()函數一樣,用來控制共享內存,它的原型如下:
      int shmctl(int shm_id, int command, struct shmid_ds *buf);
  • 例,進程A shmwrite.c 源碼
  • #include <stdlib.h>
    #include <sys/types.h>  
    #include <sys/ipc.h>  
    #include <sys/shm.h>  
    #include <stdio.h>  
    #include <error.h>  
      
    #define SHM_SIZE    4096  
    #define SHM_MODE    (SHM_R | SHM_W) /* user read/write */  
      
    int main(void)  
    {  
        int  shmid;  
        char *shmptr;  
      
        if ( (shmid = shmget(0x44, SHM_SIZE, SHM_MODE | IPC_CREAT)) < 0)  
            perror("shmget");  
      
        if ( (shmptr = shmat(shmid, 0, 0)) == (void *) -1)  
            perror("shmat");  
          
        /* 往共享內存寫數據 */  
        sprintf(shmptr, "%s", "hello, world");  
      
        exit(0);  
    } 

    進程B shmread.c 源碼

  • #include <stdlib.h>
    #include <sys/types.h>  
    #include <sys/ipc.h>  
    #include <sys/shm.h>  
    #include <stdio.h>  
    #include <error.h>  
      
    #define SHM_SIZE    4096  
    #define SHM_MODE    (SHM_R | SHM_W | IPC_CREAT) /* user read/write */  
      
    int main(void)  
    {  
        int     shmid;  
        char    *shmptr;  
      
        if ( (shmid = shmget(0x44, SHM_SIZE, SHM_MODE | IPC_CREAT)) < 0)  
            perror("shmget");  
      
        if ( (shmptr = shmat(shmid, 0, 0)) == (void *) -1)  
            perror("shmat");  
      
        /* 從共享內存讀數據 */  
        printf("%s\n", shmptr);  
      
        exit(0);  
    }

    編譯

  • 運行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章