当前位置: 首页 > news >正文

【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函数|进程状态

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&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学习思维导图

一、服务注册 参考文档&#xff1a;http://www.bryh.cn/a/118936.html https://blog.csdn.net/Saintmm/article/details/121981184 二、服务续约 参考文档&#xff1a;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模型模型预测完整代码结束语 引言 随着全球化的深入&#xff0c;翻译需求日益增长。传统的人工翻译方式虽然质量高&#xff0c;但效率低&#xff0c;成本高。机器翻译的出现&#xff0c;为解决这…...

stm32学习总结:5、Proteus8+STM32CubeMX+MDK仿真串口并使用串口打印日志(注意重定向printf到串口打印的问题)

stm32学习总结&#xff1a;5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志&#xff08;注意重定向printf到串口打印的问题&#xff09; 文章目录 stm32学习总结&#xff1a;5、Proteus8STM32CubeMXMDK仿真串口并使用串口打印日志&#xff08;注意重定向printf到串口打印…...

SAFe大规模敏捷企业级实训

课程简介 SAFe – Scaled Agile Framework是目前全球运用最广泛的大规模敏捷框架&#xff0c;也是成长最快、最被认可、最有价值的规模化敏捷框架&#xff0c;目前全球SAFe认证专业人士已达80万人&#xff0c;福布斯100强的70%都在实施SAFe。本课程是一个2天的 SAFe权威培训课…...

中医电子处方系统,西医个体诊所门诊卫生室病历记录查询软件教程

中医电子处方系统&#xff0c;西医个体诊所门诊卫生室病历记录查询软件教程 一、软件程序问答 1、电子处方软件如何快速开单&#xff1f; 如下图&#xff0c;软件以 佳易王诊所电子处方管理系统V17.1版本为例说明 在开电子处方的时候可以按单个药品开&#xff0c;也可以直…...

搞定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格式的&#xff0c;浏览器不能直接使用&#xff0c;所以需要转为mp3 注意&#xff1a;不能直接使用IO流转为mp3&#xff0c;不然H5还是用不了。转换之后的语音只能在播放器上播放&#xff0c;内里的文件格式其实还是amr 2.使用以下方式转换 音…...

Vue2面试题:说一下虚拟DOM的原理?

虚拟dom是对真实dom的抽象&#xff0c;本质是JS对象 在生成真实DOM之前&#xff0c;vue会把模板编译为一个虚拟dom&#xff0c;当里面某个DOM节点发生变动时&#xff0c;通过diff算法对比新旧虚拟DOM&#xff0c;发现不一样的地方直接修改在真实的DOM上 优点&#xff1a; 可以…...

Spring对bean的管理

一.bean的实例化 1.spring通过反射调用类的无参构造方法 在pom.xml文件中导入坐标&#xff1a; <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.29<…...

Character Controller Smooth

流畅的角色控制器 Unity的FPS解决方案&#xff01; 它是一种具有非常平滑运动和多种设置的解决方案&#xff1a; - 移动和跳跃 - 坐的能力 - 侧翻角度 - 不平整表面的处理 - 惯性守恒 - 重力 - 与物理物体的碰撞。 - 支持没有家长控制的平台 此解决方案适用于那些需要角色控制器…...

企业内训系统源码开发实战:搭建实践与经验分享

本篇文章中&#xff0c;小编将带领读者深入探讨企业内训系统的源码开发实战&#xff0c;分享在搭建过程中遇到的挑战与解决方案。 一、项目规划与需求分析 通过对企业内训需求的深入了解&#xff0c;我们可以更好地定义系统架构和数据库设计。 二、技术栈选择 在内训系统开发…...

15.三数之和(双指针,C解答附详细分析)

题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含…...

SpringCloud微服务 【实用篇】| Dockerfile自定义镜像、DockerCompose

目录 一&#xff1a;Dockerfile自定义镜像 1. 镜像结构 2. Dockerfile语法 3. 构建Java项目 二&#xff1a; Docker-Compose 1. 初识DockerCompose 2. 部署微服务集群 前些天突然发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…...

Vue3+TS+ElementPlus的安装和使用教程【详细讲解】

前言 本文简单的介绍一下vue3框架的搭建和有关vue3技术栈的使用。通过本文学习我们可以自己独立搭建一个简单项目和vue3的实战。 随着前端的日月更新&#xff0c;技术的不断迭代提高&#xff0c;如今新vue项目首选用vue3 typescript vite pinia……模式。以前我们通常使用…...

浅析锂电池保护板(BMS)系统设计思路(四)SOC算法-扩展Kalman滤波算法

BMS开发板 1 SOC估算方法介绍 电池SOC的估算是电池管理系统的核心&#xff0c;自从动力电池出现以来&#xff0c;各种各样的电池SOC估算方法不断出现。随着电池管理系统的逐渐升级&#xff0c;电池SOC估算方法的效率与精度不断提高&#xff0c;下面将介绍常用几种电池SOC估算方…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

VisualXML全新升级 | 新增数据库编辑功能

VisualXML是一个功能强大的网络总线设计工具&#xff0c;专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑&#xff08;如DBC、LDF、ARXML、HEX等&#xff09;&#xff0c;并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...