Linux里fork出子进程的时候,哪些内容是共享的?
Contents
一、共享的内容
文件描述符与文件状态
子进程会继承父进程已打开的文件描述符表,包括文件偏移量、打开模式(如读写权限)和文件状态标志(如O_APPEND
)。例如,若父进程打开了一个文件并写入数据,子进程可通过相同的文件描述符继续操作,且两者的写入位置(偏移量)会相互影响。
• 示例场景:父进程向文件写入“Parent”,子进程写入“Child”,最终文件内容会按操作顺序合并(如“ParentChild”或“ChildParent”),具体取决于调度顺序。信号处理设置
子进程继承父进程的信号处理函数(如SIG_IGN
或自定义处理程序)和信号屏蔽集(sigprocmask
的设置)。用户身份与环境变量
子进程继承父进程的用户ID、组ID、环境变量、当前工作目录等身份信息。写时复制(Copy-On-Write)的内存初始状态
在未发生写入操作前,父子进程的代码段(.text
)、数据段(.data
、.bss
)、堆、栈等内存区域共享同一物理内存页。一旦某一方尝试修改数据,则会触发写时复制,生成独立的副本。文件锁
通过fcntl
或flock
设置的文件锁会被子进程继承,父子进程对同一文件的锁定操作会相互影响。
二、不共享的内容
进程独立属性
子进程拥有独立的进程ID(PID)、父进程ID(PPID)、运行时间统计、未决信号队列等。多线程环境中的线程资源
若父进程包含多个线程,子进程仅复制执行fork()
的线程,其他线程不会被继承。独立的内存修改
通过写时复制机制,父子进程对内存的修改会各自独立。例如,全局变量初始值相同,但修改后互不影响。独立的文件描述符关闭操作
子进程关闭某个文件描述符不会影响父进程的同名描述符,反之亦然。
三、关键机制:写时复制(COW)
内核通过写时复制技术优化性能:
• 原理:fork()
后,父子进程的页表项指向相同的物理内存页,并将这些页标记为只读。当某一进程尝试写入时,触发页错误,内核复制该页并修改权限为可写。
• 优点:避免不必要的内存复制,提高资源利用率。
四、应用注意事项
- 文件操作同步:父子进程对同一文件描述符的并发写入需通过锁(如
flock()
)或原子操作避免竞争。 - 内存共享限制:若需主动共享内存,需使用
mmap()
或共享内存API(如shmget()
)。 - 僵尸进程处理:父进程需通过
wait()
回收子进程资源,或注册SIGCHLD
信号处理函数。