【Linux 08】进程概念

news/2024/4/27 13:55:27/文章来源:https://blog.csdn.net/shangguanxiu/article/details/136173628

文章目录

  • 🌈 01. 基本概念
  • 🌈 02. 描述进程 PCB
  • 🌈 03. 使用 ./ 的方式创建进程
  • 🌈 04. ps 查看进程
  • 🌈 05. getpid / getppid 获取进程标识符
  • 🌈 06. kill 终止指定进程
  • 🌈 07. fork 创建子进程
  • 🌈 08. 进程状态
    • 1. 进程基本状态
    • 2. 查看进程状态
  • 🌈 09. 僵尸进程
  • 🌈 10. 孤儿进程

🌈 01. 基本概念

1. 课本概念

  • 程序的一个执行实例,表示正在执行的程序。
  • 一个任务就是一个进程,一个程序可以启动多个进程,程序只有一个,而一个程序可以有多个进程。

在这里插入图片描述

2. 内核概念

  • 分配系统资源 (CPU时间、内存) 的实体称为进程。

🌈 02. 描述进程 PCB

  • 将外存中的可执行程序的代码和数据加载到内存当中,但光凭对应的代码和数据不足以描述进程信息。
  • 进程信息被放在一个叫做==进程控制块 PCB (process control block) ==的结构体中。
  • 在操作系统学科中,每个进程都要有一个 struct PCB 的结构体来管理这些进程的信息,Linux 操作系统下的 PCB 就是 task_struct

在这里插入图片描述

  • 操作系统为了管理所有的进程,规定了一个进程,一定要有一个 PCB

进程的定义

  • 进程 = PCB + 自己的代码和数据
  • 对进程的管理就是对 PCB 构成的链表的增删查改操作。

🌈 03. 使用 ./ 的方式创建进程

  • ./某个可执行程序:本质就是让系统创建进程并运行。我们自己编写形成的可执行程序 = 系统命令 = 可执行文件。在 Linux 中运行的大部分执行操作,本质都是运行进程。

在这里插入图片描述

🌈 04. ps 查看进程

指令ps axj

功能:查看当前系统中所有正在运行的进程。

示例

  • 直接使用 ps axj 查看的是所有的进程信息

在这里插入图片描述

  • 如果需要查看指定进程则需要搭配 管道 | 和 grep 获取关键字信息这两个指令。

在这里插入图片描述

🌈 05. getpid / getppid 获取进程标识符

1. 进程标识符

  • pid:进程的 id,也成为进程的标识符,是每个进程所拥有的唯一标识符。
  • ppid:本进程的父进程的 id。

2. 获取进程 pid

  • getpid():获取进程自身的 pid。
  • getppid():获取进程的父进程的 pid。

3. 获取 pid / ppid 示例

  • 使用如下代码获取进程的 pid 并保证进程不会结束。
