【Linux】进程的概念

文章目录

  • 1. 基本概念
  • 2. 进程的描述
  • 3. 进程的一些基本操作
    • 3.1 查看进程
    • 3.2 结束进程
    • 3.3 通过系统调用获取进程标示符
    • 3.4 通过系统调用来创建子进程
  • 4. 进程状态
    • 4.1 操作系统的进程状态
    • 4.2 Linux对于这些状态的处理方式

1. 基本概念

什么是进程?

在回答这个问题之前想问另一个问题:什么是程序?

  • 我们写的代码(源文件)在经过编译器编译之后生成的是文件,那么就是存放在磁盘中的。所以程序的本质就是文件,在磁盘存放

所谓的进程,就是运行着的程序,我们知道程序的运行肯定是需要CPU做运算的,CPU只能直接与内存做交互,所以程序一定要加载到内存中才能运行(这是体系结构决定的!!)。

同一时间,内存中会有很多进程,所以我们就要这些进程**管理**起来。

那么,怎么管理呢?

2. 进程的描述

在上一篇文章中我们讲到,所谓的管理就是:先描述,再组织

我们一般会采用一个结构体来描述这些进程的相关属性

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。课本上称之为PCB(process control block), Linux操作系统下的PCB是: task_struct

image-20231017144945959

上面是部分内核的代码截图,实际上内核中有关task_struct的代码有很多,主要可以分为以下几类

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程;
  • 状态: 任务状态,退出代码,退出信号等;
  • 优先级: 相对于其他进程的优先级;
  • 程序计数器: 程序中即将被执行的下一条指令的地址;
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针;
  • 上下文数据: 进程执行时处理器的寄存器中的数据;
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表;
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等;
  • 其他信息

抽象出来大概可以这样表示:(假设系统中进程使用链表的结构组织)

struct task_struct
{//进程的所有属性//...//进程对应的代码和数据的地址//...//下一个进程的地址struct task_struct* next;
};

