14.多进程fork后不同进程会共享哪些资源
🔬 多进程fork后资源共享机制
📖 内容概览
本文详细介绍C++多进程编程中fork函数创建子进程后,父子进程之间资源共享的机制,包括文件描述符、内存映射、信号处理等方面,并通过示例代码演示资源共享的具体行为。
🎯 核心概念
✨ fork函数的基本概念
fork函数是创建新进程的系统调用,创建的子进程是父进程的副本。父子进程的虚拟存储空间用户空间是相同的,父进程的资源会被拷贝给子进程,但采用写时拷贝(Copy-on-Write)机制,只有在子进程修改数据时才会实际拷贝。
🔗 资源共享机制
父子进程在fork后共享以下资源:
- 文件描述符表:父进程打开的所有文件描述符在子进程中都存在副本
- 文件表和v-node表:所有进程共享文件表和v-node表,因此对文件的操作是共享的
- 内存映射:通过mmap创建的内存映射区域是共享的
- 信号处理函数:信号处理函数在fork后保持一致
🛠️ 代码示例
📝 文件描述符共享演示
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/wait.h>int main(){ int fd; char c[3];
/* 打开文件foobar.txt,采用只读形式 */ fd = open("foobar.txt", O_RDONLY, 0); if (fork() == 0) { // 子进程 read(fd, &c, 2); /* 读文件的两个字节到c中 */ c[2] = '\0'; printf("子进程读取: c = %s\n", c); exit(0); } else { // 父进程 wait(NULL); /* 等待子进程结束 */ read(fd, &c, 2); printf("父进程读取: c = %s\n", c); }}📋 运行结果
假设foobar.txt中的内容是”foobar”,编译运行后输出:
[gong@Gong-Computer cprogram]$ gcc -g fileshare2.c -o fileshare2[gong@Gong-Computer cprogram]$ ./fileshare2子进程读取: c = fo父进程读取: c = ob🔍 结果分析
🧩 共享文件指针
- 父子进程共享同一文件表,因此文件读写位置是共享的
- 子进程读取两个字节后,文件指针移动到位置2
- 父进程继续从位置2开始读取,因此读取到”ob”
- 这种共享机制使得父子进程可以协同操作同一文件
🧩 独立的文件描述符表
- 每个进程都有独立的文件描述符表
- 当父进程或子进程调用close(fd)时,只会关闭自己的文件描述符
- 只有当所有引用同一文件的文件描述符都关闭后,文件才会真正关闭
⚠️ 注意事项
- 写时拷贝机制:父子进程的内存空间在fork时是共享的,但当任一进程修改内存时,会触发写时拷贝,此时才会实际分配新的内存
- 信号处理:fork后子进程会继承父进程的信号处理函数,但子进程的信号掩码和挂起信号会被重置
- 文件锁:文件锁不会被继承,子进程需要重新获取锁
- 定时器:定时器不会被继承,子进程需要重新设置
- 进程ID和父进程ID:子进程的PID和PPID与父进程不同
📋 总结
- 共享资源:文件描述符表、文件表、v-node表、内存映射、信号处理函数
- 独立资源:进程ID、父进程ID、内存数据(写时拷贝)、信号掩码、挂起信号、文件锁、定时器
- 协同操作:通过共享文件指针,父子进程可以协同操作同一文件
- 写时拷贝:优化了fork的性能,避免了不必要的内存拷贝 理解fork后的资源共享机制对于编写正确的多进程程序至关重要,特别是在涉及文件操作、内存共享和信号处理时。