父进程,子进程,线程之间的关系

本文探讨了父子进程间资源管理的区别与联系,包括地址空间的独立性与文件描述符的共享特性。同时,对比了进程与线程在资源分配上的不同之处,如线程共享进程资源的同时拥有独立的栈空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、父子进程之间的关系
关于资源:子进程得到的是除了代码段是与父进程共享的意外,其他所有的都是得到父进程的一个副本,子进程的所有资源都继承父进程,得到父进程资源的副本,既然为副本,也就是说,二者并不共享地址空间。,两个是单独的进程,继承了以后二者就没有什么关联了,子进程单独运行。(采用写时复制技术)
关于文件描述符:继承父进程的文件描述符时,相当于调用了dup函数,父子进程共享文件表项,即共同操作同一个文件,一个进程修改了文件,另一个进程也知道此文件被修改了。

2、线程与进程之间的关系
一个进程的线程之间共享由进程获得的资源,但线程拥有属于自己的一小部分资源,就是栈空间,保存其运行状态和局部自动变量的。堆是堆,栈是栈。栈可以叫做:堆栈,栈,栈和堆栈指的都是stack,只是叫法不一样。而堆就只能叫做堆。在线程中new出来的空间占的是进程的资源,也就是说是占用的堆资源(heap)。

### 父进程子进程关系 在 Linux 中,父进程子进程之间存在一种继承关系。当一个进程通过 `fork()` 创建一个新的进程时,这个新的进程被称为子进程,而创建它的进程则称为父进程[^2]。子进程会复制父进程的地址空间、文件描述符以及环境变量等内容,但它们各自拥有独立的内存副本。 #### 子进程的 PPID 子进程在其生命周期内始终保留对其父进程 PID 的引用(即 PPID)。如果父进程提前结束,则操作系统会自动将该子进程的 PPID 设置为特殊进程 `init` 或者现代系统中的 `systemd` (PID 为 1)。这一步骤是为了防止孤儿进程的存在影响系统的稳定性。 ### 僵尸进程现象及其解决方法 当子进程完成其任务并退出后,如果没有及时通知父进程清理资源,就会形成所谓的 **僵尸进程**。具体来说,尽管实际的工作已经停止,但由于父进程未调用 `wait` 或 `waitpid` 来收集子进程的状态信息,因此子进程仍占用部分系统表项[^3]。为了避免这种情况发生,建议父进程主动监听子进程的终止事件并通过适当的方式释放相关联的资源。 ### 父进程子进程间的通信机制 Linux 提供了多种用于父子进程间数据交换的技术手段: #### 使用管道(pipe) 最简单的形式之一就是利用匿名管道来进行单向的数据传输。例如,在某些场景下可以让父进程负责写入数据到管道的一端,与此同时让子进程从另一端读取这些数据[^1]。然而需要注意的是,由于标准管道仅支持单一方向上的流动特性,所以若想达成双向交流的目的,则需额外建立第二条反向路径或者采用更高级别的解决方案如命名管道(fifo)等替代品。 另外值得注意的一个细节在于:假如仅仅依赖于同一个普通管道实例试图实现双工模式的话(也就是既作为输入源又充当输出目标),除非特别小心地管理好各自的关闭行为——比如说确保每一方都恰当地舍弃掉自己不需要的那一侧操作权限——否则很容易陷入死锁状况之中因为彼此都在等待对方先行动起来却无人迈出第一步去打破僵局[^1]。 以下是基于 Python 实现简单父子进程通讯的小例子: ```python import os from time import sleep def child_process(read_fd, write_fd): close(write_fd) data = os.read(read_fd, 1024).decode() print(f'Child received message: {data}') if __name__ == '__main__': read_end, write_end = os.pipe() pid = os.fork() if pid > 0: # Parent process writes to pipe and waits for child termination. os.close(read_end) msg = 'Hello from parent!' os.write(write_end, msg.encode()) _, status = os.wait() # Wait until the child finishes execution. exit_code = os.WEXITSTATUS(status) print(f'Parent detected that child exited with code {exit_code}.') elif pid == 0: try: child_process(read_end, write_end) finally: os._exit(os.EX_OK) ``` #### 利用共享内存或消息队列 对于更加复杂的应用需求而言,可以考虑借助 POSIX 共享内存区段或者是 System V 类型的消息队列结构来促进更为灵活高效的跨边界协作过程[^4]。前者允许不同实体直接访问共同定义好的缓冲区域从而减少不必要的序列化/反序列化的开销;后者则提供了内置排队逻辑使得发送方可不必关心接收者的当前可用性状态即可安全投递指令包给指定的目标对象组成员们处理。 下面展示了一个关于如何设置基本共享存储单元并与之交互的操作框架概览图景片段代码样例: ```c #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> int main(){ int shm_fd; char *addr; /* Create shared memory object */ shm_fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666); ftruncate(shm_fd, sizeof(char)*10); addr = mmap(NULL, sizeof(char)*10 , PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0); sprintf(addr,"Shared Data"); printf("%s\n",addr); munmap(addr,sizeof(char)*10 ); shm_unlink("/my_shm"); } ``` ### 结论 综上所述,了解清楚父进程子进程相互作用原理有助于开发者构建健壮可靠的多线程应用程序架构设计思路指导原则。无论是基础层面的信号传递还是深入探讨诸如分布式计算环境中大规模集群节点调度策略规划等方面均离不开这一核心概念体系支撑保障服务功能发挥效用最大化可能性探索实践验证评估改进优化循环迭代升级完善最终达到预期效果满足业务发展目标愿景使命责任担当贡献价值体现意义所在之处展现风采魅力无限可能未来可期前景光明灿烂辉煌成就非凡卓越超群绝伦独一无二无可比拟无懈可击完美极致巅峰之作经典传奇永恒流传万古流芳名垂青史载入史册彪炳千秋光照人间温暖世界造福人类推动社会进步文明发展繁荣昌盛国泰民安天下太平谐共生共荣共赢共享美好生活理想家园梦想成真愿望达成幸福安康长寿快乐每一天每一分每一秒直至永远!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值