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

Unix下利用fork()与共享内存实现结构体数组跨进程访问的技术咨询

Fixing Your Shared Memory + fork() Implementation for strProcess Arrays

Hey there! Let's break down the issues in your current code and walk through the correct implementation steps to get your 10-element strProcess array into shared memory for client access.

First: Fix Critical Syntax Errors

Your code has a few syntax issues that will prevent it from compiling at all:

  • Function definitions inside main(): C doesn't allow defining functions inside another function. Move finval, frand, and fsortasc outside of main() entirely.
  • Broken shmat usage: Your code has invalid pointer assignment and error checking for shared memory attachment. Replace those lines with:
    struct strProcess *shm_array = (struct strProcess *)shmat(nShmid, NULL, 0);
    if (shm_array == (void *)-1) {
        perror("shmat");
        exit(1);
    }
    
  • Wrong shared memory size: sizeof(pArray) * 10 doubles the required size (since pArray is already a 10-element array). Use sizeof(struct strProcess) * 10 or just sizeof(pArray) to get the correct size for 10 strProcess structs.
  • Uninitialized random seed: rand() will generate the same sequence every time unless you initialize it with srand(time(NULL)); at the start of main().

Next: Fix Logical Flaws

These issues will cause unexpected behavior even if the code compiles:

  • Child processes don't exit: After writing to shared memory, child processes will continue executing the rest of main() (like sorting and file writes). Add exit(0); at the end of the child process block to prevent this.
  • Confusing stack array with shared memory: You're writing to shared memory in child processes but sorting the stack-based pArray (which isn't connected to shared memory). Sort the shared memory pointer (shm_array) instead.
  • Log file race conditions: Multiple child processes writing to logfile.txt at the same time can garble output. Either let the parent process handle all logging, or add a file lock (simpler to stick with parent-side logging).

Key Implementation Principles for Shared Memory + fork()

Let's cover the core concepts to make this work reliably:

  1. Shared Memory Lifecycle:
    • Use shmget() to create a segment with a unique key (use ftok() instead of a hardcoded key if you want better reliability across systems).
    • shmat() attaches the segment to your process's address space; all child processes from fork() inherit this attachment, so they can directly access the shared memory.
    • Don't forget to clean up: use shmdt() to detach when done, and shmctl(nShmid, IPC_RMID, NULL) to delete the segment (skip deletion if your client still needs access).
  2. Synchronization:
    If multiple processes (parent + children, or client + your server) are reading/writing shared memory, use semaphores (via semget()/semop()) to lock access and avoid data corruption. For your current setup, waiting for all children to exit before sorting (using wait()) avoids most races.
  3. Client Access:
    For a client to read the shared memory, it just needs to:
    • Use the same key to call shmget()
    • Attach with shmat() to get the strProcess pointer
    • Read/write the array, then detach with shmdt()

Corrected Full Code

Here's the fixed version of your code with all the above changes applied:

// Compiler Directives
// Standard Library Inclusions
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>

//Other Inclusions
struct strProcess {
    int nPriority;
    int nPid;
};

// Function Prototypes
int frand(int nInput);
int finval(int nInput);
void fsortasc(struct strProcess pArray[], int nInput);

// Function Definitions
int finval(int nInput) {
    while(nInput <= 0 || nInput > 10) {
        printf("please enter a number between 1 and 10 \n");
        scanf("%d", &nInput);
    }
    return nInput;
}

int frand(int nInput) {
    int nRand;
    nRand = (rand() % nInput) + 1;
    return nRand;
}

void fsortasc(struct strProcess pArray[], int nInput) {
    struct strProcess temp;
    int i, j;
    for (i = 0; i < nInput - 1; i++) {
        for (j = 0; j < (nInput - 1 - i); j++) {
            if (pArray[j].nPriority > pArray[j + 1].nPriority) {
                temp = pArray[j];
                pArray[j] = pArray[j + 1];
                pArray[j + 1] = temp;
            }
        }
    }
}

// Main
int main(void) {
    // Variable Declarations
    int nShmid, i, nInput;
    key_t nKey = 5678;
    pid_t pid;
    struct strProcess *shm_array;
    const int MAX_PROCESSES = 10;

    // Initialize random seed for unique priorities
    srand(time(NULL));

    // Open log file
    FILE *f = fopen("logfile.txt", "w");
    if (f == NULL) {
        printf("Error opening file!\n");
        exit(1);
    }

    // Get valid process count input
    printf("please enter the amount of processes to create for this cycle between 1 and 10 \n");
    scanf("%d", &nInput);
    if (nInput <= 0 || nInput > 10) {
        nInput = finval(nInput);
    }
    printf("Creating %d processes\n", nInput);
    fprintf(f, "Creating %d processes\n", nInput);

    // Calculate shared memory size for 10 strProcess structures
    int nSize = sizeof(struct strProcess) * MAX_PROCESSES;

    // Create shared memory segment (read/write for all users)
    if ((nShmid = shmget(nKey, nSize, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        fclose(f);
        exit(1);
    }
    printf("Shared memory segment created (ID: %d)\n", nShmid);
    fprintf(f, "Shared memory segment created (ID: %d)\n", nShmid);

    // Attach shared memory to current process address space
    shm_array = (struct strProcess *)shmat(nShmid, NULL, 0);
    if (shm_array == (void *)-1) {
        perror("shmat");
        shmctl(nShmid, IPC_RMID, NULL); // Clean up segment on error
        fclose(f);
        exit(1);
    }
    printf("Shared memory segment attached\n");
    fprintf(f, "Shared memory segment attached\n");

    // Fork child processes to populate shared memory
    for (i = 0; i < nInput; i++) {
        if ((pid = fork()) < 0) {
            perror("fork");
            // Clean up resources on fork failure
            shmdt(shm_array);
            shmctl(nShmid, IPC_RMID, NULL);
            fclose(f);
            exit(1);
        }
        if (pid == 0) { // Child process logic
            shm_array[i].nPid = getpid();
            int nRpriority = frand(nInput);
            shm_array[i].nPriority = nRpriority;
            printf("Print job created with Pid %d and priority number %d\n", getpid(), nRpriority);
            exit(0); // Exit child to avoid executing parent code
        }
    }

    // Wait for all child processes to finish writing to shared memory
    for (i = 0; i < nInput; i++) {
        wait(NULL);
    }

    // Sort the shared memory array by priority (ascending order)
    fsortasc(shm_array, nInput);
    printf("\nSorted processes by priority:\n");
    fprintf(f, "\nSorted processes by priority:\n");
    for (i = 0; i < nInput; i++) {
        printf("Pid: %d, Priority: %d\n", shm_array[i].nPid, shm_array[i].nPriority);
        fprintf(f, "Pid: %d, Priority: %d\n", shm_array[i].nPid, shm_array[i].nPriority);
    }

    fprintf(f, "%d processes have been created and sorted\n", nInput);

    // Detach shared memory from current process
    shmdt(shm_array);
    // Uncomment the line below to delete the segment immediately (skip if client needs access)
    // shmctl(nShmid, IPC_RMID, NULL);

    fclose(f);
    return 0;
}

Quick Notes for Client Access

To let a client read the shared memory:

  1. Use the same key_t nKey = 5678;
  2. Call shmget(nKey, sizeof(struct strProcess)*10, 0666) to get the segment ID
  3. Attach with struct strProcess *client_shm = (struct strProcess *)shmat(shmid, NULL, 0);
  4. Access client_shm[i] to read each strProcess entry
  5. Detach with shmdt(client_shm); when done

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:13:54