【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博客

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/580911.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H.264宏块(Macroblock)概念(运动估计、变换编码、环路滤波)

参考文章&#xff1a;音视频高手课系列5-h264编码基础(宏块原理) 参考文章&#xff1a;切片slice与宏块&#xff0c;运动矢量 文章目录 使用videoEye分析视频宏块示例H.264宏块概念1. 宏块的定义2. 运动估计3. 变换编码4. 环路滤波5. 注意&#xff1a;宏块的概念既适用于帧内编…

基于Java Swing的图书管理系统

一、项目总体架构 本项目基于Java Swing框架&#xff0c;数据库采用的是MySQL。项目文件夹如下&#xff1a; 二、项目截图 1.登录和注册界面 2.用户界面 3.管理员管理图书类别 4.管理员管理书籍 5.管理员管理用户 项目总体包括源代码和课程论文&#xff0c;需要源码的…

通过MobaXterm远程连接Anolis

目录 前言&#xff1a; 一.设置ip 二.远程连接 前言&#xff1a; 小编已经阐述了如何安装Anolis系统&#xff0c;如果有不了解的小伙伴可以查看这一篇博客Anolis安装 这篇博客将会讲述如何远程连接Anolis系统。各位看官拿好板凳&#xff01; 一.设置ip 打开网卡所在位…

西门子PLC通过PROFINET协议与多功能电表通讯

西门子PLC通过PROFINET协议与多功能电表通讯 项目要求 西门子S71200PLC需要通过PROFINET协议和多功能电表通讯&#xff0c;读取线电压、相电压、线电流、相电流、有功功率、无功功率等参数。 项目实施 采用网关NET90-PN-MBT&#xff08;以下简称“网关”&#xff09;&#…

怎么提取视频中的背景音乐?

当我们在刷视频的时候&#xff0c;有时候听到一个背景音乐很好听&#xff0c;但是又不知道歌名&#xff0c;比如英语歌&#xff0c;这个时候我们很难找到这首歌&#xff0c;相信有很多朋友会遇到这样的问题&#xff0c;不知道怎么弄&#xff0c;下面小编给大家推荐一些方法帮助…

Pytorch从零开始实战14

Pytorch从零开始实战——DenseNet SENet算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——DenseNet SENet算法实战环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#x…

亿赛通电子文档安全管理系统 linkfilterservice 未授权漏洞

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

Spring企业开发核心框架

文章目录 Spring企业开发核心框架一、框架前言1. 总体技术体系2. 框架概念和理解 二、Spring Framework简介1. Spring 和 SpringFramework2. SpringFramework主要功能模块3. SpringFramework 主要优势 三、Spring IoC 容器概念1. 组件和组件管理概念2. Spring IoC容器和容器实现…

ALS-运动系统解构

角色握持 角色蓝图&#xff1a;将物体绑在手上 动作蓝图&#xff1a; 将握持动画截取一帧&#xff08;explicit time时间写好&#xff09; 角色替换 在原人物模型下面加一个骨骼体&#xff08;先不用添加模型&#xff09;&#xff0c;重命名为bodymesh AI使用流程 新建一…

品牌如何在线上打造“社交货币”?媒介盒子揭秘

品牌的社交货币&#xff0c;是品牌与消费者的共识身份铸造器。竹筒奶茶、Keep奖牌这类的实体产品作为社交货币&#xff0c;每每能够引爆社交平台&#xff0c;那么品牌能否通过线上平台打造“社交货币”呢&#xff1f;接下来就让媒介盒子和大家聊聊。 一、社交货币是什么 社交货…

6.Nacos

1.单机部署 1.1 官网 https://nacos.io/zh-cn/index.html https://github.com/alibaba/Nacos 1.2.版本说明 https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.3.下载地址 https://github.com/alibaba/nacos/releases/tag/2.2.…

小区跑腿服务

社区跑腿服务是指在社区范围内为居民提供各种便利的服务&#xff0c;包括购物代劳、快递代取、家政服务等。 这种服务的出现&#xff0c;满足了居民生活中诸多需求&#xff0c;受到了广泛的欢迎和认可。 首先&#xff0c;社区跑腿服务方便了居民的日常生活。 居民无需亲自前…

克魔助手工具下载、注册和登录指南

下载安装克魔助手 摘要 本文介绍了如何下载安装克魔助手工具&#xff0c;以及注册和登录流程。通过简单的步骤&#xff0c;用户可以轻松获取并使用该工具&#xff0c;为后续的手机应用管理操作做好准备。 引言 克魔助手是一款免费的手机管理工具&#xff0c;通过该工具用户…

文章解读与完整程序——《考虑“源-荷-储”协同互动的主动配电网优化调度研究》

摘要&#xff1a;伴随智能电网的建设和清洁能源的开发利用,配电网中的负荷类型呈现多元化发展,分布式电源、可控负荷、储能等资源的增加让单向潮流的传统配电网逐渐向双向潮流的主动配电网结构转变。在能源结构转变的同时,清洁能源自身的随机性和波动性给配电网带来了更大的调峰…

2023.12.25 关于 Redis 数据类型 Hash 常用命令、内部编码、应用场景

目录 Hash 数据类型 Hash 操作命令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET HLEN HSETNX HINCRBY HINCRBYFLOAT HSTRLEN Hash 编码方式 理解什么是压缩 Hash 实际应用 Cache 缓存 Hash 数据类型 整体上来说 Redis 是键值对结构&#xff0c;其中 …

使用docker创建自己的Android编译容器

文章目录 背景步骤1.创建Dockerfile2.编写Dockerfile指令3.编译4.使用 背景 每次拿到新机器或者系统重装&#xff0c;最麻烦的就是各种环境配置&#xff0c;最近学习了一下docker的知识&#xff0c;用dockerfile创建一个Android编译容器&#xff0c;这样就不用每次都吭哧吭哧的…

python 通过(三维坐标)生成(三维曲面地形图)和(圆柱曲面地形图)

有需要源代码CSDN私信我 注意 python项目移植前要进行以下操作 1.python项目备份 2.生成requirements.txt的库文件 以pycharm为例&#xff0c;生成Python项目所需要的依赖库/包文档&#xff1a;requirements.txt_如何将pycharm项目安装的库文件导出为requirement.txt-CSDN博…

揭秘千巡翼X4卫星通讯无人机

揭秘千巡翼X4卫星通讯无人机 在无人机作业的时候&#xff0c;经常遇到这些异常场景&#xff0c;例如通信网络中断&#xff0c;强干扰&#xff0c;导致无人机无法与飞手通信等。而这些给无人机作业带来三大难题&#xff1a; 难题1&#xff0c;山区作业时通信中断&#xff0c;飞…

Cookie的详解使用(创建,获取,销毁)

文章目录 Cookie的详解使用&#xff08;创建&#xff0c;获取&#xff0c;销毁&#xff09;1、Cookie是什么2、cookie的常用方法3、cookie的构造和获取代码演示SetCookieServlet.javaGetCookieServlet.javaweb.xml运行结果如下 4、Cookie的销毁DestoryCookieServletweb.xml运行…

Swift 周报 第四十二期

文章目录 前言新闻和社区苹果 CEO 库克透露接班计划&#xff0c;希望继任者来自公司内部消息称苹果自研 5G 调制解调器开发再“难产”&#xff0c;将推迟到 2026 年 提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组整理周报的第四十二期&…