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

含信号量与可变长度数组的共享内存结构体定义及跨进程共享问询

Hey there! Let's work through how to create that shared memory struct for your producer-consumer setup. Your initial idea uses variable-length arrays (VLAs) in the struct, which won't work in standard C—structs can only have a single flexible array as their final member, which doesn't help here with three arrays. Here's a solid approach to make this work:

Step 1: Define the Struct with Shared Semaphores and Array Metadata

Instead of embedding VLAs directly, we'll use pointers in the struct to point to array data stored in the same shared memory block. We'll also include the array dimensions so all processes know how to index the data:

typedef double lr;

struct ShMem {
    sem_t prod;          // Producer semaphore
    sem_t cons;          // Consumer semaphore
    size_t nx;           // X dimension for your arrays
    size_t ny;           // Y dimension
    size_t nz;           // Z dimension
    lr *u_x;             // Pointer to u_x array
    lr *u_y;             // Pointer to u_y array
    lr *u_z;             // Pointer to u_z array
};

Step 2: Calculate Total Shared Memory Size

We need to allocate enough space to hold the struct plus all three arrays. Calculate the total size like this:

size_t nx = 400, ny = 400, nz = 400;

// Calculate element counts for each array
size_t u_x_count = (nx + 1) * (ny + 2) * (nz + 2);
size_t u_y_count = (nx + 2) * (ny + 1) * (nz + 2);
size_t u_z_count = (nx + 2) * (ny + 2) * (nz + 2);

// Total shared memory size = struct size + sum of all array sizes
size_t total_size = sizeof(struct ShMem) + 
                    (u_x_count + u_y_count + u_z_count) * sizeof(lr);

Step 3: Create and Map Shared Memory

Use POSIX shared memory functions (shm_open, mmap) to create and map the memory block. Then initialize the struct's pointers to point to the correct locations in the shared memory:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>

int main() {
    size_t nx = 400, ny = 400, nz = 400;
    size_t u_x_count = (nx + 1) * (ny + 2) * (nz + 2);
    size_t u_y_count = (nx + 2) * (ny + 1) * (nz + 2);
    size_t u_z_count = (nx + 2) * (ny + 2) * (nz + 2);
    size_t total_size = sizeof(struct ShMem) + 
                        (u_x_count + u_y_count + u_z_count) * sizeof(lr);

    // Create shared memory object
    int shm_fd = shm_open("/my_prod_cons_shmem", O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("Failed to create shared memory");
        exit(EXIT_FAILURE);
    }

    // Resize shared memory to our calculated total size
    if (ftruncate(shm_fd, total_size) == -1) {
        perror("Failed to resize shared memory");
        close(shm_fd);
        exit(EXIT_FAILURE);
    }

    // Map shared memory to process address space
    struct ShMem *shmem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shmem == MAP_FAILED) {
        perror("Failed to map shared memory");
        close(shm_fd);
        exit(EXIT_FAILURE);
    }

    // Initialize semaphores for inter-process sharing (second arg = 1)
    if (sem_init(&shmem->prod, 1, 0) == -1) { // Start with 0: consumer waits for producer
        perror("Failed to initialize prod semaphore");
        munmap(shmem, total_size);
        close(shm_fd);
        exit(EXIT_FAILURE);
    }
    if (sem_init(&shmem->cons, 1, 1) == -1) { // Start with 1: producer can write first
        perror("Failed to initialize cons semaphore");
        sem_destroy(&shmem->prod);
        munmap(shmem, total_size);
        close(shm_fd);
        exit(EXIT_FAILURE);
    }

    // Set dimension values in the struct
    shmem->nx = nx;
    shmem->ny = ny;
    shmem->nz = nz;

    // Calculate pointer positions (arrays start right after the struct)
    lr *data_start = (lr*)((char*)shmem + sizeof(struct ShMem));
    shmem->u_x = data_start;
    shmem->u_y = data_start + u_x_count;
    shmem->u_z = shmem->u_y + u_y_count;

Step 4: Access the Arrays Easily

Since the pointers are one-dimensional, use a macro to simplify 3D array-style access:

#define U_X(shm, i, j, k) (shm->u_x[(i)*((shm->ny)+2)*((shm->nz)+2) + (j)*((shm->nz)+2) + (k)])
#define U_Y(shm, i, j, k) (shm->u_y[(i)*((shm->ny)+1)*((shm->nz)+2) + (j)*((shm->nz)+2) + (k)])
#define U_Z(shm, i, j, k) (shm->u_z[(i)*((shm->ny)+2)*((shm->nz)+2) + (j)*((shm->nz)+2) + (k)])

// Example usage:
U_X(shmem, 0, 0, 0) = 1.0;
printf("u_x[0][0][0] = %lf\n", U_X(shmem, 0, 0, 0));

Step 5: Cleanup Resources

When all processes are done, clean up the shared memory and semaphores:

// Cleanup (run this in the last process to exit)
    sem_destroy(&shmem->prod);
    sem_destroy(&shmem->cons);
    munmap(shmem, total_size);
    close(shm_fd);
    shm_unlink("/my_prod_cons_shmem");

    return 0;
}

Key Notes

  • Semaphore Initialization: The second argument to sem_init must be 1 to make the semaphore shared between processes.
  • Shared Memory Name: All processes must use the same name (e.g., /my_prod_cons_shmem) to access the same shared memory block.
  • Dimension Consistency: Ensure all producer/consumer processes use the same nx, ny, nz values—mismatched dimensions will cause memory access errors.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:07:33