关于task_strcut更详细的讲解,可以看一看这一篇博客:Linux中进程控制块PCB-------task_struct结构体结构(童嫣

有了上述的观念之后,我们从内核的角度来看,进程就是**内核数据结构(task_struct) + 进程对应的磁盘代码**

3. 进程的一些基本操作

3.1 查看进程

  1. 方法一:ps axj可以查看当前所有的进程

ps axj结合管道grep指令可以显示我们想要看到的进程,同时想要看到所有信息的含义,就要加上head -1表示将查询到的第一行数据也显示出来

image-20231017153523703

  1. 可以在/proc目录下查看当前所有进程

image-20231017154325799

3.2 结束进程

对于一般进程,我们可以使用**[Ctrl + c]结束,也可以使用kill**命令结束

image-20231017155140082

image-20231017155551984

3.3 通过系统调用获取进程标示符

每个进程都有一个唯一标识符:PID我们可以通过系统调getpid()用来获取这个唯一标识符

image-20231017160058629

注意:

  • 这里的getpid和getppid获取到的就是进程的标识符,其中getpid是获取进程的PID,getppid是用于获取父进程PID

  • 函数的返回值pid_t实际上就是int,只是在系统层面进行了封装

image-20231017162257157

image-20231017164705233

可以看到,我们通过 getpid() 和 getppid() 函数得到的值的确是我们进程对应的id;同时,我们发现myproc进程的父进程是 bash,即 shell 外壳,这也侧面证实了我们之前提到的结论 – shell 为了防止自身崩溃,并不会自己去执行指令,而是会派生子进程去执行

同一个程序重新被运行时它的进程id可能与之前不一样,因为它的代码和数据需要重新从磁盘中加载;但是它的父进程id一定是一样的,因为它们都是通过 bash 来执行

image-20231017164950366

3.4 通过系统调用来创建子进程

我们可以通过系统调fork来创建子进程

image-20231017165123058

image-20231017170441969

image-20231017170609253

可以看到,所有子进程的id都是0,父进程的id都是子进程的pid,这是因为fork的返回值规定:当fork执行之后将会产生两个进程,其中父进程的返回值是子进程的pid,子进程的返回值是0,fork之后的所有代码都被父子进程共有

4. 进程状态

4.1 操作系统的进程状态

在真正进入的进程状态的学习之前,大家或多或少应该听说过一些进程的状态,比如:挂起,僵尸等等,在进入的进程状态的学习之前,我们需要统一一些观点:

  1. 状态是进程内部的属性,所有的属性都在PCB里

  2. 进程不只会占用CPU资源,也有可能随时要外设资源

  • 运行状态

    进程PCB在运行队列里面的进程状态就是运行状态(不是说进程在运行时才是运行状态)

    运行队列的概念:

    CPU需要对进程做执行,同一时间操作系统内会有很多的进程,那么这些进程谁先谁后呢?此时就需要一个队列将这些进程管理起来,确定谁先执行谁后执行。这个队列里面保存的实际上并不是每个进程对应的二进制代码,而是PCB(task_struct),这个队列就是运行队列(run queue)

    每个CPU拥有一个运行队列

  • 阻塞状态

    我们在上面说到,进程不止会占用CPU资源,也可能随时需要外设资源,当一个进程在运行的过程中需要访问外设资源的时候,由于外设很慢(相对于CPU来说),所以进程需要等待外设,此时CPU就想去处理其他进程,那么当前进程就会进入到阻塞状态

    拓展一下:

    每个CPU执行一个进程,当前进程在处于阻塞状态,等待其他硬件资源的时候,实际上也就是当前进程的PCB进入到了其他硬件的run queue中,也就是说每一个硬件都拥有一个runqueue

  • 挂起状态

    如果系统中存在很多进程,当前进程短时间内不会被调度,代码和数据短时间内不会被执行,此时如果操作系统中的内存不够,就会将这些进程的相关信息保存在磁盘中,节省一部分内存。此时这些被保存在磁盘上的进程就是处于挂起状态

    挂起一定是阻塞的,阻塞不一定挂起

4.2 Linux对于这些状态的处理方式

在上一小节中我们讲到了操作系统内进程的概念性状态,那么在Linux下的表现形式是怎样的呢?

在Linux源码里面能够找到一个数组:task_state_array 罗列了Linux下所有的进程状态

/** The task state array is a strange "bitmap" of* reasons to sleep. Thus "running" is zero, and* you can test for combinations of others with* simple bit tests.*/
static const char *task_state_array[] = {"R (running)",		/*  0 */     // 运行状态"S (sleeping)",		/*  1 */     // 阻塞状态"D (disk sleep)",	/*  2 */     // 磁盘休眠状态/深度睡眠状态(了解)"T (stopped)",		/*  4 */     // 暂停状态"T (tracing stop)",	/*  8 */     // 该进程正在被追踪(看到的是t状态)"Z (zombie)",		/* 16 */     // 僵尸状态"X (dead)"		    /* 32 */     // 死亡状态
};

接下来我们来看一些进程状态的例子:

  • 运行状态:

image-20231031235917100

image-20231031235745673

  • 休眠状态

image-20231101000050282

image-20231101000033126

这里出现休眠状态的原因是:调用printf的时候需要访问外设——显示器,由于外设的速度很慢(相对于CPU而言),所以大部分时间都是在等在显示器资源,所以我们能看到的状态大多都是休眠。当然如果非常巧合的话,也是能看到R状态的

  • 暂停状态

image-20231101004334337
在这里插入图片描述

这里扩展一下:S是浅度睡眠,可以被终止;D是深度睡眠,无法被OS杀掉,只能通过断电、自己醒来进行解决。出现的原因一般是由于高IO导致的。

  • t状态

image-20231101005813173

image-20231101010109141

tracing stop表示该进程正在被追踪


本节完

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

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

相关文章

云安全—docker Deamon攻击面

0x00 前言 本篇文章主要是讲docker Deamon的原理以及docker Deamon攻击面相关的内容,属于抛砖引玉系列,如有不妥之处还请斧正。 0x01 docker Deamon 还是先来看一下docker Deamon的一些相关知识,依旧是采用问答的方式来进行。为了文章的整…

2023-11-04:用go语言,如果n = 1,打印 1*** 如果n = 2,打印 1*** 3*** 2*** 如果n = 3,打印

2023-11-04:用go语言,如果n 1,打印 1*** 如果n 2,打印 1***3*** 2*** 如果n 3,打印 1***3*** 2***4*** 5*** 6*** 如果n 4,打印 1***3*** 2***4*** 5*** 6***10** 9*** 8*** 7*** 输入…

Spring底层原理(六)

Spring底层原理(六) 本章内容 介绍AOP的实现方式、JDK代理的模拟实现与源码 AOP的实现方式 使用代理模式 jdk动态代理cglib动态代理 使用aspectj的编译器,该编译器会直接对字节码进行修改,可以实现静态方法增强 使用javaagent,在jvm option中指定-…

高匿IP有什么作用

在互联网的蓬勃发展中,IP地址作为网络通信的基础,一直扮演着举足轻重的角色。而在诸多IP地址中,高匿IP地址则是一种特殊类型,其作用和价值在某些特定场合下尤为突出。那么,高匿IP地址究竟有哪些用处呢? 首先…

[动态规划] (五) 路径问题: LeetCode 62.不同路径

[动态规划] (五) 路径问题: LeetCode 62.不同路径 文章目录 [动态规划] (五) 路径问题: LeetCode 62.不同路径题目解析解题思路状态表示状态转移方程初始化和填表返回值 代码实现总结 62. 不同路径 题目解析 (1) 机器人从左上角到右下角有多少方法 (2) 机器人只能向左或者向右…

掌握Maven和SpringBoot的灵活性:定制化lib目录和依赖范围

前言 在开发基于Maven和SpringBoot的项目时,我们经常会使用第三方库来满足需求。然而,有时候我们需要更灵活地控制这些库的依赖范围和加载方式。本文将介绍如何使用Maven和SpringBoot实现定制化的lib目录和依赖范围。经过如下定制化后,打包执…

[PyTorch][chapter 61][强化学习-免模型学习1]

前言: 在现实的学习任务中,环境 其中的转移概率P,奖赏函数R 是未知的,或者状态X也是未知的 称为免模型学习(model-free learning) 目录: 1: 蒙特卡洛强化学习 2:同策略-蒙特卡洛强化学习 3&am…

阿里云免费服务器

文章目录 最近的阿里云活动By the way在云服务器ECS上搭建个人网站正文补充:定期释放补充:不知道阿里云服务器的密码怎么办?成果补充:怎么找到实例操作的后台?补充:怎么查看服务器到期时间? 究竟白嫖了多少?最后&…

修复dinput8.dll文件的缺失,以及修复dinput8.dll文件时需要注意什么

dinput8.dll文件通常在使用大型游戏时容易出现dinput8.dll文件丢失的情况,今天这篇文章将要教大家修复dinput8.dll文件的缺失,同时在修复dinput8.dll文件时需要注意些什么?防止文件在修复的过程中出现其他的错误。 dinput8.dll是DirectInput库…

部署ELK

一、elasticsearch #拉取镜像 docker pull elasticsearch:7.12.1 #创建ELK docker网络 docker network create elk #启动ELK docker run -d --name es --net elk -P -e "discovery.typesingle-node" elasticsearch:7.12.1 #拷贝配置文件 docker cp es:/usr/share/el…

Visual Studio Code 常用快捷键大全

Visual Studio Code 常用快捷键大全 快捷键是编码过程中经常使用,且能够极大提升效率的部分,这里给大家介绍一些VS Code中非常有用的快捷键。 打开和关闭侧边栏 Mac — Command B Windows — Ctrl B Ubuntu — Ctrl B 选择单词 Mac — Command D …

“第六十天”

SRAM和DRAM: DRAM:动态RAM(随机存期存储器),是使用栅极电容存储信息的; SRAM:静态RAM,是使用双稳态触发器存储信息的。 重点在于DRAM由于要通过电容放电来表示信息,所…

逆袭Flutter? Facebook 发布全新跨平台引擎 Hermes!

Facebook 于前日发布了新的 JavaScript 引擎:Hermes,专注于提高 React Native 应用的性能,并且在市面上那些内存较少、存储速度较慢且计算能力低下的移动设备上都有良好的表现。但是不是为了追赶Flutter?这块作者没有说明。 移动应…

【JMeter】插件管理工具

1. 官方下载地址 Documentation :: JMeter-Plugins.org 2.安装 将该插件的jar包移动到lib/ext下 3.重启JMeter就可以看到插件管理器 4. 安装,更新,删除插件 安装插件 删除插件 更新插件

深入理解WPF中的依赖注入和控制反转

在WPF开发中,依赖注入(Dependency Injection)和控制反转(Inversion of Control)是程序解耦的关键,在当今软件工程中占有举足轻重的地位,两者之间有着密不可分的联系。今天就以一个简单的小例子&…

防止重复提交请求

前景提要: ts 简易封装 axios,统一 API 实现在 config 中配置开关拦截器 axios 实现请求 loading 效果 用一个数组保存当前请求的 url,此时还未响应。如果再次发起同样请求,比对 url 发现已经存在数组中,则拦截请求&a…

Java 谈谈你对OOM的认识

文章目录 前言一、基础架构二、常见OOM1、栈内存溢出java.lang.StackOverflowError2、堆内存溢出java.lang.OutOfMemoryError:Java heap space3、GC回收时间过长java.lang.OutOfMemoryError: GC overhead limit exceeded4、NIO程序堆外内存溢出java.lang.OutOfMemor…

thinkphp漏洞复现

thinkphp漏洞复现 ThinkPHP 2.x 任意代码执行漏洞Thinkphp5 5.0.22/5.1.29 远程代码执行ThinkPHP5 5.0.23 远程代码执行ThinkPHP5 SQL Injection Vulnerability && Sensitive Information Disclosure VulnerabilityThinkPHP Lang Local File Inclusion ThinkPHP 2.x 任…

Vue 条件渲染 与 列表渲染

目录 一、条件渲染 1.简介 : 2.v-if实例 : 3.v-show实例 : 4.v-if与v-show的区别 : 二、列表渲染 1.基本用法 : 1.1 v-for遍历数组 1.2 v-for遍历对象 2.应用实例 : 一、条件渲染 1.简介 : (1) Vue提供了v-if 和 v-show条件指令来完成条件渲染/控制。 v-if指令用于条…

sql server数据库跟踪——SQL Server Profiler解析

工具: SQL Server Profiler这个工具是SQL Server数据库自带的语句执行跟踪工具,常使用于分析软件修改数据库时所执行的语句,适合用来研究软件运行数据库的原理。 打开方式: 本机安装了SQL server的话,都是自带的。直接…