1. 程式人生 > 其它 >Linux API-共享記憶體:shmget、shmat、shmdt、shmctl

Linux API-共享記憶體:shmget、shmat、shmdt、shmctl

技術標籤:Linux API程序間通訊linuxc語言

共享記憶體特性

  1. 共享記憶體存在於Linux核心中,可以使資料雙向流動
  2. 系統核心的所有程序都可共享此記憶體空間
  3. 程序可直接訪問共享記憶體,通訊速度快、效率高
  4. 通常用訊號量來實現程序對共享記憶體同步訪問的控制

共享記憶體API

  1. shmget——建立/開啟共享記憶體
  2. shmat——將共享記憶體與當前程序相關聯
  3. shmdt——將當前程序與共享記憶體間脫離關聯
  4. shmctl——操控共享記憶體

一、shmget——建立/開啟共享記憶體

1.原函式

表頭檔案
#include <sys/ipc.h>
#include <sys/shm.h>
定義函式 int shmget(key_t key, size_t size, int shmflg);

函式說明——建立/開啟共享記憶體
key——共享記憶體名稱(ftok()函式獲取
size——開闢共享記憶體大小
shmflg——許可權標誌
返回值——成功返回共享記憶體的識別符號。錯誤返回-1

2.示例

key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享記憶體的許可權為可讀可寫

二、shmat——將共享記憶體與當前程序相關聯

1.原函式

表頭檔案
#include <sys/types.h>
#include <sys/shm.h> 定義函式 void *shmat(int shmid, const void *shmaddr, int shmflg);

函式說明——將共享記憶體與當前程序相關聯
shmid——共享記憶體的識別符號(shmget的返回值)
shmaddr——使用0(核心選擇儲存地址)
shmflg —— 使用0 (記憶體空間可讀可寫)
返回值——成功返回該共享記憶體的首地址。失敗返回-1,錯誤程式碼在errno

2.示例

char *shaddr=shmat(shmid,0,0);//將共享記憶體與當前程序相關聯

三、shmdt——將當前程序與共享記憶體間脫離關聯

1.原函式

表頭檔案
#include <sys/types.h>
#include <sys/shm.h>
定義函式 
int shmdt(const void *shmaddr);

函式說明——將當前程序與共享記憶體間脫離關聯
shmaddr——shmat()的返回值
返回值——成功返回0。出錯返回-1,錯誤程式碼在errno

2.示例

key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享記憶體的許可權為可讀可寫

char *shaddr=shmat(shmid,0,0);//將共享記憶體與當前程序相關聯

shmdt(shaddr);//將當前程序與共享記憶體間脫離關聯

四、shmctl——操控共享記憶體

1.原函式

表頭檔案
#include <sys/ipc.h>
#include <sys/shm.h>
定義函式
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

函式說明——操控共享記憶體
shmid —— shmget的返回值
cmd —— 對共享記憶體的指令
buf —— 記憶體各種資訊的結構體指標(共享記憶體模式和訪問許可權)(預設為0)
返回值——成功返回0。出錯返回-1,錯誤程式碼在errno

2.引數取值
cmd引數:

IPC_STAT:把shmid_ds結構中的資料設定為共享記憶體的當前關聯值,即用共享記憶體的當前關聯值覆蓋shmid_ds的值。    
IPC_SET:如果程序有足夠的許可權,就把共享記憶體的當前關聯值設定為shmid_ds結構中給出的值    
IPC_RMID:刪除共享記憶體段

struct shmid_ds結構體預設如下:

struct shmid_ds {
           struct ipc_perm shm_perm;    /* Ownership and permissions */
           size_t          shm_segsz;   /* Size of segment (bytes) */
           time_t          shm_atime;   /* Last attach time */
           time_t          shm_dtime;   /* Last detach time */
           time_t          shm_ctime;   /* Last change time */
           pid_t           shm_cpid;    /* PID of creator */
           pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
           shmatt_t        shm_nattch;  /* No. of current attaches */
           ...
	  };

3.示例

key_t key=ftok(".",1);
int shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享記憶體的許可權為可讀可寫

char *shaddr=shmat(shmid,0,0);//將共享記憶體與當前程序相關聯

shmdt(shaddr);//將當前程序與共享記憶體間脫離關聯

shmctl(shmid,IPC_RMID,0);//刪除共享記憶體

共享記憶體通訊例程

先寫後讀

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

int main()
{
        key_t key;
        int shmid;
        char *shaddr;

        key=ftok(".",'k');//鍵值獲取

        shmid=shmget(key,1024*4,IPC_CREAT|0600);//此共享記憶體的許可權為可讀可寫

        shaddr=shmat(shmid,0,0);//將共享記憶體與當前程序相關聯

        memset(shaddr,0,strlen(shaddr));
        strcpy(shaddr,"Hello");//先向shaddr記憶體寫資料
        sleep(5);
        printf("write succeed\n");

        printf("read succeed:%s\n",shaddr);//後在shaddr記憶體讀資料

        shmdt(shaddr);//將當前程序與共享記憶體間脫離關聯

        shmctl(shmid,IPC_RMID,0);//刪除共享記憶體

        return 0;
}

先讀後寫

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

int main()
{
        key_t key;
        int shmid;
        char *shaddr;

        key=ftok(".",'k');//鍵值獲取

        shmid=shmget(key,1024*4,0);//此共享記憶體的許可權為可讀可寫

        shaddr=shmat(shmid,0,0);//將共享記憶體與當前程序相關聯

        printf("read succeed:%s\n",shaddr);//先在shaddr記憶體讀資料

        memset(shaddr,0,strlen(shaddr));
        strcpy(shaddr,"World");//後向shaddr記憶體寫資料
        sleep(5);
        printf("write succeed\n");

        shmdt(shaddr);//將當前程序與共享記憶體間脫離關聯

        return 0;
}

執行結果:先執行先寫後讀,再執行先讀後寫
write succeed
read succeed:World

read succeed:Hello
write succeed

喜歡的請收藏,謝謝你。星辰~念