#include <unistd.h>
#include <iostream>
#include <sys/types.h>using std::cout;
using std::endl;int main()
{while(1){// 获取当前进程的 pid 与 ppidcout << "I am a process pid: " << getpid() << "ppid: " << getppid() << endl;sleep(1);}return 0;}
  • 发现获取到的进程 pid 和 ppid 与使用 ps 指令查询到的进程 pid 一致。

在这里插入图片描述
在这里插入图片描述

🌈 06. kill 终止指定进程

常见指令

指令功能
kill -9 pid终止指定 pid 所标识的进程
kill -19 pid暂定指定 pid 所标识的进程
kill -18 pid解除暂停 pid 所标识的进程

终止进程示例

  • 使用 getpid 获取到的 myprocess 进程的 pid 的来终止该进程。

在这里插入图片描述

🌈 07. fork 创建子进程

1. fork 的返回值说明

fork() 的返回值说明
返回值 < 0子进程创建失败
返回值 == 0子进程创建成功,返回子进程 pid 给父进程,返回 0 给子进程
子进程 pid表示父进程,父进程通过接收子进程 pid 管理子进程

2. 创建进程的本质

  • 创建一个进程,本质是系统中多出一个子进程,即多了一个内核 task_struct2,子进程与父进程都各自拥有自己的代码和数据。
  • 默认情况下,子进程会继承父进程的代码和数据,包括 PCB 也会以父进程的 PCB 为模板来初始化。
  • 父子进程之间代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
  • 因为父子进程之间的代码是共享的,在执行子进程自己的代码时会顺带着再执行一遍父进程的代码,这种情况下,创建出子进程就没有任何意义了。
  • 因此在 fork 之后,如果想要单独执行子进程的数据,就要使用 if 对父子进程的代码和数据进行分流

3. 创建子进程的原因

  • 希望子进程和父进程执行不一样的代码部分,让多个进程并发跑起来。

4. 多进程中使用 if 让父子进程执行不同的代码

#include <unistd.h>
#include <iostream>
#include <sys/types.h>using std::cout;
using std::endl;int main()
{                                                                                                                                                                             pid_t id = fork();if (0 == id)    // 执行子进程部分代码  cout << "I am child process" << endl;  else if(id < 0) // 子进程的创建失败了cout << "process creation failure" << endl;else            // 执行父进程部分代码                                                                                                                            cout << "I am parent process" << endl;return 0;                               
}
  • 父子进程各执行了自己的那部分代码。
  • 关于 fork 函数为什么会有两个返回值的问题看虚拟地址空间 + 父子写时拷贝

在这里插入图片描述

🌈 08. 进程状态

1. 进程基本状态

  • 任何一个进程在运行的时候都要有对应的状态,一个进程可以拥有几个状态。
  • 进程状态是 task_struct 内部的一个属性,更改进程状态就是更改其状态属性。
状态标识符标识符说明状态说明
R运行状态 running进程处于运行中或运行队列里
S睡眠状态 sleeping浅度睡眠,进程在等待 “资源” 就绪,睡眠状态可被中断
D磁盘休眠状态 disk sleep深度睡眠,不可中断睡眠,该状态的进程不会被操作系统干掉
T停止状态 stoppedkill -19 pid 暂停进程;kill -18 pid 解除暂停
Z僵尸状态 zombies进程退出时,会暂时处于僵尸状态,要将退出信息保留在自己的 PCB 中,没人读取这些退出信息回收该进程时,该进程就不会释放,此时就一直处于僵尸状态

2. 查看进程状态

1. R 运行状态

  • 编写一段死循环的代码,能够让 CPU 一直处在运行状态。
#include <iostream>
#include <unistd.h>
#include <sys/types.h>int main()                                                                         
{while(1);return 0;
}
  • R+ 表示该进程在前台运行

在这里插入图片描述

2. S 睡眠状态

  • 编写如下一段死循环打印的代码。
#include <iostream>
#include <unistd.h>
#include <sys/types.h>int main()                                                                         
{while(1)cout << "sleeping" << endl;return 0;
}
  • 因为 CPU 绝大部分时间都 在等待显示器打印信息,因此绝大部分时间处于睡眠状态。

在这里插入图片描述

3. T 暂停状态

  1. 暂停指定进程:kill -19 对应进程 pid

在这里插入图片描述

  1. 解除进程暂停:kill -18 对应进程 pid,恢复的进程会跑到后台状态自动变成 R。

在这里插入图片描述

🌈 09. 僵尸进程

僵尸进程概念

  • 已经运行完毕,但是需要维持自己的退出信息,自己的进程 task_struct 会记录自己的退出信息,未来让父进程读取。
  • 子进程退出时不会立即退出,此时处于僵尸状态,父进程没有读取到退出信息,无法对该进程回收时就会一直处于僵尸状态。无法使用 kill 指令干掉僵尸进程。
  • 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
  • 如果一直处于僵尸状态,即僵尸进程一直存在,则会造成内存泄漏

僵尸进程示例

  • 使用如下代码让父进程多运行一会,保证子进程退出时,父进程还在运行。
#include <iostream>
#include <unistd.h>
#include <sys/types.h>using std::cout;
using std::endl;int main()
{pid_t id = fork();if (0 == id)	// 子进程{cout << "I am child pid: " << getpid() << endl;sleep(5);}else			// 父进程{cout << "I am father ppid: " << getppid() << endl;sleep(100);}return 0;
}     

在这里插入图片描述
在这里插入图片描述

🌈 10. 孤儿进程

孤儿进程概念

  • 孤儿进程听名字就知道是个什么东西,父进程如果先行退出,子进程就会变成孤儿进程。
  • 为了避免未来孤儿进程在退出后无法被回收,因此孤儿进程会被 1 号进程 (操作系统) 领养

孤儿进程示例

  • 对僵尸进程的示例代码进行改动,让父进程先行结束掉,即可看到孤儿进程的情况。
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>using std::cout;
using std::endl;int main()
{pid_t id = fork();if (0 == id)	// 子进程{cout << "I am child pid: " << getpid() << endl;sleep(100);}else			// 父进程{cout << "I am father ppid: " << getppid() << endl;sleep(5);exit(0);}return 0;
}
  • 通过图 1 可以看到子进程 28689 的父进程 ppid 是 26543,图 2 在执行完父进程后,子进程 28689 的父进程就变成了 1 号进程。

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

python学习14:python中的表达式

python中的表达式 1.表达式是什么呢&#xff1f; 表达式就是一个具有明确结果的代码语句&#xff0c;如11、type(‘字符串’)、3*5等 在定义变量的时候&#xff0c;如age108,等号右侧的就是表达式&#xff0c;也就是有具体的结果&#xff0c;将结果赋值给了等号左侧的变量 2.…

Linux 系统基础操作命令

当前市面上常见的系统&#xff1a;Windows、Linux、Mac OS、Android、IOS…… Linux 不太适合日常使用&#xff0c;但是非常适合用于开发。因此作为一个程序猿来说&#xff0c;Linux 都是务必要掌握的。 Linux 介绍 Linux 发行版 目前市面上比较知名的发行版有&#xff1a;R…

DNS隧道攻击

什么是DNS隧道&#xff1f; DNS隧道是一种网络通信技术&#xff0c;它利用DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;协议来建立隐蔽的通信通道。在正常情况下&#xff0c;DNS协议主要用于将域名解析为IP地址&#xff0c;但攻击者可以通过构造特殊的…

总结 | vue3项目初始化(附相应链接)

如何运行 vue 项目&#xff1a;vscode运行vue项目_vscode启动vue项目命令-CSDN博客 vue3项目搭建 目录管理 git管理&#xff1a;vue3项目搭建并git管理_git 新建vue3项目-CSDN博客 目录调整&#xff1a;vue3项目 - 目录调整-CSDN博客 vscode中快速生成vue3模板&#xff1a…

实现能效升级 | 基于ACM32 MCU的冰箱压缩机变频方案

概述 冰箱制冷系统中最重要的部件是压缩机。它从吸气管吸入低温低压的制冷剂气体&#xff0c;通过电机运转带动活塞对其进行压缩后&#xff0c;向排气管排出高温高压的制冷剂气体&#xff0c;为整个制冷循环提供源动力。这样就实现了压缩→冷凝→膨胀→蒸发 ( 吸热 ) 的制冷循环…

并查集|1971. 寻找图中是否存在路径、684.冗余连接、685.冗余连接II

目录 并查集基础 1971. 寻找图中是否存在路径 684.冗余连接 685.冗余连接II 并查集基础 并查集主要有三个功能。 寻找根节点&#xff0c;函数&#xff1a;find(int u)&#xff0c;也就是判断这个节点的祖先节点是哪个将两个节点接入到同一个集合&#xff0c;函数&#xf…

项目中自动引入神器 - unplugin-auto-import/unplugin-vue-components

前端 项目中 自动引入 神器 前言 在开发中&#xff0c;我们总喜欢站在巨人的肩膀上开发&#xff0c;比如用一些 框架&#xff1a;vue,react, 组件库&#xff1a;element&#xff0c;ant。 工具函数&#xff1a;axios&#xff0c;lodash 现在是模块化时代&#xff0c;我们…

新手入门C语言之联合体和枚举

在上一篇文章中&#xff0c;我们了解到在C语言中&#xff0c;自定义类型有三种&#xff0c;这里我们介绍后两种&#xff0c;联合体和枚举。 一.联合体 1.联合体的声明 像结构体一样&#xff0c;联合体也是由一个或多个成员构成&#xff0c;这些成员的类型可以是不一样的&…

Go——结构体

Go语言中没有类的概念&#xff0c;也不支持类的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。 一. 类型别名和自定义类型 1.1 自定义类型 在Go语言中有一些基本的数据类型&#xff0c;如string&#xff0c;整型&#xff0c;…

手机网页关键词视频爬虫采集软件可导出视频分享链接|视频无水印批量下载工具

全新音视频批量下载工具&#xff0c;为您解放视频管理烦恼&#xff01; 现如今&#xff0c;音上涌现出大量精彩的视频内容&#xff0c;但是要想高效地获取、管理和分享这些视频却是一件颇具挑战的事情。针对这一难题&#xff0c;我们自主研发了全新的音视频批量下载工具&#x…

数学建模体育建模和经济建模国防科大版

目录 6.体育中的数学建模 7.经济学问题中的数学建模 7.1.实物交换模型 7.2.边际效应 7.3.最佳消费选择模型 6.体育中的数学建模 体育科学的研究中&#xff0c;也有大量的数学建模问题&#xff0c;例如&#xff1a;棒球的最佳击球点问题、滑板滑雪赛道的设计、越野自行车比…

各种需要使用的方法-->vue/微信小程序/layui

各种需要使用的方法-->vue/微信小程序/layui 1、vue里样式不起作用的方法&#xff0c;可以通过deep穿透的方式2、 js获取本周、上周、本月、上月日期3、ArrayBuffer Blob 格式转换ArrayBuffer与Blob的区别ArrayBuffer转BlobBlob转ArrayBuffer需要借助fileReader对象 4、使用…

STM32使用滴答定时器实现delayms

在STM32上使用SysTick实现jiffies&#xff08;时间戳&#xff09;并且实现delay_ms 代码实现&#xff1a; volatile uint32_t jiffies 0; // 用于记录系统运行的jiffies数 void SysTick_Handler(void) {/* 每次SysTick中断&#xff0c;jiffies增加 */jiffies; }uint32_t tick…

如何利用生成式人工智能挑选合适的候选人?

在当今激烈的商业竞争中&#xff0c;招聘合适的人才是构建企业成功的基石。筛选和面试候选人是一个复杂且精细的过程&#xff0c;它不仅关系到职位的有效填补&#xff0c;更影响到企业的长期发展和团队建设。 选择合适候选人的重要性 选择合适的候选人就像寻找一片沙滩上的珍…

曲线生成 | 图解Reeds-Shepp曲线生成原理(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 什么是Reeds-Shepp曲线&#xff1f;2 Reeds-Shepp曲线的运动模式3 Reeds-Shepp曲线算法原理3.1 坐标变换3.2 时间翻转(time-flip)3.3 反射变换(reflect)3.4 后向变换(backwards) 4 仿真实现4.1 ROS C实现4.2 Python实现4.3 Matlab实现 0 专栏介绍 &#x1f5…

MP4如何把视频转MOV格式? MP4视频转MOV格式的技巧

在现代的数字媒体时代&#xff0c;视频格式转换成为了许多用户必须掌握的技能。特别是将MP4视频转换为MOV格式&#xff0c;这对于需要在Apple设备上播放或编辑视频的用户来说尤为重要。本文将详细介绍如何将MP4视频转换为MOV格式&#xff0c;帮助读者轻松应对不同设备和平台的需…

编程语言|C语言——C语言基本数据类型

前言 针对不同的数据&#xff0c;采取不同的存储方式和进行不同的处理。随着处理对象的复杂化&#xff0c;数据类型也要变得更丰富。数据类型的丰富程度直接反映了程序设计语言处理数据的能力。 C语言很重要的一个特点是它的数据类型十分丰富。因此&#xff0c;C语言程序数据处…

【Nuxt3】modules目录和nuxt3模块的简单介绍

简言 记录下nuxt3项目中module的用法 modules目录 使用 modules/ 目录在应用程序中自动注册本地模块。 这是一个很好的地方&#xff0c;可以放置您在构建应用程序时开发的任何本地nuxt模块。 nuxt模块相当于npm包&#xff0c;可以发布到npm社区中 在modules/ 目录下的本地模…

二叉树|654.最大二叉树

力扣题目地址 class Solution { public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {TreeNode* node new TreeNode(0);if (nums.size() 1) {node->val nums[0];return node;}// 找到数组中最大的值和对应的下标int maxValue 0;int maxValueIn…

Kubernetes生产集群部署指南

部署生产就绪的Kubernetes集群需要考虑到管理、负载均衡、安全、存储等很多细节&#xff0c;本文给出了一个生产就绪Kubernetes集群的完整部署流程&#xff0c;可以作为生产部署的有效参考。原文: Deploying a Production Kubernetes Cluster in 2023 — A Complete Guide Grow…