Linux Process Address Space
high address +---------------+
| |
| Stack | int local_b
| |
+---------------+
| | |
| v |
| |
| |
| ^ |
| | |
+---------------+
| |
| Heap | int * heap_c = malloc()
| |
+---------------+
| Data | int global_a
+---------------+
| Code |
low address +---------------+
上图是 Linux 的进程地址空间,从低位到高位地址分别为:
- Code Segment: 程序的代码,CPU 执行的指令部分,共享只读
- Data Segment: 可细分为初始化数据段和未初始化数据段,常用于存储全局变量等
- Stack: 函数以及自动变量(未加 static 的自动变量又称为局部变量)
- Heap: 动态分配内存,如 malloc() 分配的内存
更为详细的介绍请见 Anatomy of a Program in Memory。
Fork
Parent Process Child Process
high address +---------------+ +---------------+
| | | |
| Stack | | Stack |
| | | |
+---------------+ +---------------+
| | | | | |
| v | | v |
| | | |
| | | |
| ^ | | ^ |
| | | | | |
+---------------+ +---------------+
| | | |
| Heap | | Heap |
| | | |
+---------------+ +---------------+
| Data | | Data |
+---------------+----------+---------------+
| Code |
low address +------------------------------------------+
fork 是 linux 中最重要的系统调用之一,用于创建一个新进程,它完全的复制父进程地址空间的 data segment、 heap 和 stack,但是和父进程共享一个 code segment,因为 code segment 通常为只读,从逻辑的角度来看,子进程和父进程的内存地址空间互相独立,子进程修改自己的 data segment,heap 和 stack 并不影响父进程内存空间。每次调用 fork,返回两次结果,其中父进程的返回值为子进程的 pid,子进程的返回值为 0。
#include<stdio.h>