我有一个带有父进程和子进程的程序.在fork()之前,父进程调用malloc()并用一些数据填充array.在fork()之后,子元素需要这些数据.我知道我可以使用管道,但以下代码似乎有效:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main( int argc, char *argv[] ) {
    char *array;
    array = malloc( 20 );
    strcpy( array, "Hello" );
    switch( fork() ) {
    case 0:
        printf( "Child array: %s\n", array );
        strcpy( array, "Goodbye" );
        printf( "Child array: %s\n", array );
        free( array );
        break;
    case -1:
        printf( "Error with fork()\n" );
        break;
    default:
        printf( "Parent array: %s\n", array );
        sleep(1);
        printf( "Parent array: %s\n", array );
        free( array );
    }
    return 0;
}

输出为:

Parent array: Hello
Child array: Hello
Child array: Goodbye
Parent array: Hello

我知道在堆栈上分配的数据在子级中是可用的,但在堆上分配的数据似乎也对子级可用.同样,子级不能修改堆栈上父级的数据,子级不能修改堆上父级的数据.因此,我假设子级同时获得堆栈和堆数据的副本.

Linux中总是这样吗?如果是,支持这一点的文档在哪里?我查看了fork()手册页,但没有特别提到堆上的动态分配内存.

推荐答案

为进程分配的每个页面(无论是包含堆栈的虚拟内存页面还是堆)都会被复制,以便Forking 的进程能够访问它.

实际上,它不是从一开始就被复制的,它被设置为写时复制,这意味着一旦一个进程(父进程或子进程)试图修改一个页面,它就会被复制,这样它们就不会互相伤害,并且仍然可以访问来自fork()点的所有数据.

例如,代码页(实际可执行文件映射到内存中的代码页)通常是只读的,因此在所有Forking 进程中重用——它们不会被再次复制,因为没有人在那里写,只需要读,因此永远不需要写时复制.

更多信息请参见herehere.

Linux相关问答推荐

Linux打开/dev/tran/n是否与复制相同?

无法在Raspberry PI 3 Model B上分配256TB的虚拟内存

在同一目录中未检测到G++预编译头

在linux中,我想将昨天的文件与今天的文件进行比较,仅将今天的更改作为输出,忽略一些字段

CMake:处理静态库和共享库的正确方法

我有 ext2 格式的文件系统图像.我喜欢在终端中读取 Linux 特别是 Ubuntu 中的所有文件系统 struct 数据.有没有工具>

PHP factor 30 从 Linux 到 Windows 的性能差异

在 Linux 下将 TCP 流量重定向到 UNIX 域套接字

判断条件是否为假

从 Linux shell 将多个文件从一个目录复制到另一个目录

如何在 Linux 中创建高分辨率计时器来测量程序性能?

如何在没有空格的情况下打印 awk?

try 使用 sudo 将文件附加到根拥有的文件时权限被拒绝

如何在shell的递归目录中列出特定类型的文件?

比较文件的日期 bash

在 Linux / Mono 上运行 ServiceStack 的最佳方式是什么?

UNIX `time` 命令对于基准测试是否足够准确?

Bash:如何标记字符串变量?

如何使用mv命令移动特定目录中的文件除外?

如何限制我网站的 API 用户?