进程间通信_共享内存

共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。

特点

  • 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
  • 因为多个进程可以同时操作,所以需要进行同步。
  • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

原型

#include <sys/shm.h>
// 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
int shmget(key_t key, size_t size, int shmflg);
// 连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
void *shmat(int shmid, const void *shmaddr, int shmflg);
// 断开与共享内存的连接:成功返回0,失败返回-1
int shmdt(const void *shmaddr);
// 控制共享内存的相关信息:成功返回0,失败返回-1
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmget函数

// 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
int shmget(key_t key, size_t size, int shmflg);

shmget 用于创建新的共享内存段获取已存在的共享内存段,返回一个唯一的标识符,后续操作都基于这个标识符。

参数详解

key_t key

  • 作用:共享内存段的键值
  • 取值
    • IPC_PRIVATE:创建新的私有共享内存(通常值为0)
    • 自定义键值:通过 ftok() 生成或直接指定整数值
  • 说明:用于标识共享内存段,不同进程使用相同key可访问同一内存

size_t size

  • 作用:共享内存段的大小(字节)
  • 说明
    • 创建新段时:指定需要的内存大小
    • 获取已有段时:可设为0(系统忽略)
    • 实际分配的内存会按页大小(通常4KB)对齐
      int shmflg
  • 作用:标志位和权限的组合
  • 常用标志
    • IPC_CREAT:如果不存在则创建
    • IPC_EXCL:与 IPC_CREAT 一起使用,如果已存在则失败
    • IPC_NOWAIT:如果操作不能立即完成则报错
  • 权限模式(与文件权限类似):
    • 0666:所有用户可读写
    • 0644:用户可读写,组和其他用户只读
      返回值
  • 成功:返回共享内存标识符(正整数)
  • 失败:返回-1,并设置 errno

shmat函数

// 连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
void *shmat(int shmid, const void *shmaddr, int shmflg);

shmat 是 System V 共享内存机制中的关键函数,用于将共享内存段附加到当前进程的地址空间,使进程能够访问和操作共享内存。

一句话理解
shmat 将 shmget 创建的共享内存段映射到当前进程的虚拟地址空间,返回一个指针,进程可以通过这个指针直接读写共享内存。

参数详解

int shmid

  • 作用:共享内存标识符
  • 说明:由 shmget() 函数返回的标识符,指定要附加的共享内存段
    const void *shmaddr
  • 作用:指定附加地址(通常设为NULL让系统自动选择)
  • 取值:
    • NULL:让系统自动选择合适地址(推荐)
    • 具体地址:尝试在指定地址附加(需要对齐和权限)
      int shmflg
  • 作用:附加标志位
  • 常用标志:
  • SHM_RDONLY:以只读方式附加
  • SHM_RND:与 shmaddr 配合使用, Round down address
  • 0:默认读写方式

返回值

  • 成功:返回共享内存段附加到进程地址空间的起始地址
  • 失败:返回 (void *) -1,并设置 errno

strcpy 函数

strcpy 是 C 语言标准库中最基本且最常用的字符串操作函数之一,用于将一个字符串复制到另一个字符串。

一句话理解
strcpy 将源字符串(包括结束符 \0)完整地复制到目标字符串中,覆盖目标原有的内容

原型
#include <string.h>  // 必须包含的头文件
char *strcpy(char *dest, const char *src);
参数说明

char *dest

  • 作用:目标字符串缓冲区
  • 要求:必须有足够的空间存储源字符串及其结束符
    const char *src
  • 作用:源字符串(不会被修改)
  • 要求:必须以 \0 结尾的有效字符串
    返回值
  • 返回目标字符串的指针(即 dest)
  • 方便链式调用,但很少使用
    使用
char *shmaddr;
strcpy("shmaddr,"hello world");

shmdt函数

shmdt 是 System V 共享内存机制中的重要函数,用于将共享内存段从当前进程的地址空间中分离。它完成了共享内存使用的”善后工作”。

一句话理解
shmdt 断开进程与共享内存段的连接,使该内存区域不再对当前进程可访问,但不会删除共享内存段本身。

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);
参数详解

const void *shmaddr

  • 作用:共享内存段在当前进程中的起始地址(shmat返回的起始地址)
  • 说明:必须是之前 shmat() 调用返回的有效地址
  • 要求:必须指向已附加的共享内存段起始位置

返回值

  • 成功:返回 0
  • 失败:返回 -1,并设置 errno

shmctl函数

对已存在的共享内存段执行各种控制操作,例如查询状态修改权限锁定内存以及最重要的——销毁内存段

函数原型

#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数解析

