linux ipc通信 - 共享內(nèi)存

函數(shù)介紹

/* The following System V style IPC functions implement a shared memory
   facility.  The definition is found in XPG4.2.  */

/* Shared memory control operation.  */
int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf);

/* Get shared memory segment.  */
int shmget (key_t __key, size_t __size, int __shmflg) ;

/* Attach shared memory segment.  */
void *shmat (int __shmid, const void *__shmaddr, int __shmflg);

/* Detach shared memory segment.  */
int shmdt (const void *__shmaddr) ;
shmget 說明
/* Get shared memory segment.  */
int shmget (key_t __key, size_t __size, int __shmflg) ;
  • key shmget 中的key與shmid對應真慢,可以用ftok來生成key或者指定IPC_PRIVATE
  • size 共享內(nèi)存的大小
  • flag 權(quán)限設(shè)置
/* Mode bits for `msgget', `semget', and `shmget'.  */
#define IPC_CREAT   01000       /* Create key if key does not exist. */
#define IPC_EXCL    02000       /* Fail if key exists.  */
#define IPC_NOWAIT  04000       /* Return error on wait.  */
后面3位是用戶毅臊、用戶組、其他用戶的讀寫執(zhí)行權(quán)限黑界,如 0777
  • 返回值 成功返回 shmid管嬉,用戶后面的讀寫id,失敗返回負數(shù)
shmctl 說明
/* Shared memory control operation.  */
int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf);
  • shmid 通過shmget返回的id
  • cmd 控制選項
#define IPC_RMID    0       /* Remove identifier.  */
#define IPC_SET     1       /* Set `ipc_perm' options.  */
#define IPC_STAT    2       /* Get `ipc_perm' options.  */
/* Commands for `shmctl'.  */
#define SHM_LOCK    11      /* lock segment (root only) */
#define SHM_UNLOCK  12      /* unlock segment (root only) */
后面兩個選項只適用于linux 和solaris
lock :當內(nèi)存不夠時不允許與外存換入換出
unlock 反之
  • buf set 和get的結(jié)構(gòu)體信息朗鸠,如可以通過get獲取共享內(nèi)存的大小
/* Data structure describing a shared memory segment.  */
struct shmid_ds
  {
    struct ipc_perm shm_perm;       /* operation permission struct */
    size_t shm_segsz;           /* size of segment in bytes */
    __time_t shm_atime;         /* time of last shmat() */
#ifndef __x86_64__
    unsigned long int __glibc_reserved1;
#endif
    __time_t shm_dtime;         /* time of last shmdt() */
#ifndef __x86_64__
    unsigned long int __glibc_reserved2;
#endif
    __time_t shm_ctime;         /* time of last change by shmctl() */
#ifndef __x86_64__
    unsigned long int __glibc_reserved3;
#endif
    __pid_t shm_cpid;           /* pid of creator */
    __pid_t shm_lpid;           /* pid of last shmop */
    shmatt_t shm_nattch;        /* number of current attaches */
    __syscall_ulong_t __glibc_reserved4;
    __syscall_ulong_t __glibc_reserved5;
 };
shmat說明
/* Attach shared memory segment.  */
void *shmat (int __shmid, const void *__shmaddr, int __shmflg);
  • shmid 通過get返回的id
  • shmaddr 如何為空蚯撩,則系統(tǒng)給你返回映射的地址,如果該參數(shù)非空烛占,會映射到此地址上
    為了不必要的麻煩胎挎,一般傳遞空
  • flag 在地址傳遞非空的時候用于設(shè)置SHM_RND, 好像是什么地址隨機之類的
    同樣不用自找麻煩,傳遞0就完事了

代碼展示

/**
 * @file shm_lsw.c
 * @author 李斯文 (lisiwen945@163.com)
 * @brief 共享內(nèi)存的接口測試函數(shù)
 * @version 0.1
 * @date 2021-01-28
 *
 * @copyright Copyright (c) 2021
 *
 */
#include "apue.h"
#include <sys/shm.h>
#include <fcntl.h>
#include <errno.h>

void shm_send()
{
    int id = shmget(11, 1024, 0777);
    if (id < 0) {
        printf("%s shmget error errno %d\n", __func__, errno);
        return;
    } else {
        printf("shmget success id %d\n", id);
    }
    struct shmid_ds ds;
    if (shmctl(id, IPC_STAT, &ds) < 0) {
        printf("func %s line %d error\n", __func__, __LINE__);
        return;
    } else {
        printf("get share memory size %ld\n", ds.shm_segsz);
    }

    char * buf = shmat(id, 0, 0);
    if (buf == NULL) {
        printf("func %s line %d error\n", __func__, __LINE__);
        return;
    }
    char msg[] = "lisiwen debug";
    strcpy(buf, msg);
}

void shm_recv()
{
    int id = shmget(11, 1024, 0777);
    if (id < 0) {
        printf("%s shmget error errno %d\n", __func__, errno);
        return;
    } else {
        printf("shmget success id %d\n", id);
    }
    struct shmid_ds ds;
    if (shmctl(id, IPC_STAT, &ds) < 0) {
        printf("func %s line %d error\n", __func__, __LINE__);
        return;
    } else {
        printf("get share memory size %ld\n", ds.shm_segsz);
    }
    char * buf = shmat(id, 0, 0);
    printf("get msg %s\n", buf);
}

