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

如何用C语言fork()创建多进程读写共享数组实现任务分摊

C语言多进程共享内存处理大数组方案

针对你提出的多进程处理大数组、避免内存重复占用的需求,核心解决方案是使用共享内存机制,让父子进程直接访问同一块物理内存,无需fork时复制整个地址空间。下面提供两种实用实现方式:


1. 匿名内存映射(mmap)

这种方式简洁高效,专为父子进程共享内存设计,无需额外的内存标识符管理。

实现思路

  • 用mmap创建匿名共享内存块,同时存储原N×M数组和结果数组
  • 父进程填充原数组的随机整数
  • 拆分N行给K个子进程,每个子进程独立统计分配到的行的奇数数量,写入结果数组对应位置
  • 父进程等待所有子进程完成后,读取结果

代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <time.h>

int main() {
    int N = 100;  // 行数(可按需调整)
    int M = 1000; // 每行元素数(可按需调整)
    int K = 4;    // 进程数(可按需调整)

    // 计算总内存:原数组(N*M个int) + 结果数组(N个int)
    size_t total_size = (N * M + N) * sizeof(int);
    // 创建匿名共享内存,父子进程共享同一块物理内存
    void *shared_mem = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (shared_mem == MAP_FAILED) {
        perror("mmap failed");
        exit(EXIT_FAILURE);
    }

    // 映射原数组和结果数组的指针
    int (*arr)[M] = (int (*)[M])shared_mem;
    int *result = (int *)((char *)shared_mem + N * M * sizeof(int));

    // 父进程填充随机整数
    srand(time(NULL));
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            arr[i][j] = rand() % 1000;
        }
    }

    // 创建K个子进程
    for (int i = 0; i < K; i++) {
        pid_t pid = fork();
        if (pid == -1) {
            perror("fork failed");
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            // 子进程分配行范围:最后一个进程处理剩余行
            int start = i * (N / K);
            int end = (i == K-1) ? N : (i+1)*(N/K);

            // 统计每行奇数数量
            for (int row = start; row < end; row++) {
                int count = 0;
                for (int col = 0; col < M; col++) {
                    if (arr[row][col] % 2 != 0) count++;
                }
                result[row] = count;
            }

            // 子进程完成任务后退出,自动释放内存映射
            munmap(shared_mem, total_size);
            exit(EXIT_SUCCESS);
        }
    }

    // 父进程等待所有子进程结束
    for (int i = 0; i < K; i++) {
        wait(NULL);
    }

    // 验证结果(可选)
    printf("前5行的奇数数量:\n");
    for (int i = 0; i < 5; i++) {
        printf("行%d:%d\n", i, result[i]);
    }

    // 释放共享内存
    munmap(shared_mem, total_size);
    return 0;
}

2. System V共享内存(shmget/shmat)

这种方式更灵活,支持非父子进程间的内存共享,适合复杂场景。

实现思路

  • 用shmget创建共享内存段,获取唯一标识符
  • 用shmat将内存段映射到进程地址空间
  • 后续逻辑与匿名映射一致,完成后需手动删除共享内存

代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <time.h>

int main() {
    int N = 100;
    int M = 1000;
    int K = 4;

    size_t total_size = (N * M + N) * sizeof(int);
    // 创建私有共享内存段,仅父子进程可用
    int shmid = shmget(IPC_PRIVATE, total_size, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget failed");
        exit(EXIT_FAILURE);
    }

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

    int (*arr)[M] = (int (*)[M])shared_mem;
    int *result = (int *)((char *)shared_mem + N * M * sizeof(int));

    // 填充随机整数
    srand(time(NULL));
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            arr[i][j] = rand() % 1000;
        }
    }

    // 创建子进程处理任务
    for (int i = 0; i < K; i++) {
        pid_t pid = fork();
        if (pid == -1) {
            perror("fork failed");
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            int start = i * (N / K);
            int end = (i == K-1) ? N : (i+1)*(N/K);

            for (int row = start; row < end; row++) {
                int count = 0;
                for (int col = 0; col < M; col++) {
                    if (arr[row][col] % 2 != 0) count++;
                }
                result[row] = count;
            }

            // 子进程解除内存映射
            shmdt(shared_mem);
            exit(EXIT_SUCCESS);
        }
    }

    // 等待子进程完成
    for (int i = 0; i < K; i++) {
        wait(NULL);
    }

    // 验证结果
    printf("前5行的奇数数量:\n");
    for (int i = 0; i < 5; i++) {
        printf("行%d:%d\n", i, result[i]);
    }

    // 父进程解除映射并删除共享内存
    shmdt(shared_mem);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

关键说明

  • 无需同步:你的场景中每个子进程处理独立的行,不会出现内存竞争,因此不需要信号量或互斥锁
  • 编译方式:直接用gcc编译即可,无需额外链接库:gcc -o shared_demo shared_demo.c
  • 内存回收:匿名mmap会在所有进程退出后自动回收;System V共享内存需手动调用shmctl删除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:35:09