一、共享的内容

  1. 文件描述符与文件状态
    子进程会继承父进程已打开的文件描述符表,包括文件偏移量、打开模式(如读写权限)和文件状态标志(如O_APPEND)。例如,若父进程打开了一个文件并写入数据,子进程可通过相同的文件描述符继续操作,且两者的写入位置(偏移量)会相互影响。
    示例场景:父进程向文件写入“Parent”,子进程写入“Child”,最终文件内容会按操作顺序合并(如“ParentChild”或“ChildParent”),具体取决于调度顺序。

  2. 信号处理设置
    子进程继承父进程的信号处理函数(如SIG_IGN或自定义处理程序)和信号屏蔽集(sigprocmask的设置)。

  3. 用户身份与环境变量
    子进程继承父进程的用户ID、组ID、环境变量、当前工作目录等身份信息。

  4. 写时复制(Copy-On-Write)的内存初始状态
    在未发生写入操作前,父子进程的代码段(.text)、数据段(.data.bss)、堆、栈等内存区域共享同一物理内存页。一旦某一方尝试修改数据,则会触发写时复制,生成独立的副本。

  5. 文件锁
    通过fcntlflock设置的文件锁会被子进程继承,父子进程对同一文件的锁定操作会相互影响。


二、不共享的内容

  1. 进程独立属性
    子进程拥有独立的进程ID(PID)、父进程ID(PPID)、运行时间统计、未决信号队列等。

  2. 多线程环境中的线程资源
    若父进程包含多个线程,子进程仅复制执行fork()的线程,其他线程不会被继承。

  3. 独立的内存修改
    通过写时复制机制,父子进程对内存的修改会各自独立。例如,全局变量初始值相同,但修改后互不影响。

  4. 独立的文件描述符关闭操作
    子进程关闭某个文件描述符不会影响父进程的同名描述符,反之亦然。


三、关键机制:写时复制(COW)

内核通过写时复制技术优化性能:
原理fork()后,父子进程的页表项指向相同的物理内存页,并将这些页标记为只读。当某一进程尝试写入时,触发页错误,内核复制该页并修改权限为可写。
优点:避免不必要的内存复制,提高资源利用率。


四、应用注意事项

  1. 文件操作同步:父子进程对同一文件描述符的并发写入需通过锁(如flock())或原子操作避免竞争。
  2. 内存共享限制:若需主动共享内存,需使用mmap()或共享内存API(如shmget())。
  3. 僵尸进程处理:父进程需通过wait()回收子进程资源,或注册SIGCHLD信号处理函数。