📜  通过共享内存进行IPC(1)

📅  最后修改于: 2023-12-03 15:12:23.615000             🧑  作者: Mango

通过共享内存进行IPC

IPC(Inter-Process Communication)是进程间通信的缩写,是指不同进程之间进行数据交换的操作。在操作系统的发展历程中,进程间通信已经成为了一个重要的课题。共享内存是一种常见的IPC机制,它可以使得多个进程之间能够直接读写同一块物理内存区域。本文将介绍如何通过共享内存进行IPC。

什么是共享内存

共享内存是指两个或多个进程共享同一块物理内存区域的机制。通常情况下,这块物理内存区域可以由一个进程创建并初始化,然后其他进程可以连接到它并读写该区域。共享内存机制可以大大提高进程间通信的效率,因为它避免了数据拷贝的开销。

共享内存的使用方法

在Linux系统中,共享内存的使用方法包括以下步骤:

  1. 创建共享内存区域:使用shmget()系统调用创建共享内存区域。该系统调用接收三个参数:键值(key)、内存区域大小和标识。其中,键值是一个可以唯一标识该共享内存的整数值,可以使用ftok()函数将一个已知的文件路径和一个字符值(随意)转换成一个长整数值作为该共享内存的键值。内存区域大小指定了要创建的共享内存的大小,单位为字节。标识可以指定一些标志位,例如设置共享内存为只读或者读写模式。

  2. 将共享内存映射到进程地址空间:使用shmat()系统调用将创建的共享内存片段(Memory Segment)映射到当前进程的地址空间。映射之后,进程就可以使用指针来访问该共享内存区域中的数据了。

  3. 操作共享内存:完成对共享内存区域的读写操作。此时可以使用指针操作共享内存,就像操作普通的内存一样。

  4. 解除共享内存的映射:使用shmdt()系统调用将共享内存片段与当前进程的地址空间分离。

  5. 删除共享内存:使用shmctl()系统调用将共享内存片段从系统中删除。

共享内存示例代码

下面是一个使用共享内存进行IPC的示例代码,在该代码中,一个进程先创建一个共享内存片段,然后在该片段中写入一些数据。接着另外一个进程连接到该共享内存片段,并从该片段中读取数据。

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

#define SHM_SIZE 1024  // 共享内存的大小

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

  // 创建共享内存
  shmid = shmget(ftok(".", 'a'), SHM_SIZE, IPC_CREAT | 0644);
  if (shmid < 0) {
    perror("shmget");
    exit(EXIT_FAILURE);
  }

  // 映射共享内存到当前进程地址空间
  shm_ptr = shmat(shmid, NULL, 0);
  if (shm_ptr == (char*)-1) {
    perror("shmat");
    exit(EXIT_FAILURE);
  }

  // 在共享内存中写入一些数据
  strncpy(shm_ptr, "Hello, world!", SHM_SIZE);

  // 分离共享内存
  if (shmdt(shm_ptr) < 0) {
    perror("shmdt");
    exit(EXIT_FAILURE);
  }

  // 重新连接到共享内存
  shm_ptr = shmat(shmid, NULL, SHM_RDONLY);
  if (shm_ptr == (char*)-1) {
    perror("shmat2");
    exit(EXIT_FAILURE);
  }

  // 从共享内存中读取数据
  printf("Read from shared memory: %s\n", shm_ptr);

  // 分离共享内存
  if (shmdt(shm_ptr) < 0) {
    perror("shmdt2");
    exit(EXIT_FAILURE);
  }

  // 删除共享内存
  if (shmctl(shmid, IPC_RMID, NULL) < 0) {
    perror("shmctl");
    exit(EXIT_FAILURE);
  }

  return 0;
}

在该代码中,首先调用shmget()函数创建了一个共享内存片段,然后使用shmat()函数讲该片段映射到当前进程的地址空间。之后,在共享内存片段中写入了一些数据。然后,另外一个进程调用shmat()函数连接到该共享内存片段,并从该片段中读取数据。最后,调用shmctl()函数将该共享内存片段从系统中删除。