Linux——进程间通信(system V共享内存)

system V共享内存

  • [system V共享内存](#system V共享内存)
    • 概念
    • [System V 共享内存的定义方式](#System V 共享内存的定义方式)
    • 函数详解
    • [System V 共享内存的本质](#System V 共享内存的本质)
    • [System V 共享内存与匿名管道的不同](#System V 共享内存与匿名管道的不同)
    • [System V 共享内存的原理与底层解读](#System V 共享内存的原理与底层解读)
    • 分步操作案例
    • 通信案例

system V共享内存

概念

System V 共享内存是一种进程间通信(IPC)机制,允许多个进程共享同一块内存区域。与管道不同,共享内存不涉及内核缓冲区,而是直接映射到进程的地址空间,因此速度非常快。

System V 共享内存的定义方式

(1)在代码中创建共享内存

在 C 代码中,可以使用以下系统调用来操作共享内存:

  • shmget():创建或获取共享内存段。

  • shmat():将共享内存段附加到进程的地址空间。

  • shmdt():将共享内存段从进程的地址空间分离。

  • shmctl():控制共享内存段(如删除)。

函数详解

复制代码
(1)ftok()

生成一个唯一的键值,用于标识共享内存段。

函数模型:

c 复制代码
key_t ftok(const char *pathname, int proj_id);

参数:

  • pathname:文件路径名(必须存在且可访问)。

  • proj_id:项目 ID(通常为一个字符)。

返回值:

  • 成功:返回生成的键值。

  • 失败:返回 -1。

复制代码
 (2) shmget() 

创建或获取共享内存段。

函数模型:

c 复制代码
int shmget(key_t key, size_t size, int shmflg);

参数:

  • key:共享内存段的键值(通常由 ftok() 生成)。

  • size:共享内存段的大小(以字节为单位)。

  • shmflg:标志位,通常为权限模式(如 0666)与 IPC_CREAT 的组合。

返回值:

  • 成功:返回共享内存段的标识符(shmid)。

  • 失败:返回 -1。

复制代码
(3)shmat()

将共享内存段附加到进程的地址空间。

函数模型:

c 复制代码
void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:

  • shmid:共享内存段的标识符。

  • shmaddr:指定附加地址(通常为 NULL,由系统自动选择)。

  • shmflg:标志位(通常为 0)。

返回值:

  • 成功:返回共享内存段的起始地址。

  • 失败:返回 (void*) -1。

复制代码
(4)shmdt()

将共享内存段从进程的地址空间分离。

函数模型:

c 复制代码
int shmdt(const void *shmaddr);

参数:

  • shmaddr:共享内存段的起始地址(由 shmat() 返回)。

返回值:

  • 成功:返回 0。

  • 失败:返回 -1。

复制代码
(5)shmctl()

控制共享内存段(如删除)。

函数模型:

c 复制代码
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数:

  • shmid:共享内存段的标识符。

  • cmd:控制命令(如 IPC_RMID 用于删除)。

  • buf:指向 struct shmid_ds 的指针(通常为 NULL)。

返回值:

  • 成功:返回 0。

  • 失败:返回 -1。

System V 共享内存的本质

(1)内核中的共享内存段

共享内存段是内核中的一块内存区域,由内核分配和管理。

每个共享内存段有一个唯一的标识符(shmid)。

(2)进程地址空间映射

进程通过 shmat() 将共享内存段映射到自己的地址空间。

映射后,进程可以直接访问共享内存中的数据。

(3)同步机制

共享内存本身不提供同步机制,需要结合信号量或互斥锁来避免竞争条件。

System V 共享内存与匿名管道的不同

特性 System V 共享内存 管道(Pipe)
通信方式 直接共享内存区域 通过内核缓冲区传递数据
速度 非常快,无需内核介入 较慢,涉及内核缓冲区拷贝
同步机制 需要额外同步机制(如信号量) 无需额外同步机制
进程关系 可用于无亲缘关系的进程 仅用于具有亲缘关系的进程
生命周期 持久存在,直到显式删除 随进程结束而销毁
使用场景 大数据量、高性能要求的通信 小数据量、简单通信
通信方向 双向 单向
缓冲区大小 由用户指定 通常为 64KB
内核实现 通过 struct shmid_kernel 管理 通过 pipe_inode_info 管理
适用性 适用于无亲缘关系的进程 适用于有亲缘关系的进程
删除方式 使用 shmctl() 显式删除 随进程结束自动销毁

System V 共享内存的原理与底层解读

(1)内核数据结构

共享内存段在内核中通过 struct shmid_kernel 管理。

每个共享内存段包含以下信息:

  • 唯一标识符(shmid)。

  • 内存大小。

  • 附加的进程数。

  • 权限信息。

(2)内存映射

进程通过 shmat() 将共享内存段映射到自己的地址空间。

映射后,进程可以直接读写共享内存。

(3)同步机制

共享内存本身不提供同步机制,需要结合信号量或互斥锁来避免竞争条件。

分步操作案例

复制代码
以下是一个完整的案例,分为 创建、挂载 和 销毁 三个部分。

(1)创建共享内存段

c 复制代码
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    // 生成唯一键值
    key_t key = ftok("shmfile", 65);
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    // 创建共享内存段
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    printf("Shared memory created with ID: %d\n", shmid);
    return 0;
}

(2)挂载共享内存段并写入数据

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main() {
    // 生成唯一键值
    key_t key = ftok("shmfile", 65);
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    // 获取共享内存段
    int shmid = shmget(key, 1024, 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    // 挂载共享内存段
    char *str = (char*) shmat(shmid, (void*)0, 0);
    if (str == (char*) -1) {
        perror("shmat");
        return 1;
    }

    // 写入数据到共享内存
    printf("Writer: Enter data to write: ");
    fgets(str, 1024, stdin);
    printf("Writer: Data written to shared memory: %s\n", str);

    // 分离共享内存段
    if (shmdt(str) == -1) {
        perror("shmdt");
        return 1;
    }

    return 0;
}

(3)挂载共享内存段并读取数据,最后销毁

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    // 生成唯一键值
    key_t key = ftok("shmfile", 65);
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    // 获取共享内存段
    int shmid = shmget(key, 1024, 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    // 挂载共享内存段
    char *str = (char*) shmat(shmid, (void*)0, 0);
    if (str == (char*) -1) {
        perror("shmat");
        return 1;
    }

    // 读取数据
    printf("Reader: Data read from shared memory: %s\n", str);

    // 分离共享内存段
    if (shmdt(str) == -1) {
        perror("shmdt");
        return 1;
    }

    // 销毁共享内存段
    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
        perror("shmctl");
        return 1;
    }

    printf("Shared memory destroyed.\n");
    return 0;
    }

通信案例

(1)写入进程(writer.c)

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main() {
    key_t key = ftok("shmfile", 65); // 生成唯一键值
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT); // 创建共享内存段
    char *str = (char*) shmat(shmid, (void*)0, 0); // 附加共享内存段

    printf("Writer: Enter data to write: ");
    fgets(str, 1024, stdin); // 写入数据到共享内存

    printf("Writer: Data written to shared memory: %s\n", str);
    shmdt(str); // 分离共享内存段
    return 0;
}

(2)读取进程(reader.c)

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    key_t key = ftok("shmfile", 65); // 生成唯一键值
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT); // 获取共享内存段
    char *str = (char*) shmat(shmid, (void*)0, 0); // 附加共享内存段

    printf("Reader: Data read from shared memory: %s\n", str);
    shmdt(str); // 分离共享内存段
    shmctl(shmid, IPC_RMID, NULL); // 删除共享内存段
    return 0;
}
相关推荐
乌恩大侠几秒前
【AI-RAN】在空ubuntu服务器安装环境和生成TV,高达430G文件
服务器·人工智能·ubuntu·fpga开发·o-ru
日取其半万世不竭4 分钟前
用 Netdata 实时监控服务器,比 Prometheus + Grafana 轻量得多
linux·服务器·网络·系统架构·负载均衡·zabbix·grafana
jamon_tan21 分钟前
Linux下cmake构建方法
linux
weisian15121 分钟前
Java并发编程--47-分布式ID生成器:雪花算法(Snowflake)与时钟回拨问题
java·算法·时钟回拨·雪花算法id
itzixiao22 分钟前
L1-066 猫是液体(5分)[java][python]
java·开发语言·python·算法
ytttr87323 分钟前
MATLAB SIFT图像配准实现
算法·机器学习·matlab
JiaWen技术圈25 分钟前
内核子系统 nf_tables 深度解析
linux·服务器·安全·运维开发
小饕27 分钟前
从 Word2Vec 到多模态:词嵌入技术的演进全景
人工智能·算法·机器学习
海参崴-28 分钟前
AVL树完整实现与深度解析
算法
计算机安禾29 分钟前
【Linux从入门到精通】第32篇:Nginx入门——高性能Web服务器搭建
linux·服务器·nginx