lavonXV 发表于 2024-5-26 13:14:43

System V 共享内存

本帖最后由 lavonXV 于 2024-5-26 13:16 编辑

共享内存是一种进程间通信(IPC)机制,允许多个进程共享一块内存区域,以实现数据的快速传递和共享。System V 共享内存是 UNIX 系统中一种经典的共享内存机制,具有广泛的应用。本文将详细介绍 System V 共享内存的概念、创建与使用方法,并提供示例代码以便更好地理解其实现和应用。


1. 概念与原理

共享内存是一种高效的进程间通信方式,允许多个进程直接访问同一块内存区域,避免了频繁的数据复制。System V 共享内存是基于 System V IPC(Inter-Process Communication)机制的一部分,通过系统调用进行操作。

1.1 关键概念

(1) 共享内存段:共享内存段是分配给多个进程共享的内存区域,每个共享内存段由一个唯一的标识符(shmid)进行标识。

(2) 键(key):键是用于创建或访问共享内存段的标识符,通过 `ftok` 函数生成。相同的键会得到相同的共享内存段标识符。

(3) 标志(flags):在创建共享内存段时,可以通过标志来设置权限和控制选项,如 `IPC_CREAT` 表示如果不存在则创建共享内存段。

2. 创建与使用

2.1 创建共享内存段

要创建一个共享内存段,需要使用 `shmget` 系统调用。


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


(1) `key`:共享内存段的键值,由 `ftok` 函数生成。
(2) `size`:共享内存段的大小(字节数)。
(3) `shmflg`:标志和权限,常用的标志包括 `IPC_CREAT` 和 `IPC_EXCL`。

示例代码:


key_t key = ftok("path/to/file", 'R');
int shmid = shmget(key, 1024, IPC_CREAT | 0666);
if (shmid == -1) {
    perror("shmget failed");
    exit(1);
}


2.2 附加和分离共享内存段

创建共享内存段后,进程需要将其附加到自身的地址空间,这可以通过 `shmat` 系统调用实现。完成操作后,可以通过 `shmdt` 系统调用将其分离。


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


示例代码:


void *shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1) {
    perror("shmat failed");
    exit(1);
}

// 使用共享内存...

if (shmdt(shared_memory) == -1) {
    perror("shmdt failed");
    exit(1);
}


2.3 控制共享内存段

使用 `shmctl` 系统调用可以对共享内存段进行控制,如删除共享内存段、获取状态信息等。


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


(1) `shmid`:共享内存段的标识符。
(2) `cmd`:控制命令,如 `IPC_RMID` 用于删除共享内存段。
(3) `buf`:存储状态信息的结构体指针。

示例代码:


if (shmctl(shmid, IPC_RMID, NULL) == -1) {
    perror("shmctl failed");
    exit(1);
}


3. 示例应用

以下是一个示例程序,展示了如何使用 System V 共享内存在两个进程之间进行通信。

3.1 创建和写入共享内存段

创建一个共享内存段并写入数据。


#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, IPC_CREAT | 0666);
    if (shmid == -1) {
      perror("shmget failed");
      exit(1);
    }

    char *str = (char *)shmat(shmid, NULL, 0);
    if (str == (char *)-1) {
      perror("shmat failed");
      exit(1);
    }

    strcpy(str, "Hello, Shared Memory!");
    printf("Data written to shared memory: %s\n", str);

    if (shmdt(str) == -1) {
      perror("shmdt failed");
      exit(1);
    }

    return 0;
}


3.2 读取共享内存段

在另一个进程中读取共享内存段中的数据。


#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);
    if (shmid == -1) {
      perror("shmget failed");
      exit(1);
    }

    char *str = (char *)shmat(shmid, NULL, 0);
    if (str == (char *)-1) {
      perror("shmat failed");
      exit(1);
    }

    printf("Data read from shared memory: %s\n", str);

    if (shmdt(str) == -1) {
      perror("shmdt failed");
      exit(1);
    }

    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
      perror("shmctl failed");
      exit(1);
    }

    return 0;
}


4. 总结

System V 共享内存是 UNIX 系统中一种高效的进程间通信机制,通过共享内存段,多个进程可以直接读写同一块内存区域。本文详细介绍了共享内存的概念、创建与使用方法,并提供了示例代码,帮助读者更好地理解和应用这一技术。希望这些内容能帮助您在实际项目中更高效地实现进程间通信。

页: [1]
查看完整版本: System V 共享内存