Linux-共享內存通訊

Linux共享存儲通訊

內容

  • 建立共享存儲區實現進程通訊

機理說明

共享存儲區(Share Memory)是Linux系統中通訊速度最高的通訊機制。該機制中共享內存空間和進程的虛地址空間知足多對多的關係。即一個共享內存空間能夠映射多個進程的虛地址空間,一個進程的虛地址空間又能夠鏈接多個共享存儲區。當進程間預利用共享存儲區通訊時,先要在主存中創建一個共享存儲區,而後將它附接到本身的虛地址空間。該機制只爲進程提供了用於實現通訊的共享存儲區和對共享存儲區進行操做的手段,然而並未提供對該區進行互斥訪問及進程同步的措施linux

調用函數說明

建立共享內存

shmget(key ,size ,flag)數組

功能:得到一個內部標識爲shmid的共享存儲區。數據結構

語法:int shmget = int shmget(key_t key ,int size ,int flag);函數

參數說明:操作系統

​ key 共享存儲區關鍵字,可由用戶指定。若使用IPC_PRIVATE則其值由系統產生。3d

​ size 存儲區大小(字節數)。若存儲區定義爲字符型,則大小爲定義的字符個數;若定義爲整型,大小能夠用sizeof(int)加以定義code

​ flag 用戶設置的標誌或訪問方式,如0666|IPC_CREAT,表示任意進程皆可讀可寫blog

操做容許權 八進制數 操做容許權 八進制數
用戶可讀 0400 小組可寫 0020
用戶可寫 0200 其它可讀 0004
小組可讀 0040 其它可寫 0002

附接共享內存

字符型共享內存:進程

shmat(int shmid ,char shmadddr ,int msgflg ,ulong raddr);內存

數值型共享內存:

shmat(int shmid ,int shmadddr ,int msgflg ,ulong raddr);

語法格式:

字符型共享內存:

viraddr = (char *) shmat (shmid ,shmaddr ,shmflag);

viraddr = (int *) shmat (shmid ,shmaddr ,shmflag);

參數說明:

​ shmid共享存儲區的描述符,可由shmget()的返回值獲得。

​ shmaddr用戶提供的共享存儲區附接的虛地址。

​ shmflag規定存儲區的操做權限。如,SHM_RND則表示操做系統在必要時捨去地址;SHM_RDONLY則表示只容許讀,shmflag爲0表示可讀可寫。

斷開共享內存

shmdt(viraddr)

參數說明:

​ viraddr系統調用shmat()所返回的虛地址。

返回值:

​ 函數被正確調用則返回0,錯誤返回-1

shmctl(int shmid ,int cmd ,struct shmid_ds * buf);

功能:對共享內存進行操做控制

參數說明:

​ shmid共享存儲區的描述符,可由shmget()的返回值獲得。

​ buf用戶級數據結構地址,可爲0。

​ cmd規定的操做類型

操做代碼 含義
IPC_STAT 返回指定shmid數據結構的狀態信息,放置於*buf中,必須有讀取容許權
IPC_SET 設置指定shmid的有效用戶和操做存取權
IPC_RMID 刪除指定shmid以及與它相關的共享存儲區的數據結構
SHM_LOCK 在內存中鎖定指定的共享存儲區,必須是root才能執行

shmctl(shmid ,IPC_RMID ,0); //撤銷共享內存區

實現思路

send:

  • shmget()建立或者獲取指定key值的共享內存
  • shmat()將該內存附接到本身的虛擬地址空間
  • 將消息寫入共享內存
    • 字符:
      • 以追加方式寫入,strcat(viraddr ,buffer)
      • 以覆蓋方式寫入,strcpy(viraddr ,buffer)
    • 數字:
      • 直接賦值
      • 操做數組
  • shmdt()斷開共享內存

receive:

  • shmget()建立或者獲取指定key值的共享內存
  • shmat()將該內存附接到本身的虛擬地址空間
  • 輸出信息
  • shmdt()斷開共享內存
  • shmctl()撤銷內存

實例

send

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/*共享內存 share memory 實現的進程通訊*/
main()
{
    int shmid;
    char *viraddr;
    char buffer[BUFSIZ];
    
    shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    while(1)
    {
        puts("Enter some text:");
        fgets(buffer,BUFSIZ,stdin);/*從標準輸入設備讀入一行字符串,stdin是標準輸入,C標準庫裏面的一                                     個全局變量*/
        strcat(viraddr,buffer);     /*字符串追加函數*/
        if(strncmp(buffer,"end",3)==0)/*比較兩個字符串數組*/
            break;
    }
    shmdt(viraddr);
    exit(0);
}

receive

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

main()
{
    int shmid;
    char *viraddr;
    
    shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    printf("Your message is :\n%s",viraddr);
    shmdt(viraddr);                         /*斷開鏈接*/
    shmctl(shmid,IPC_RMID,0);               /*撤銷共享內存*/
    exit(0); 
}

運行結果

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/* 父進程與子進程間的通訊,子進程寫信息到共享內存中,父進程讀取該信息
BUFSIZ爲全局量定義在<stdlib.h>,8192 
使用exit(0)和wait(0)進行同步*/
main()
{
    int chld,shmid;
    char *viraddr;
    char buffer[BUFSIZ];
    
    shmid=shmget(IPC_PRIVATE,BUFSIZ,0666|IPC_CREAT);
    viraddr=(char*)shmat(shmid,0,0);
    
    while((chld=fork())==-1);
    if(chld==0)
    {                                   /*子進程塊*/
        while(1)
        {
            puts("Enter some text:");   /*寫信息到共享內存*/
            fgets(buffer,BUFSIZ,stdin); /*用戶輸入信息*/
            strcat(viraddr,buffer);     /*附接到進程的虛擬空間*/
            if(strncmp(buffer,"end",3)==0)
                break;                  /*輸入end結束*/
        }
        exit(0);
    }
    else
    {                                   /*父進程塊*/
        wait(0);
        printf("Your message is:\n%s",viraddr);
        
        shmdt(viraddr);                 /*斷開共享內存*/
        shmctl(shmid,IPC_RMID,0);       /*釋放共享內存*/
        exit(0);
    }
}

運行結果

相關文章
相關標籤/搜索