void shm_del()
{
    int id = shmget(11, 1024, 0777);
    if (id < 0) {
        printf("%s shmget error errno %d\n", __func__, errno);
        return;
    } else {
        printf("shmget success id %d\n", id);
    }
    if (shmctl(id, IPC_RMID, NULL) < 0) {
        printf("func %s line %d error\n", __func__, __LINE__);
        return;
    } else {
        printf("remove share memory %d success\n", id);
    }
}

void shm_create()
{
    int id = shmget(11, 1024, IPC_CREAT|IPC_EXCL|0777);
    if (id < 0) {
        printf("create shared memory error errno %d\n", errno);
    } else {
        printf("shmget success id %d\n", id);
    }
}


int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("%s arg", argv[0]);
        return 0;
    }
    if (strcmp(argv[1], "send") == 0) {
        shm_send();
    } else if (strcmp(argv[1], "recv") == 0) {
        shm_recv();
    } else if (strcmp(argv[1], "del") == 0) {
        /* 使用ipcrm -q id也可以刪除 */
        shm_del();
    } else if (strcmp(argv[1], "create") == 0) {
        shm_create();
    }
}

運行結(jié)果

ipcs 可以查看ipc的詳細信息 -m表示共享內(nèi)存
swing@ubun:~/code/apue.3e/ipc1$ ipcs -m
------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權(quán)限     字節(jié)     連接數(shù)  狀態(tài)      
0x00000000 8          swing      600        67108864   2          目標       
0x00000000 11         swing      600        524288     2          目標       
0x00000000 12         swing      600        524288     2          目標       
0x00000000 13         swing      600        524288     2          目標       
0x00000000 20         swing      600        524288     2          目標       

創(chuàng)建共享內(nèi)存犹菇,可以看到多路一個id為23的內(nèi)存德迹,大小為1024字節(jié)
swing@ubun:~/code/apue.3e/ipc1$ ./shm_lsw create
shmget success id 23
swing@ubun:~/code/apue.3e/ipc1$ ipcs -m
------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權(quán)限     字節(jié)     連接數(shù)  狀態(tài)      
0x00000000 8          swing      600        67108864   2          目標       
0x00000000 11         swing      600        524288     2          目標       
0x00000000 12         swing      600        524288     2          目標       
0x00000000 13         swing      600        524288     2          目標       
0x00000000 20         swing      600        524288     2          目標       
0x0000000b 23         swing      777        1024       0       

swing@ubun:~/code/apue.3e/ipc1$ ./shm_lsw send
shmget success id 23
get share memory size 1024

swing@ubun:~/code/apue.3e/ipc1$ ./shm_lsw recv
shmget success id 23
get share memory size 1024
get msg lisiwen debug

swing@ubun:~/code/apue.3e/ipc1$ ./shm_lsw del
shmget success id 23
remove share memory 23 success

swing@ubun:~/code/apue.3e/ipc1$ ipcs -m
------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權(quán)限     字節(jié)     連接數(shù)  狀態(tài)      
0x00000000 8          swing      600        67108864   2          目標       
0x00000000 11         swing      600        524288     2          目標       
0x00000000 12         swing      600        524288     2          目標       
0x00000000 13         swing      600        524288     2          目標       
0x00000000 20         swing      600        524288     2          目標       
swing@ubun:~/code/apue.3e/ipc1$
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市项栏,隨后出現(xiàn)的幾起案子浦辨,更是在濱河造成了極大的恐慌蹬竖,老刑警劉巖沼沈,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異币厕,居然都是意外死亡列另,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門旦装,熙熙樓的掌柜王于貴愁眉苦臉地迎上來页衙,“玉大人,你說我怎么就攤上這事阴绢〉昀郑” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵呻袭,是天一觀的道長眨八。 經(jīng)常有香客問我,道長左电,這世上最難降的妖魔是什么廉侧? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮篓足,結(jié)果婚禮上段誊,老公的妹妹穿的比我還像新娘。我一直安慰自己栈拖,他們只是感情好连舍,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涩哟,像睡著了一般烟瞧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上染簇,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天参滴,我揣著相機與錄音,去河邊找鬼锻弓。 笑死砾赔,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播暴心,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼妓盲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了专普?” 一聲冷哼從身側(cè)響起悯衬,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎檀夹,沒想到半個月后筋粗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡炸渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年娜亿,在試婚紗的時候發(fā)現(xiàn)自己被綠了检号。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坯癣。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖带猴,靈堂內(nèi)的尸體忽然破棺而出吼畏,到底是詐尸還是另有隱情督赤,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布泻蚊,位于F島的核電站躲舌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏藕夫。R本人自食惡果不足惜孽糖,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毅贮。 院中可真熱鬧办悟,春花似錦、人聲如沸滩褥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瑰煎。三九已至铺然,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間酒甸,已是汗流浹背魄健。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留插勤,地道東北人沽瘦。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓革骨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親析恋。 傳聞我的和親對象是個殘疾皇子良哲,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容