Linux详解共享内存

Linux详解共享内存

  • 1. Linux详解共享内存
  • 2. 共享内存简介
  • 3. 共享内存的原理
  • 4. 共享内存函数
    • 4.1 shmget 函数 - 创建共享内存
    • 4.2 ftok 函数 - 获取 key 值
    • 4.3 shmat 函数 - 连接共享内存到进程地址空间
    • 4.4 shmdt 函数 - 断开连接共享内存
    • 4.5 shmctl 函数 - 控制共享内存
  • 5. 共享内存的代码实现

1. Linux详解共享内存

在Linux操作系统中,共享内存是一种用于实现进程间通信(IPC)的机制,允许多个进程访问同一块内存区域。共享内存是一种高效的IPC方式,因为它允许进程直接共享数据,而无需进行数据的复制和传输。

2. 共享内存简介

什么是共享内存?
共享内存是操作系统中的一块内存区域,用于多个进程之间直接访问和共享数据。通过获取内存地址,进程可以实现数据的读写操作。

共享内存优点
适用范围广:可用于父子进程和非父子进程通信。
快速访问:直接访问内存,速度相对较快,无需通过文件系统。

共享内存缺点
不支持阻塞等待:无内建阻塞机制,读写端可以同时访问内存。
缺乏访问控制:无法主动停止读写,需要额外的同步机制。

3. 共享内存的原理

共享内存允许多个进程访问同一块物理内存,这使得它成为一种快速且有效的进程间通信方式。以下是共享内存的基本原理:
Linux详解共享内存_第1张图片

内核空间分配内存: 在内核空间中,通过系统调用(如shmget)来分配一块共享内存区域。

进程连接共享内存: 进程通过系统调用(如shmat)将共享内存区域连接到它们的地址空间中。

进程访问共享内存: 连接后,进程可以直接在共享内存区域进行读写操作,就像访问自己的内存一样。

内核管理同步: 为了确保多个进程之间的同步,通常需要使用信号量等机制来管理对共享内存的访问。

4. 共享内存函数

4.1 shmget 函数 - 创建共享内存

#include 
#include 
int shmget(key_t key, size_t size, int shmflg);

key 参数:
用于标识共享内存的唯一键值,通常通过 ftok 函数生成。可以使用任意整数值,但通常会使用 ftok 函数以便唯一标识。

size 参数:
共享内存的大小,一般设置为4k的整数倍,因为操作系统在分配空间时是以4k对齐的。例如,4096表示4KB的共享内存。

shmflg 参数:
由九个权限标志构成,表示创建共享内存的方式。
IPC_CREAT:如果不存在,则创建;如果存在,则返回旧的共享内存标识符。
IPC_EXCL:与 IPC_CREAT 一同使用,表示如果存在则出错返回,即创建一个全新的共享内存。
权限位:用于设置创建的共享内存的权限,通常以八进制表示,例如,0666表示读写权限。

返回值:
成功时返回共享内存标识符(shmid),失败时返回 -1。

例如:

int shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666);

4.2 ftok 函数 - 获取 key 值

#include 
#include 
key_t ftok(const char *pathname, int proj_id);

pathname 参数:
文件路径名,通常使用 ftok 来生成 key。可以使用当前工作目录的路径名,如通过 getcwd 函数获取。

proj_id 参数:
项目ID,可以是任意整数值,用于进一步标识 key。

返回值:
成功时返回生成的 key,失败时返回 -1。

4.3 shmat 函数 - 连接共享内存到进程地址空间

#include 
#include 
void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid 参数:
由 shmget 返回的共享内存标识符。

shmaddr 参数:
指定连接的地址,通常为 nullptr,表示由系统自动选择一个地址。

shmflg 参数:
用于设置对共享内存的读写权限,通常为0表示读写权限。

返回值:
成功时返回连接的共享内存地址,失败时返回 (void *)-1。

4.4 shmdt 函数 - 断开连接共享内存

#include 
#include 
int shmdt(const void *shmaddr);

shmaddr 参数:
shmat 返回的指针,代表要断开连接的共享内存。

返回值:
成功时返回 0,失败时返回 -1。

4.5 shmctl 函数 - 控制共享内存

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

shmid 参数:
shmget 返回的共享内存标识符。

cmd 参数:
控制命令,有三个主要取值:
IPC_STAT:获取共享内存的状态信息。
IPC_SET:设置共享内存的状态信息。
IPC_RMID:删除共享内存。

buf 参数:
指向一个保存着共享内存的模式状态和访问权限的数据结构 struct shmid_ds,用于传递和获取共享内存的信息。通常设置为 nullptr。

返回值:
成功时返回 0,失败时返回 -1。

5. 共享内存的代码实现

Linux详解共享内存_第2张图片

关系:

processa.cpp 中创建并写入共享内存,然后删除共享内存。
processb.cpp 中获取共享内存,等待5秒后开始循环读取共享内存并输出。两者通过共享内存进行简单的进程间通信。

查看系统中当前存在的共享内存:

ipcs -m

这个命令会列出系统中当前存在的所有共享内存段的信息,包括内存段的ID(shmid)、大小、创建者、附加的进程数等。

删除系统中的某个共享内存:

ipcrm -m [shmid]

这个命令用于删除指定ID(shmid)的共享内存段。请确保在执行此命令之前,没有任何进程附加到该共享内存段,否则删除操作可能会失败。

你可能感兴趣的:(linux,服务器,c语言)