fork()出来一个进程,这个进程的父进程是从哪来的?
基本概念
fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.
fork()是一个系统调用,不是一个函数。详细信息可以,man fork。
如何查看进程ID
每个linux进程都一定有一个唯一的数字标识符,称为进程ID(process ID),进程ID总是一非负整数,它的父进程叫PPID。
查看进程ID命令:
ps -ef

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); 返回:调用进程的进程ID
pid_t getppid(void); 返回:调用进程的父进程ID第一个进程init
Linux内核启动之后,会创建第一个用户级进程init,由上图可知, init 进程 (pid=1) 是除了 idle 进程 (pid=0,也就是 init_task) 之外另一个比较特殊的进程,它是 Linux 内核开始建立起进程概念时第一个通过 kernel_thread 产生的进程,其开始在内核态执行,然后通过一个系统调用,开始执行用户空间的 / sbin/init 程序。
fork函数
创建一个进程很简单,先来认识一下fork函数:
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回:子进程中为0,父进程中为子进程I D,出错为-1
由fork创建的新进程被称为子进程( child process)。该函数被调用一次,但返回两次,两次返回的区别是子进程的返回值是0,而父进程的返回值则是子进程的进程ID。一般来说,在fork()之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。
#include <unistd.h>
#include <stdio.h>int main(int argc,char* argv[])
{pid_t pid;if((pid=fork()) == -1){perror("fork\n");return -1;}else if(pid == 0){printf("this is child process\n");printf("The return value %d in child process! My Pid is %d,My ppid is %d\n",pid,getpid(),getppid());}else{//usleep(1000);printf("this is parent process\n");printf("The return value %d in parent process! My Pid is %d,My ppid is %d\n",pid,getpid(),getppid());}return 0;
}
由上图可知,fork被调用了一次,返回了两次,一次是父进程执行,另外一次是子进程执行。
父子进程关系
使用fork系统调用得到的子进程是父进程的处继承了整个进程的地址空间,包括:[进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端]等。

fork出的子进程会继承父进程的文件描述符,如果读写文件,父子进程之间会互相影响。
./run.out 运行的程序父进程是谁?
我们来编写一个例子:
#include <unistd.h>
#include <stdio.h>int main(int argc,char* argv[])
{while(1);return 0;
}例子很简单,就是创建一个死循环的进程,编译执行。
ps -ef 查看进程ID
ps -ef > 1.txt
wj 40762 1648 0 2月23 ? 00:00:16 /usr/libexec/gnome-terminal-server
wj 558001 40762 0 11:05 pts/3 00:00:00 bash
wj 583066 558001 99 16:22 pts/3 00:01:19 ./run.out
从以上log可以看出来,run.out进程PID为583066,它的父进程为 558001,进程558001即为bash进程。
bash 的父进程为:/usr/libexec/gnome-terminal-server
所以大家应该明白,我们打开1个Linux终端,其实就是启动了1个gnome-terminal-server进程。我们在这个终端上执行./run.out其实就是利用gnome-terminal-server的子进程bash通过execve()将创建的子进程装入./run.out

父进程死了,子进程怎么办?
僵尸进程

如上图所示,父进程Process A创建子进程Process B,当子进程退出时会给父进程发送信号SIGCHLD;
如果父进程没有调用wait等待子进程结束,退出状态丢失,转换成僵死状态,子进程会变成一个僵尸进程。当父进程调用wait,僵尸子进程的结束状态被提取出来,子进程被删除,并且wait函数立刻返回。
当父进程调用wait,僵尸子进程的结束状态被提取出来,子进程被删除,并且wait函数立刻返回。
实例:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>int main(int argc,char* argv[])
{if(fork()){while(1){sleep(1);}}return 0;
}上述程序会保证父进程不退出,一直在while(1)中无限循环,而子进程会立刻退出。

由上图可知,父进程是585663,子进程是585664,子进程因为退出后父进程没有调用wait回收子进程资源,所以子进程585664变成僵尸进程defunct。
ps -ax | grep run.out 查看进程状态,进程状态为:Z+

孤儿进程
如果父进程退出,并且没有调用wait函数,它的子进程就变成孤儿进程,会被一个特殊进程继承,这就是init进程,init 进程会自动清理所有它继承的僵尸进程。
实例代码:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>int main(int argc,char* argv[])
{if(fork()){// parent process.}else{//child process.while(1){sleep(1);}}return 0;
}上述程序会保证子进程不退出,一直在while(1)中无限循环,而父进程会立刻退出。孤儿进程:
待确认?
相关文章:
fork()出来一个进程,这个进程的父进程是从哪来的?
基本概念fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.fork()是一个系统调用,不是一个函数。详细信息可以,man…...
结构体内存对齐
结构体相信大家已经了解过了,现在我们深入讨论一个问题,计算结构体的大小 也是很热门的一个考点:结构体内存对齐 先看看下面结构体的大小 typedef struct Test {char a;char b;char c; }Test; 很容易看出答案为3,结构体的大小位…...
【C语言进阶】指针进阶
今日所做之事勿候明天,自我所做之事勿候他人。 --歌德 目录 指针进阶(更深层次的理解): 一.字符指针 二.指针数组 三.数组指针 1.数组指针的定义: 2.&数组名和数组名: 3.数组指针的使用: 四.数组参数,指针参数 1.一维数组传参:…...
java:Class的isPrimitive方法使用
java:Class的isPrimitive方法使用 1 前言 java中Class类的isPrimitive方法,用于检查类型是否为基本类型。java虚拟机创建了int、byte、short、long、float、double、boolean、char这8种基础信息,以及void,一共9种。为这9种类型时…...
TCP 握手过程 三次 四次
蛋老师视频 SYN 同步 ACK 确认 FIN 结束 核心机制是确定哪些请求或响应需要丢弃 SYN、ACK、FIN 通过 1/0 设置开启/关闭 开启SYN后,报文中会随机生成 Sequence序号 用于校验 (应用可能发起多个会话,可以区分) 服务器的同步序…...
windows 下 安裝mysql 5.7.41 (64位) 超简单方式
文章目录1. 安装包下载2.安装步骤3. 服务卸载方式4. 配上 my.ini 常用配置1. 安装包下载 注意,截至2023年2月23日,MySQL所有版本不提供ARM芯片架构的Windows版本(8.0.12开始支持Red Hat系统的ARM版本),所以ARM架构的Windows无法安装MySQL&am…...
二叉树——二叉树的最近公共祖先
二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一…...
数据结构与算法基础-学习-14-线性表之串
一、串的定义由0-n个字符组成的有限序列。(n>0)二、串的相关术语1、子串串中任意个连续字符组成的子序列成为该串的子串。2、主串包含子串的串成为主串。3、字符位置字符在序列中的序号为该字符在串中的位置。4、子串位置子串第一个字符在主串中的位置…...
Mac 快捷键
目录 命令行快捷键 命令行快捷键 control d 命令行中代表发送EOF终止输入 control u 删除光标之前到行首的字符 control k 删除光标之前到行尾的字符(比较常用) control a 移动光标到行首(常用) control e 移动光标到行尾 control l 清屏,相当于clear命令 con…...
【微服务】-微服务环境搭建
目录 2.1 技术选型 2.2 模块设计 2.3 微服务调用 2.4 创建⽗⼯程 2.5 创建商品微服务 2.6 创建订单微服务 2.1 技术选型 持久层: SpingData Jpa 数据库: MySQL5.7 其他: SpringCloud Alibaba 技术栈 2.2 模块设计 --- shop-parent ⽗⼯程 --- shop-product-api 商品微服…...
IGKBoard(imx6ull)-ADC编程MQ-2烟雾传感器采样
文章目录1- ADC介绍2- MQ-2烟雾传感器介绍(1)工作原理(2)MQ-2应用电路3- MQ-2烟雾传感器硬件连接4- ADC驱动配置5- 编程查看当前浓度1- ADC介绍 ADC是Analog-to-Digital Converter的缩写,指模数转换器。真实世界的模拟…...
前端二面vue面试题总结
什么是 mixin ? Mixin 使我们能够为 Vue 组件编写可插拔和可重用的功能。如果希望在多个组件之间重用一组组件选项,例如生命周期 hook、 方法等,则可以将其编写为 mixin,并在组件中简单的引用它。然后将 mixin 的内容合并到组件中…...
时间API在更新,传奇已经谢幕,但技术永远不死
(Bill Joy(左一),Vinod Khosla(左二),Andy Bechtolsheim(右二),Scott McNealy(右一) ) CSDN 博文征集活动(和日期相关的代码和bug):点击这里 各位 “big guys”,这篇博文…...
SQL调优指南笔记22:Gathering Diagnostic Data with SQL Test Case Builder
本文为SQL Tuning Guide 第21章“Gathering Diagnostic Data with SQL Test Case Builder”的笔记。 SQL Test Case Builder 是一种工具,可自动收集在不同数据库实例中重现问题所需的信息。 SQL 测试用例是一组信息,使开发人员能够为遇到性能问题的特定…...
从0开始学python -43
Python3 正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。 re 模块使 Python 语言拥有全部的正则表达式功能。 compile 函数根…...
Kafka基本原理
总述 简介 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各…...
css3的重点内容
css3的重点内容 浮动 父级边框塌陷问题 浮动的清除 clear:left; //清除左侧浮动 clear:right; //清除右侧浮动 clear:both; //清除两侧浮动解决方案 增加父级元素的高度增加一个空的div,之后清除浮动通过overflow来进行相关元素的修剪给父类添加相应的伪类元素…...
《Roller: Fast and Efficient Tensor Compilation for Deep Learning》
《Roller: Fast and Efficient Tensor Compilation for Deep Learning》 用于深度学习 快速高效的张量编译器 作者 微软亚洲研究院以及多伦多大学等多所高校 摘要 当前编译为了产生高效的kernel时,搜索空间大,通常使用机器学习的方法 找到最优的方案…...
顺丰同城测试开发一面 49min答案,全文7000字,面试总结都在这里了
今天给大家分享一份顺丰同城的测试开发一面面试真题。老规矩,当你看到这份面试题的时候,先不要着急去看答案,你可以想想假如你在面试现场,你会怎么回答?这个思考的过程其实也是很重要的。 全文7000字干货,…...
docker启动容器服务之后访问失败
关于docker启动容器服务之后,宿主机访问失败(解决方法) 注:在进行docker容器启动宿主机进行容器访问时,无需进行网络的配置,docker容器在启动时会自动解决 第一种原因及修改方法 在进行启动的时候&#…...
ICLR2025杰出论文启示录:大模型安全、微调与知识编辑的三大前沿突破
1. 深度安全对齐:从表层防御到系统级防护 大语言模型的安全性问题一直是业界关注的焦点。普林斯顿大学和Google DeepMind的研究团队发现,当前主流的安全对齐方法存在一个致命缺陷——它们只停留在模型输出的前几个token层面。这就好比给房子装防盗门却忘…...
Python 日志神器 Loguru 超详细使用教程
前言 在 Python 开发中,日志记录是排查问题、监控程序运行的核心工具,但原生 logging 库配置繁琐、语法复杂,新手很难快速上手。Loguru 是一款极简、强大、开箱即用的第三方日志库,无需复杂配置,一行代码就能实现专业级…...
鸿蒙与微信开发深度融合:技术适配、实操指南与生态展望
鸿蒙与微信开发深度融合:技术适配、实操指南与生态展望 随着鸿蒙系统(HarmonyOS NEXT)的全面普及,其分布式架构、原生生态的优势日益凸显,成为移动应用开发的新赛道。微信作为国民级应用,其鸿蒙版的适配与开…...
二极管特性与19种经典应用电路详解
1. 二极管基础特性与工作原理二极管作为电子电路中最基础的半导体器件之一,其核心特性源于PN结的单向导电性。当P型半导体(空穴多数载流子)与N型半导体(电子多数载流子)结合时,在交界处形成耗尽层ÿ…...
大学生保护动物网页——web网页期末大作业
(文件先保存到自己网盘,谨防文件丢失!!) 源码获取地址 链接: https://pan.baidu.com/s/1bz6nL9WPBBsxxWVmBAfGXw?pwdrcwi提取码: rcwihtml个人网页源码 ✅ 网页一共4个页面 ✅ 网页使用html css完成 布局简单 ✅ 文…...
TypeScript 快速实战系列:基础入门|TypeScript 核心语法 1 小时吃透(必备基础)
🔥 导读:上一篇我们搞定了TS环境搭建,也搞懂了为什么大模型开发必须学TS。今天这篇,不搞复杂理论,只讲大模型开发中「最常用、最核心」的TS语法——基础类型类型注解,1小时就能吃透,学完就能给大…...
别再只会apt autoremove了!dpkg报错Sub-process returned error code (1)的5种修复姿势全解析
深度解析dpkg报错Sub-process returned error code (1)的5种专业修复策略 当你正在Ubuntu或Debian系统上安装某个关键软件包时,突然终端弹出一条刺眼的错误信息:"Sub-process /usr/bin/dpkg returned an error code (1)"。这不是普通的警告&am…...
AI教程——让每个人都能高效写出好故事
📖 AI小说创作系统:让每个人都能高效写出好故事 第一章:创作者的痛点在哪里? 写小说并不只是“把故事写出来”那么简单。很多创作者在第一章之后就陷入了困境: * 情节没头绪:故事开了头,但不知道怎么发展。 * 人物难塑造:角色扁平、动机混乱、行为前后不一。 * 设…...
Flutter Web:混合开发的最佳实践
Flutter Web:混合开发的最佳实践一次编写,多端运行。Flutter Web 让前端开发更加高效。一、Flutter Web 的优势 作为一名追求像素级还原的 UI 匠人,我对跨平台解决方案有着严格的要求。Flutter Web 不仅让我们能够使用相同的代码库构建 Andro…...
3款免费MySQL客户端实测对比:DBeaver、WorkBench、HeidiSQL哪个更适合你?
三款开源MySQL客户端深度横评:从安装到高阶功能的全方位指南 当Navicat的收费模式成为团队协作或个人开发的负担时,开发者们往往需要寻找功能相当但零成本的开源替代品。本文将基于实际工程经验,对DBeaver、MySQL Workbench和HeidiSQL这三款主…...
