【Linux】进程查看|fork函数|进程状态

🦄 个人主页——🎐开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁
🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁🍁🪁🍁🪁 🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁
感谢点赞和关注 ,每天进步一点点!加油!
目录
一、基本概念
1.1 概念提出
1.2 特征
二、描述进程-PCB
2.1 什么是进程控制块PCB
2.2 task_struct内容分类(成员)
2.3 进程控制块如何对进程进行管理的呢?
三、查看进程
3.1 通过系统目录查看
3.2 通过用户级工具ps查看
四、通过系统调用获取进程标识符(PID)
4.1 使用getpid和getppid
五、通过系统调用创建进程-fork初识
5.1 fork函数
5.2 fork函数创建子进程
六、Linux进程状态
七、两种特殊进程
7.1 僵尸进程
7.2 孤儿进程
一、基本概念
1.1 概念提出
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体(百度百科)。
1.2 特征
- 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
- 并发性:任何进程都可以同其他进程一起并发执行
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
- 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
- 结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。
二、描述进程-PCB
引入一个新概念: 进程控制块PCB(process control block)。PCB就是进程属性的集合(数据结构),里面存储的是进程信息。
2.1 什么是进程控制块PCB
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,称之为PCB(process control block),Linux操作系统下的PCB是: task_struct。
即task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含进程的信息。
2.2 task_struct内容分类(成员)
- 标示符(PID): 描述本进程的唯一标示符,用来区别其他进程(每次启动都会变化)。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器(pc): 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
- 上下文数据: 进程执行时处理器的寄存器中的数据。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟总和,时间限制,记账号等。
- 其他信息
2.3 进程控制块如何对进程进行管理
- 磁盘中的可执行程序在将要运行时,所有的进程中的数据(并不是程序本身)加载到内存中,此时操作系统会建立起一个PCB来保存每一个程序的信息;
- 这个时候PCB就会对每一个进程都建立起相应的结构体(即进程控制块)将对应的进程的属性、代码等匹配的传到这个结构体中:(这就是先描述)
- 此时,操作系统就会将每一个进程控制块都连接起来,形成链表结构,并返回头结点。这样便通过数据结构的形式将进程的信息组织起来。
三、查看进程
3.1 通过系统目录查看
根目录下的proc目录,/proc下存储着进程信息。

目录名为数字的即为进程信息的目录,每个目录内存储着他们对应的进程信息。而这些数字对应着该进程的标识符PID。如下查看标识符PID=18964的进程信息:

我们进入进程 18964进程目录

3.2 通过用户级工具ps查看
实例:ps ajx/ps aux
该命令可以查看所有系统进程。如下查看PID=18964的进程信息

创建如下测试脚本并执行
#!/bin/bashproc_test()
{while(true)doecho "I am a process!"sleep 1done
}proc_test## 执行
sh proc_test_18964.sh
另外通过指令对进程进行检测,检测它是否运行:
ps ajx | head -1 && ps ajx | grep proc_test | grep -v grep
这里grep实际也是进程,且该进程内包含有proc_test的信息,所以也显示出来了。-v选项是反向搜索的意思,即过滤掉包含有grep内容的信息。

- PPID (Parent Process ID):代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
- PID (Process ID): 代表这个进程的代号
- PGID(Process Group):PGID就是进程所属的Group的Leader的PID,如果PGID=PID,那么该进程是Group Leader
- SID(Session ID):和PGID非常相似,SID就是进程所属的Session Leader的PID,如果SID==PID,那么该进程是session leader
- TPGID:终端进程组ID
- STAT:进程状态
四、通过系统调用获取进程标识符(PID)
4.1 使用getpid和getppid
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t id = getpid();while (1){printf("I am a process!pid:%d\n", id);sleep(1);}return 0;
}
执行上面可执行程序并运行如下命令进行监控
while :; do ps ajx | head -1 && ps ajx | grep proc_test | grep -v grep ; sleep 1;done

函数getppid(获取父进程的进程标识符),一般在Linux中普通进程都有他的父进程。
每一个子进程都是由父进程创建出来的。
子进程只能有一个父进程,父进程可以有多个子进程。每次执行可执行程序,进程标识符会改变,因为每次都会创建新的进程。
编写如下测试代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t id = getpid();pid_t fid = getppid();while (1){printf("I am a process!pid:%d ppid:%d\n", id, fid);sleep(1);}return 0;
}
执行结果如下图:

多次执行我们发现程序多次执行子进程每次都会创建新的新的进程标识符,父进程标识符没有改变。如下父进程是bash命令行解释器。

