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

子进程调用exec()后,父子进程如何共享内存?能否使用mmap?

Great question—this is a common pitfall when working with fork() and exec() together. Let's break down why your original mmap shared memory stops working, and how to fix it (including using mmap correctly!).

Why the original mmap shared memory fails after exec()

When a child process calls exec(), it completely replaces its entire user-space address space: the code, data, heap, and stack are all swapped out for the new program's contents. Any existing memory mappings (including your original mmap shared region) are discarded in this process—so the exec'd program has no way to access the old shared memory.

Can we still use mmap to share memory? Yes—here's how

You absolutely can use mmap for shared memory across exec(), but you need to adjust your approach to account for the address space replacement. The key idea is to create a shared memory source that the exec'd program can explicitly re-map after it starts up. Here are two reliable methods:

1. Use a file-backed mmap (with a persistent file or POSIX shared memory object)

Instead of using anonymous mmap (MAP_ANONYMOUS), create a shared memory region backed by a file (or a POSIX shared memory object, which acts like a file but lives in /dev/shm for faster access). Then:

  • The parent process creates and maps this file/shared object first.
  • When forking the child, pass the file descriptor or the path to the shared object to the exec'd program (via command-line arguments, inherited file descriptors, or environment variables).
  • The exec'd program then opens the file/shared object and calls mmap() on it to connect to the same shared memory region as the parent.

Example code snippets:

Parent process:

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

int main() {
    // Create a POSIX shared memory object
    int shm_fd = shm_open("/my_shared_region", O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open failed");
        return 1;
    }

    // Set the size of the shared region
    if (ftruncate(shm_fd, 4096) == -1) {
        perror("ftruncate failed");
        close(shm_fd);
        shm_unlink("/my_shared_region");
        return 1;
    }

    // Map the shared region into parent's address space
    void *shared_ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shared_ptr == MAP_FAILED) {
        perror("mmap failed");
        close(shm_fd);
        shm_unlink("/my_shared_region");
        return 1;
    }

    // Write initial data to shared memory
    sprintf(shared_ptr, "Hello from parent!");

    // Fork child process
    pid_t pid = fork();
    if (pid == 0) {
        // Pass the shared memory file descriptor to the exec'd program as an argument
        char fd_str[10];
        snprintf(fd_str, sizeof(fd_str), "%d", shm_fd);
        execl("./exec_child", "./exec_child", fd_str, NULL);
        
        // If execl returns, it failed
        perror("execl failed");
        return 1;
    } else if (pid > 0) {
        // Wait for child to finish
        wait(NULL);
        // Read the updated data from shared memory
        printf("Parent received: %s\n", (char*)shared_ptr);

        // Cleanup
        munmap(shared_ptr, 4096);
        close(shm_fd);
        shm_unlink("/my_shared_region");
    } else {
        perror("fork failed");
        close(shm_fd);
        shm_unlink("/my_shared_region");
        return 1;
    }

    return 0;
}

Exec'd child program (exec_child.c):

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

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <shared_memory_fd>\n", argv[0]);
        return 1;
    }

    // Convert the passed file descriptor string to an int
    int shm_fd = atoi(argv[1]);

    // Map the shared region into this process's address space
    void *shared_ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shared_ptr == MAP_FAILED) {
        perror("mmap failed");
        close(shm_fd);
        return 1;
    }

    // Read and modify the shared data
    printf("Exec'd child received: %s\n", (char*)shared_ptr);
    sprintf(shared_ptr, "Hello from exec'd child!");

    // Cleanup
    munmap(shared_ptr, 4096);
    close(shm_fd);

    return 0;
}

2. Inherit file descriptors across exec()

By default, file descriptors that are not marked as FD_CLOEXEC are inherited by the exec'd program. So instead of passing the FD as a command-line argument, you can just ensure the shared memory file descriptor isn't closed on exec (which is the default behavior unless you set FD_CLOEXEC with fcntl()). The exec'd program can then use that FD directly to mmap the shared region.

Alternative approaches

If you don't want to use mmap directly, you can also use System V shared memory (shmget(), shmat()), but this is an older API with more cumbersome setup. POSIX shared memory + mmap is generally preferred for its simplicity and compatibility with modern systems.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:48:40