int shmid

  • 含义: 共享内存段的标识符。
  • 来源: 这个 ID 是由之前成功调用 shmget() 函数返回的。
  • 作用: 指定你要操作的是哪一个共享内存段。
    int cmd
  • 含义: 要执行的控制命令。
  • 作用: 这是函数的核心,决定了 shmctl 的行为
命令说明是否需要 buf
IPC_RMID标记删除共享内存段。这是最常用的命令。否 (可设为 NULL)
IPC_STAT获取共享内存段的当前状态信息(如权限、大小、附加进程数等),并将其存入 buf 指向的结构体中。
IPC_SET根据 buf 指向的结构体中的值,来设置共享内存段的某些参数(主要是 shm_perm.uidshm_perm.gidshm_perm.mode)。
SHM_LOCK锁定共享内存段,防止其被交换到磁盘(swap)。(仅超级用户可用)
SHM_UNLOCK解锁共享内存段。(仅超级用户可用)
IPC_INFO / SHM_INFO获取系统级的共享内存限制和参数信息(更高级的用法)。
struct shmid_ds *buf
  • 含义: 指向 struct shmid_ds 结构体的指针。该结构体用于存放共享内存段的元数据和状态信息。
  • 作用: 根据 cmd 的不同,这个参数有两种用途:
    1. 输入: 当 cmd 为 IPC_SET 时,buf 提供了要设置的新值。
    2. 输出: 当 cmd 为 IPC_STAT 时,函数会将共享内存段的信息填充到这个结构体中。

struct shmid_ds 结构体定义(简化):

struct shmid_ds {
    struct ipc_perm shm_perm;   /* 所有权和权限信息 */
    size_t          shm_segsz;  /* 段的大小(字节) */
    time_t          shm_atime;  /* 最后一次附加时间 */
    time_t          shm_dtime;  /* 最后一次分离时间 */
    time_t          shm_ctime;  /* 最后一次改变时间 */
    pid_t           shm_cpid;   /* 创建者的PID */
    pid_t           shm_lpid;   /* 最后操作者的PID */
    shmatt_t        shm_nattch; /* 当前附加进程的数量 */
    ...
};

其中的 struct ipc_perm 包含了权限信息:

struct ipc_perm {
    key_t          __key;    /* 创建时提供的key */
    uid_t          uid;      /* 所有者的有效UID */
    gid_t          gid;      /* 所有者的有效GID */
    uid_t          cuid;     /* 创建者的有效UID */
    gid_t          cgid;     /* 创建者的有效GID */
    unsigned short mode;     /* 权限位 (RWX) */
    unsigned short __seq;    /* 序列号 */
};

返回值

  • 成功: 返回 0
  • 失败: 返回 -1,并设置全局变量 errno 以指示错误类型(例如 EINVAL 无效的 shmidEPERM 权限不足等)。

代码

写的代码 shmw.c

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


//       int shmget(key_t key, size_t size, int shmflg);
//       void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg);
//       int shmdt(const void *shmaddr);

int main()
{       
        int shmid;//用来存储共享内存的id
        char *shmaddr;//shmat返回的起始地址

        key_t key;
        key = ftok(".",1);//创建索引值

        shmid = shmget(key,1024 * 4,IPC_CREAT|0666);//创建共享内存空间
        if(shmid == -1)
        {
                printf("shmget noOK\n");
                exit(-1);
        }

        shmaddr = shmat(shmid,NULL,0);//挂载

        printf("shmat ok\n");
        strcpy(shmaddr,"hello world");//将字符串内容写进shmaddr里面

        sleep(5);
        shmdt(shmaddr);//断开连接
        shmctl(shmid,IPC_RMID,0);//删除内存

        printf("quit\n");

        return 0;
} 

读的代码 shmr.c

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

//       int shmget(key_t key, size_t size, int shmflg);
//       void *shmat(int shmid, const void *_Nullable shmaddr, int shmflg);
//       int shmdt(const void *shmaddr);

int main()
{
    int shmid;
    char *shmaddr;

    key_t key;
    key = ftok(".",1);

    shmid = shmget(key,1024 * 4,0);//获取共享内存不创建
    if(shmid == -1)
    {
            printf("shmget noOK\n");
            exit(-1);
    }

    shmaddr = shmat(shmid,NULL,0);//挂载

    printf("shmat ok\n");
    printf("data: %s\n",shmaddr);

    shmdt(shmaddr);

    printf("quit\n");
    return 0;
}
重点

写入

  • 索引值->创建共享内存->挂载-> 写入内容->等待读取->断开内存连接->删除内存
    读取
  • 索引值->获取共享内存不创建->挂载-> 打印内容->断开内存连接

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