五、通过系统调用创建进程-fork初识
5.1 fork函数
pid_t fork(void);
一个进程包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。
5.2 fork函数创建子进程
创建测试代码:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>int main()
{pid_t pid;printf("before fork : pid is : %d, ppid is : %d\n", getpid(), getppid());pid=fork();printf("after fork : pid is : %d, ppid is : %d, fork return %d\n", getpid(), getppid(),pid);sleep(2);return 0;
}
编译后执行
fork函数执行后,后面的"after fork"执行了两次,8897作为父进程创建了子进程 8898。也就是说fork之后,代码共享,从一个进程分为两个分支,一为父,一为子。
进程调用fork,当控制转移到内核中的fork代码后,内核会:
- 分配新的内存块和内核数据结构给子进程;
- 将父进程部分数据结构内容拷贝至子进程;
- 添加子进程到系统进程列表当中;
- fork返回,开始调度器调度;
所以,fork之前父进程独立执行,fork之后父子两个执行流分别执行。注意:fork之后谁先执行完全由调度器决定。
fork它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
(1) 在父进程中,fork返回新创建子进程的进程ID;
(2)在子进程中,fork返回0;
(3)如果出现错误,fork返回一个负值;
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
六、Linux进程状态
进程状态:
TASK_RUNNING:就绪/可运行状态
TASK_INTERRUPTABLE:进程被挂起(睡眠),直到等待条件为真被唤醒
TASK_UNINTERRUPTABLE:深度睡眠,睡眠期间不响应信号
TASK_STOPPED:进程的执行被暂停
TASK_TRACED:被其它进程跟踪,常用于调试
EXIT_ZOMBIE:僵死状态,进程的执行被终止
EXIT_DEAD:僵死撤销状态,防止wait类系统调用的竞争状态发送
可以使用man ps 查看进程状态 Ss、Sl、S+、Z、I 释义

具体解释如下:
- D (TASK_UNINTERRUPTIBLE) 不可中断的睡眠状态
- R (TASK_RUNNING) 正在运行,或在队列中的进程
- S (TASK_INTERRUPTIBLE) 可中断的睡眠状态
- T (TASK_STOPPED) 停止状态
- t (TASK_TRACED) 被跟踪状态
- Z (TASK_DEAD - EXIT_ZOMBIE) 退出状态,但没被父进程收尸,成为僵尸状态
- W 进入内存交换(从内核2.6开始无效)
- X (TASK_DEAD - EXIT_DEAD) 退出状态,进程即将被销毁
- < 高优先级
- N 低优先级
- L 有些页被锁进内存
- s 包含子进程
- 位于前台的进程组;
- l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
七、两种特殊进程
7.1 僵尸进程
1.僵死状态(Zombies)是一个比较特殊的状态。当子进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
测试代码 :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id > 0) { //parentwhile(1){printf("parent[%d] is sleeping...,ppid: %d\n", getpid(),getppid());sleep(1);}}else {printf("child[%d] is begin Z...,ppid: %d\n", getpid(),getppid());sleep(5);exit(1);}return 0;
}
fork函数执行后子进程PID:15156 在5 s后exit(1)异常退出 ,父进程15155没有读取到正常的退出代码导致产生僵尸进程。
进程PID:15156的名称加上了【】且后面跟着< defunct > (失效的)
7.2 孤儿进程
修改代码,让子进程和父进程同时不间断运行
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id > 0) { //parentwhile(1){printf("parent[%d] is sleeping...,ppid: %d\n", getpid(),getppid());sleep(1);}}else {while(1){printf("child[%d] is begin Z...,ppid: %d\n", getpid(),getppid());sleep(1);}}return 0;
}
运行
while :; do ps ajx | head -1 && ps ajx | grep pro_test | grep -v grep ; sleep 1;done
监控进程状态

