You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于头文件的共享内存实现报错:结构体定义与跨进程访问问题

解决共享内存定义与跨进程访问问题

你的核心问题出在头文件中错误使用#define定义枚举和结构体类型,再加上服务端代码里对共享内存指针的错误引用,导致编译器无法识别ShmData相关定义。下面一步步帮你修复这些问题,确保共享内存能正确包含指定字段并支持跨进程访问。

一、修复shm.h的类型定义错误

你用#define来定义枚举和结构体是完全错误的——#define只是预处理宏替换,不是C语言定义自定义类型的方式。正确做法是用typedef来定义类型:

#ifndef SHM_H
#define SHM_H

// 定义枚举类型StatusEnus
typedef enum {
    INVALID,
    VALID,
    CONSUMED
} StatusEnus;

// 定义共享内存数据结构体
typedef struct {
    StatusEnus status;
    int data;
} ShmData;

// 用结构体实际大小定义共享内存尺寸,避免硬编码出错
#define SIZE sizeof(ShmData)

#endif

为什么原来的写法错了?

  • #define enum StatusEnus{...} StatusEnus 会被预处理成完全不符合C语法的代码,编译器根本无法识别这个枚举类型。
  • 同理,#define struct ShmData{...} ShmData; 也是错误的,typedef才是C语言定义自定义类型的标准方式。
  • 用sizeof(ShmData)代替硬编码的8,能保证大小和结构体实际内存布局一致,避免因平台或编译器差异导致的大小不匹配。

二、修复服务端代码的核心错误

你的服务端代码存在指针引用错误、mmap参数错误、错误处理缺失等问题。以下是修复后的完整代码,关键修复点我会在代码后标注:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "shm.h"

int main(int argc, char* argv[]) {
    int retVal = 0;
    ShmData* shared_data = NULL; // 定义指向共享内存的结构体指针
    int shm_fd = -1;

    // 修复参数检查:给出正确的用法提示
    if(argc != 2){
        fprintf(stderr, "Usage: %s <integer_data>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // 打开共享内存对象,添加错误信息打印(POSIX规范建议名称以/开头)
    shm_fd = shm_open("/sharedMem", O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open failed");
        return EXIT_FAILURE;
    }

    // 设置共享内存大小为结构体实际大小
    if (ftruncate(shm_fd, SIZE) == -1) {
        perror("ftruncate failed");
        close(shm_fd);
        shm_unlink("/sharedMem");
        return EXIT_FAILURE;
    }

    // 修复mmap参数:PROT_READ | PROT_WRITE(原来重复写了PROT_WRITE),并转换为ShmData*类型
    shared_data = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shared_data == MAP_FAILED) {
        perror("mmap failed");
        close(shm_fd);
        shm_unlink("/sharedMem");
        return EXIT_FAILURE;
    }

    // 修复指针引用:用shared_data->而不是ShmData->(ShmData是类型名,不是实例指针)
    shared_data->status = INVALID;
    shared_data->data = atoi(argv[1]);
    shared_data->status = VALID;

    printf("[Server]: Server data Valid... waiting for client\n");

    // 循环等待客户端标记为CONSUMED
    while(shared_data->status != CONSUMED) {
        sleep(1);
    }

    printf("[Server]: Server Data consumed!\n");

    // 按顺序清理资源:先解除内存映射,再关闭文件描述符,最后删除共享内存对象
    if (munmap(shared_data, SIZE) == -1) {
        perror("munmap failed");
        retVal = EXIT_FAILURE;
    }
    close(shm_fd);
    if (shm_unlink("/sharedMem") == -1) {
        perror("shm_unlink failed");
        retVal = EXIT_FAILURE;
    }

    printf("[Server]: Server exiting...\n");
    return retVal;
}

关键修复点说明:

  1. 共享内存指针的正确使用:
    • 定义ShmData* shared_data来接收mmap返回的地址,不能直接用ShmData->(ShmData是类型名,不是指针变量)。
  2. mmap参数修正:
    • 原来的PROT_WRITE | PROT_WRITE是冗余错误,应该是PROT_READ | PROT_WRITE,保证进程能读写共享内存。
    • 检查mmap返回值是否为MAP_FAILED(而非NULL),这是POSIX规范的错误返回值。
  3. 错误处理完善:
    • 每个系统调用(shm_open、ftruncate、mmap等)都添加了错误检查和资源清理逻辑,避免资源泄漏。
  4. 共享内存路径规范:
    • shm_open的名称建议以/开头(POSIX标准要求),确保跨进程能正确识别同一个共享内存对象。
  5. 资源清理顺序:
    • 必须先munmap解除内存映射,再close文件描述符,最后shm_unlink删除共享内存对象。

三、跨进程访问的注意事项

  1. 客户端代码要包含相同的shm.h:客户端必须使用完全一致的结构体和枚举定义,才能正确解析共享内存中的数据。
  2. 同步机制:如果多个进程同时读写共享内存,建议使用信号量(sem_open等API)做同步,避免竞态条件。
  3. 权限设置:shm_open的0666权限要确保客户端进程有足够的权限访问共享内存对象。

内容的提问来源于stack exchange,提问作者Danny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:27:00