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容器在启动时会自动解决 第一种原因及修改方法 在进行启动的时候&#…...
自动化数据清洗:OpenClaw+nanobot处理混乱的Excel表格
自动化数据清洗:OpenClawnanobot处理混乱的Excel表格 1. 为什么需要自动化数据清洗 作为一名经常处理外包数据的自由职业者,我每天都要面对各种来源混乱的Excel表格。这些表格往往存在表头不规范、格式不统一、缺失值等问题。传统的手动清洗不仅耗时耗…...
RT-Thread内核启动流程与自动初始化机制详解
RT-Thread内核启动流程深度解析1. RT-Thread内核架构概述RT-Thread是一款开源的实时操作系统(RTOS),其内核设计采用模块化架构,主要由两大部分组成:1.1 内核库实现内核库是RT-Thread独立运行的基础设施,提供了一套精简的C库函数实…...
在CentOS 7上远程跑3D应用:保姆级TurboVNC+VirtualGL配置与GPU调用验证
在CentOS 7上构建高性能远程3D工作站:TurboVNC与VirtualGL深度配置指南 当工程师需要远程操控配备NVIDIA GPU的服务器运行Maya、Paraview或TensorBoard等图形密集型应用时,直接使用传统VNC会遇到3D渲染性能低下的问题。本方案通过TurboVNC的高效压缩传输…...
OpenClaw+GLM-4.7-Flash自动化测试:3小时无人值守执行日志分析
OpenClawGLM-4.7-Flash自动化测试:3小时无人值守执行日志分析 1. 为什么选择这个技术组合 上个月团队新上线了一个分布式服务,每天产生近10GB的日志文件。最初我们尝试用传统脚本分析,但发现两个痛点:一是日志格式不统一&#x…...
Cuvil编译器避坑手册:97%新手踩过的5类IR转换陷阱,第4种会导致A100显存泄漏率飙升210%
第一章:Cuvil编译器在Python AI推理中的核心定位与价值Cuvil编译器并非传统意义上的通用语言编译器,而是专为Python生态中AI模型推理阶段深度优化的静态编译工具链。它在PyTorch、ONNX及自定义计算图之上构建轻量级中间表示(CIR)&…...
Conda环境下的WebRTC编译与部署:从源码下载到实战避坑指南
最近在做一个实时音视频项目,需要用到 WebRTC。作为一个习惯用 Conda 管理 Python 环境的开发者,我本能地想用 conda install 来搞定一切,结果发现这条路根本走不通。预编译的二进制包要么版本不对,要么依赖冲突,尤其是…...
UVM实战解析:从零构建高效验证环境的五大核心技巧
1. UVM验证环境搭建的核心逻辑 第一次接触UVM验证方法学时,我被它复杂的类库结构吓到了。直到在项目中真正搭建验证环境才发现,UVM的精髓在于分层设计思想。就像组装乐高积木,每个组件都有明确的职责边界。最让我印象深刻的是,一个…...
OpenClaw对接GLM-4.7-Flash:模型性能优化指南
OpenClaw对接GLM-4.7-Flash:模型性能优化指南 1. 为什么需要专门优化GLM-4.7-Flash的对接? 上个月我在本地部署了OpenClawGLM-4.7-Flash组合,原本期待它能流畅处理我的自动化办公需求,结果遭遇了典型的"水土不服"症状…...
高效PDF处理:PDF补丁丁的全场景应用指南
高效PDF处理:PDF补丁丁的全场景应用指南 【免费下载链接】PDFPatcher PDF补丁丁——PDF工具箱,可以编辑书签、剪裁旋转页面、解除限制、提取或合并文档,探查文档结构,提取图片、转成图片等等 项目地址: https://gitcode.com/Git…...
探索WLED:从入门到精通的智能LED控制指南
探索WLED:从入门到精通的智能LED控制指南 【免费下载链接】WLED Control WS2812B and many more types of digital RGB LEDs with an ESP8266 or ESP32 over WiFi! 项目地址: https://gitcode.com/GitHub_Trending/wl/WLED WLED是一款专为ESP8266和ESP32微控…...