杀掉父进程(10552),子进程被编号为1的进程接管,该1号进程就是bash,而bash就是父进程的父进程,父进程被杀死后,bash进程就接管了子进程,这种失去“爸爸”后被接管的进程就被称为孤儿进程。且子进程从前台进程变成了后台进程。
原文链接:fork函数详解-CSDN博客
【Linux】进程周边001之进程概念-CSDN博客
fork()函数详解_fork函数-CSDN博客
原文链接:Linux进程状态_task_interrupt-CSDN博客
相关文章:
【Linux】进程查看|fork函数|进程状态
🦄 个人主页——🎐开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁&am…...
LeetCode第98题 - 有效的括号
题目 解答 方案一 class Solution {public boolean isValidBST(TreeNode root) {if (root null) {return true;}if (root.left null && root.right null) {return true;}if (root.left ! null && root.left.val > root.val) {return false;}if (root.…...
Nacos学习思维导图
一、服务注册 参考文档:http://www.bryh.cn/a/118936.html https://blog.csdn.net/Saintmm/article/details/121981184 二、服务续约 参考文档:http://www.bryh.cn/a/118936.html https://blog.csdn.net/Saintmm/article/details/121981184 三、服务…...
新视野英语课本复盘1
the triumpth of years of hard work 多年的辛勤付出的胜利 get by on very little sleep 靠很少的睡眠勉强维持生活或工作 pursue new passions 追求新的热爱之事 reap the benefits of this opportunity 收获这个机会带来的益处 you will not only emerge as a more broadly …...
Sentinel整合OpenFeign
1、配置文件 feign:sentinel:enabled: true 2、 编写一个工厂类 import com.cart.cartservice.client.ItemClient; import com.cart.cartservice.entity.Item; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import org.sp…...
PyTorch实战:基于Seq2seq模型处理机器翻译任务(模型预测)
文章目录 引言数据预处理加载字典对象en2id和zh2id文本分词 加载训练好的Seq2Seq模型模型预测完整代码结束语 引言 随着全球化的深入,翻译需求日益增长。传统的人工翻译方式虽然质量高,但效率低,成本高。机器翻译的出现,为解决这…...
stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)
stm32学习总结:5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题) 文章目录 stm32学习总结:5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志(注意重定向printf到串口打印…...
SAFe大规模敏捷企业级实训
课程简介 SAFe – Scaled Agile Framework是目前全球运用最广泛的大规模敏捷框架,也是成长最快、最被认可、最有价值的规模化敏捷框架,目前全球SAFe认证专业人士已达80万人,福布斯100强的70%都在实施SAFe。本课程是一个2天的 SAFe权威培训课…...
中医电子处方系统,西医个体诊所门诊卫生室病历记录查询软件教程
中医电子处方系统,西医个体诊所门诊卫生室病历记录查询软件教程 一、软件程序问答 1、电子处方软件如何快速开单? 如下图,软件以 佳易王诊所电子处方管理系统V17.1版本为例说明 在开电子处方的时候可以按单个药品开,也可以直…...
搞定ESD(八):静电放电之原理图设计
文章目录 一、防护对象识别方法1.1 根据应用手册识别防护对象1.2 根据端口信号类型识别防护对象1.3 根据信号类型识别防护对象二、电路级ESD防护设计2.1 静电尖峰脉冲电压钳位设计(ESD器件并联)2.1.1 高速差分信号ESD防护设计2.1.2 低速信号ESD防护设计2.2 静电放电电流限制设…...
微前端 Micro App
MicroApp 官网链接 MicroApp 链接...
Java amr格式转mp3格式
1.问题描述 微信返回的语音是amr格式的,浏览器不能直接使用,所以需要转为mp3 注意:不能直接使用IO流转为mp3,不然H5还是用不了。转换之后的语音只能在播放器上播放,内里的文件格式其实还是amr 2.使用以下方式转换 音…...
Vue2面试题:说一下虚拟DOM的原理?
虚拟dom是对真实dom的抽象,本质是JS对象 在生成真实DOM之前,vue会把模板编译为一个虚拟dom,当里面某个DOM节点发生变动时,通过diff算法对比新旧虚拟DOM,发现不一样的地方直接修改在真实的DOM上 优点: 可以…...
Spring对bean的管理
一.bean的实例化 1.spring通过反射调用类的无参构造方法 在pom.xml文件中导入坐标: <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.29<…...
Character Controller Smooth
流畅的角色控制器 Unity的FPS解决方案! 它是一种具有非常平滑运动和多种设置的解决方案: - 移动和跳跃 - 坐的能力 - 侧翻角度 - 不平整表面的处理 - 惯性守恒 - 重力 - 与物理物体的碰撞。 - 支持没有家长控制的平台 此解决方案适用于那些需要角色控制器…...
企业内训系统源码开发实战:搭建实践与经验分享
本篇文章中,小编将带领读者深入探讨企业内训系统的源码开发实战,分享在搭建过程中遇到的挑战与解决方案。 一、项目规划与需求分析 通过对企业内训需求的深入了解,我们可以更好地定义系统架构和数据库设计。 二、技术栈选择 在内训系统开发…...
15.三数之和(双指针,C解答附详细分析)
题目描述: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含…...
SpringCloud微服务 【实用篇】| Dockerfile自定义镜像、DockerCompose
目录 一:Dockerfile自定义镜像 1. 镜像结构 2. Dockerfile语法 3. 构建Java项目 二: Docker-Compose 1. 初识DockerCompose 2. 部署微服务集群 前些天突然发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,…...
Vue3+TS+ElementPlus的安装和使用教程【详细讲解】
前言 本文简单的介绍一下vue3框架的搭建和有关vue3技术栈的使用。通过本文学习我们可以自己独立搭建一个简单项目和vue3的实战。 随着前端的日月更新,技术的不断迭代提高,如今新vue项目首选用vue3 typescript vite pinia……模式。以前我们通常使用…...
浅析锂电池保护板(BMS)系统设计思路(四)SOC算法-扩展Kalman滤波算法
BMS开发板 1 SOC估算方法介绍 电池SOC的估算是电池管理系统的核心,自从动力电池出现以来,各种各样的电池SOC估算方法不断出现。随着电池管理系统的逐渐升级,电池SOC估算方法的效率与精度不断提高,下面将介绍常用几种电池SOC估算方…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
HTTPS证书一年多少钱?
HTTPS证书作为保障网站数据传输安全的重要工具,成为众多网站运营者的必备选择。然而,面对市场上种类繁多的HTTPS证书,其一年费用究竟是多少,又受哪些因素影响呢? 首先,HTTPS证书通常在PinTrust这样的专业平…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...

一个进程包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。