- 父进程和通过fork()函数创建的子进程之间确实采用了“写时复制”(Copy-On-Write, COW)技术。这种技术是为了提高内存使用效率和系统性能而设计的。以下是关于父进程和子进程之间共享和不共享内容的详细解释:
- 共享内容(复制的内容)
- 代码段(Code Segment):父进程和子进程共享相同的代码段。这是因为子进程是父进程的一个副本,它们执行相同的程序代码。代码段通常被标记为只读,以确保数据的一致性。
- 全局变量和静态变量(如果它们位于共享的数据段中):在某些情况下,全局变量和静态变量可能位于父进程和子进程共享的数据段中。但是,如果这些变量在后续的操作中被修改,写时复制技术会确保每个进程都有自己的变量副本。
- 文件描述符和其他系统资源:子进程会继承父进程的文件描述符和其他系统资源(如信号处理器(阻塞信号集)、网络连接等)。但是,需要注意的是,这些资源的修改(如文件写入)在默认情况下是独立的,因为写时复制技术会确保每个进程有自己的修改副本。
- 不共享内容(不复制的内容)
- 数据段(Data Segment)、堆(Heap)和栈(Stack):虽然子进程在创建时会得到父进程这些部分的副本,但它们并不共享这些内存区域。写时复制技术确保在需要修改这些区域时,会为子进程创建独立的内存副本。
- 进程ID(PID):每个进程都有一个唯一的进程ID,用于系统内部标识和管理进程。子进程会得到一个新的PID,与父进程的PID不同。
- 返回值:fork()函数在父进程中返回子进程的PID,而在子进程中返回0。这个返回值用于区分父进程和子进程的执行路径。
- 父进程ID(PPID):子进程的父进程ID(PPID)会被设置为父进程的PID,但父进程的PPID不会改变。
- 运行时间和计数器:如定时器、未决信号集等,这些与进程执行相关的运行时信息在每个进程中都是独立的。
- 共享内容(复制的内容)
- fork( )的写时拷贝技术(读时共享,写时复制)
- 子进程会复制父进程的文件描述符,阻塞信号集、代码段、堆栈、静态存储区(静态变量全局变量)
- 但是复制归复制,任一进程修改共享内容时还是会发生写时复制,就是为自己再创建一个副本。
- 未决信号集没复制
- 在Unix/Linux系统中,当父进程打开文件并创建子进程时,子进程会继承父进程的文件描述符表的一个副本。这意味着子进程和父进程拥有指向相同文件表项的不同文件描述符。
- 既然父进程和子进程共享文件描述符,如果两进程同时写同一个文件,那么是互相覆盖还是同时追加
- 如果两进程都以追加的模式写入文件,那么两进程在文件锁的同步机制下就会顺序追加到文件尾
- 如果两进程都以非追加的模式写入文件,那么两进程会在文件锁的同步下还是会互相覆盖。由于文件偏移量是共享的,如果两个进程都没有改变文件指针的位置(例如,没有调用lseek),那么它们可能会在同一个位置写入数据,从而导致覆盖。
- 那么可以采用两种应对方式
- 使用文件锁(如fcntl锁)来同步对文件的访问。
- 显式地管理文件指针的位置(lseek),确保每个进程在写入前都将文件指针移动到适当的位置。
父子进程之间的“写时拷贝,读时共享”技术介绍
于 2024-08-12 09:37:17 首次发布