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容器在启动时会自动解决 第一种原因及修改方法 在进行启动的时候&#…...
STM32模拟I2C驱动PCF8591避坑指南:为什么你的AD/DA数据总在跳?
STM32模拟I2C驱动PCF8591避坑指南:为什么你的AD/DA数据总在跳? 调试STM32与PCF8591的模拟I2C通信时,AD/DA数据跳动是开发者最常遇到的棘手问题。本文将深入分析数据不稳定的根源,并提供一套完整的解决方案。不同于基础教程&#x…...
基于适配器模式构建跨平台待办事项聚合器:设计、实现与实战
1. 项目概述:一个跨平台待办事项聚合器的诞生最近在整理自己的效率工具时,发现了一个挺普遍但又很恼人的问题:我的待办事项散落在各处。工作上的任务在公司的Jira里,个人学习计划在滴答清单,一些临时想法随手记在手机备…...
京东数据利器:掌握详情与评论资源
在电商高速发展的今天,数据是了解市场、洞察用户需求、优化产品策略的核心利器。京东作为国内领先的电商平台,其商品详情与用户评论数据承载了大量价值信息。掌握这些资源,不仅可以帮助商家、品牌方优化产品策略,还能辅助内容创作…...
LaTeX排版避坑指南:为什么你的多图caption编号对不齐?一个案例讲清subfig、minipage和tabular的选择
LaTeX多图排版实战:从编号错乱到完美对齐的解决方案 第一次在学术论文中遇到多图排版问题时,我盯着那个歪歪扭扭的(c)编号看了整整十分钟——它本该和(a)(b)整齐排列,却像迷路的孩子一样缩在角落。更糟的是,当我引用这些子图时&am…...
从pip._vendor.urllib3报错到apt-get失败:一次搞定Ubuntu网络DNS配置(附阿里云镜像加速)
从pip报错到apt-get失败:Ubuntu网络DNS配置全攻略 最近在Ubuntu 16.04上配置Python开发环境时,遇到了一个看似简单却令人头疼的问题——pip安装包时频繁报错pip._vendor.urllib3.connection.HTTPSConnection,紧接着发现连apt-get update也失败…...
从继电器到边缘计算:拆解PAC控制器里的‘智能手机’架构(以Codesys/倍福为例)
从继电器到边缘计算:拆解PAC控制器里的‘智能手机’架构 在工业自动化领域,PAC(可编程自动化控制器)正逐渐取代传统PLC,成为智能制造的核心大脑。这种转变类似于功能手机向智能手机的进化——从单一功能到开放平台&…...
如何快速掌握SRWE:Windows窗口分辨率自定义完整教程
如何快速掌握SRWE:Windows窗口分辨率自定义完整教程 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否曾遇到过游戏窗口大小不合适、截图分辨率不够高,或者想要为特定应用程序设置独…...
阿里云百炼接入OpenClaw全攻略
前置准备 已安装并可正常打开 OpenClaw Windows 版本 OpenClaw 部署包获取:https://xiake.yun/api/download/package/14?promoCodeIVD643FDE29AOpenClaw 顶部 Gateway 状态显示为在线准备好可正常登录的阿里云账号可正常访问阿里云百炼控制台地址确认账号已开通百…...
ZCU102开发板新手避坑:从官网下载MIG例程到LED闪烁的完整流程(Vivado 2023.1)
ZCU102开发板新手避坑:从官网下载MIG例程到LED闪烁的完整流程(Vivado 2023.1) 刚拿到ZCU102开发板时,那种既兴奋又忐忑的心情我至今记忆犹新。作为Xilinx旗下的高端FPGA开发平台,ZCU102强大的性能和丰富的接口让它成为…...
西门子博图V17变量导入昆仑通态MCGS Pro的保姆级避坑指南(含DB块偏移量设置)
西门子博图V17与MCGS Pro高效数据对接实战指南 在工业自动化系统集成中,西门子TIA Portal(博图)与昆仑通态MCGS Pro触摸屏的数据交互是常见需求。许多工程师在变量导入环节频繁遭遇DB块偏移量异常、变量名截断、数据类型不匹配等"暗坑&q…...
