冯诺依曼+OS+进程+进程状态

news2024/11/15 21:20:59

索引

  • 一.冯诺依曼理解
  • 二.OS+ 进程的初步认识
    • 1.什么是进程?
    • 2.如何查看进程
    • 3.父进程与子进程
    • 4.进程状态
      • 1.S阻塞态+R运行态
      • 2.D阻塞(不可中断)
      • 3.Z僵尸状态andX死亡状态
      • 4.孤儿进程
      • 5,进程死亡之后OS做了什么
      • 五.状态总结:

一.冯诺依曼理解

在这里插入图片描述
几乎所有的计算机都采用了冯诺依曼体系结构
该结构包括五个基本部件:运算器,控制器,存储器(这里理解成内存不完全正确),输入输出设备

运算器:算术和逻辑运算
控制器:控制程序的执行流程,协调外设,什么时候将数据加载到内存,加载多少,什么时候将内存输出到外设
存储器也就是内存的作用下面详谈

存储器(内存)是什么?:
由于外设的速度非常慢,CPU的速度非常快,存储器的速度介于二者之间,当CPU需要直接进行计算时,存储器提前将数据加载到内存,数据输出时,CPU也直接将数据加载到存储器,再有存储器定期输出至输出设备上。正是有了存储器的存在,才过度平衡了CPU和外设速度不均衡的现状。
为什么要有存储器(内存)的存在?
从技术角度看的话
cpu>寄存器》L1~L3Cache>内存>外设(磁盘)>光盘磁带
成本角度:
寄存器>内存>磁盘(外设)
综上考虑:
内存在我看来就是体系结构一个大缓存,适配外设和CPU速度不均的问题
理解几个问题:
写好的程序编译完成后,在运行之前必须先加载到内存,为什么要这样做?
因为程序编译好之后,他就是磁盘上的一个文件,代码是在磁盘上的,但是cpu计算只和存储器打交道,所以编译好程序之后需要运行的话必须先加载到内存上
OS是如何加载数据的,万一位置的数据加载错了呢?如何保证数据加载到内存就会被立刻使用?
因为计算机在设计优化中有一个基本原则:局部性原理
假设我们读取的是第10行的代码,OS默认我们前后几十行的代码也会被读取,此时加载到内存即可
模拟微信发一条信息?
数据从键盘输入,先加载到内存,再由内存加载到CPU,CPU将各种信息打包,其中一份显示到自身的显示器,另一份传输到存储器,再由存储器发送到网卡,然后网卡通过网线输出到对方的网卡,对方接受到之后,也是由网卡传输到存储器然后由存储器发送到CPU,CPU进行各种解包,然后传输到存储器,再由存储器显示到显示器

二.OS+ 进程的初步认识

OS是一种系统软件,是一种搞管理的软件,可以管理软硬件资源
如何管理?
管理的本质:不是对被管理对象直接进行管理,而是只要拿到被管理对象的相关数据,我们直接对数据管理,就可以达到对对象管理。
所以管理的核心就是:先描述,再组织!!
开发阶段:OS对外表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分接口叫做系统调用

1.什么是进程?

什么是进程?
指正在运行的程序实例,是系统资源分配的基本单位,也是OS中进行任务调度和管理的基本单位。
如何管理进程?
进程本质上是一个程序,是文件,是在磁盘上,OS中可能同时有大量的进程,所以需要将进程管理起来,而管理的本质就是先描述再组织,所以Linux一定对进程用一个很大很大的结构体将进程给描述起来了,这个很大的结构体称为进程控制块PCB,无论是何种操作系统,对进程都有各自的结构体描述进程,Linux操作系统下的PCB是tack_struct

下面是Linux源码中task_struct结构展示
在这里插入图片描述
有了这个结构,可以在大体上想象出OS是如何管理进程,多个进程的管理就是将多个进程的task_struct用链表连接起来,此时就是对链表这个数据结构做管理了。
所以最后理解进程是什么?
进程 = 可执行程序 + 该进程对应的内核数据结构

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

2.如何查看进程

 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6 
  7 while(1)
  8 {
  9 
 10   printf("I am a process!,pid: %d ,ppid:%d\n",getpid(),getppi    d());
 11   sleep(1);
 12                                                              
 13 }
 14 
 15   return 0;
 16 }
 17 

查看进程的第一种方式
在这里插入图片描述
我们自己写的代码编译成可执行程序启动之后是一个进程,别人写的类似于Linux指令他们也是进程
在这里插入图片描述
Linux自带的命令在usr/bin目录底下,自带的命令启动后也是一个进程
在这里插入图片描述

理解当前路径:当前路径就是进程所在路径,进程会自己维护,并不是源代码所在路径

3.父进程与子进程

在这里插入图片描述
观察上述运行现象可以发现,每一次子进程的pid都会发生变化,但是ppid也就是父进程id不会发生改变,为什么呢?

几乎我们在命令行上所执行的所有指令(cmd),都是bash进程的子进程,除bash创建子进程外,我们自己还可以用代码创建子进程:fork()

fork()函数创建一个子进程
该函数有两个返回值,父进程返回子进程的pid,子进程返回0,根据返回值判断父子进程,问为什么(篇幅下面解答)?
且fork之后,父子进程会共享代码,一般会同时执行后续的代码,但根据fork之后的返回值不同条件让父子进程执行不同代码

#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6 
  7 while(1)
  8 {
  9    pid_t id = fork();
 10    //id:0 子进程, >0 :父进程
 11    if(id == 0)
 12    {
 13      //child
 14      while(1)
 15      {
 16        printf("我是子进程,我的pid :%d,我的父进程是:%d\n",getpid(),getppid());
 17       sleep(1);
 18      }
 19    }
 20    else 
 21    {                                                                                                                              
 22      //parent
 23      while(1)
 24      {
 25        printf("我是子进程,我的pid :%d,我的父进程是:%d\n",getpid(),getppid());
 26       sleep(1);
  }
 19    }
 20    else 
 21    {
 22      //parent
 23      while(1)
 24      {                                                                                                                            
 25        printf("我是子进程,我的pid :%d,我的父进程是:%d\n",getpid(),getppid());
 26       sleep(1);
 27      }
 28    }
 29  /* printf("I am a process!,pid: %d ,ppid:%d\n",getpid(),getppid());
 30   sleep(1);*/ 
 31 
 32 }
 33 
 34   return 0;
 35 }


在这里插入图片描述
问:为什么给父进程返回子进程的pid,给子进程返回0?
因为父亲:儿子 = 1:n(n>=1)
父进程必须要有表示子进程的方案,因为父进程要能够控制子进程的退出,fork之后,给父进程返回子进程的pid,而子进程最重要的是知道自己被创建成功了,因为子进程找父进程的成本非常低,只需要getppid()就可以了
如何理解进程被运行?
进程被运行,就是OS将进程的进程控制块放到cpu调度器中等待调用,说到进程其实就是与task_struct有关。

4.进程状态

谈到进程状态,对于整体操作系统
在这里插入图片描述
大致有很多,但是学不清楚,下面针对Linux操作系统针对性学习状态
主要讲的是Linux下进程状态,其他操作系统类比即可
kernel源码状态定义

static const char * const task_state_array[] = {
"R (running)", /* 0 */[重点]
"S (sleeping)", /* 1 */[重点]
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */[重点]
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */[重点]
};

Linux操作系统进程状态分类
进程状态:
R:运行状态
S:睡眠状态
D:磁盘休眠状态
T:停止状态
X:死亡状态
Z:僵尸状态

在Linux下
R运行态: ,表示进程已经准备好了,随时可以调度!
T终止状态,该进程还在,只不过永远不运行罢了,随时等待释放问题:进程都终止了,为什么不立马释放对应的资源呢?而是维护一个终止态,维护资源也是要耗费资源的 释放是要花时间的,如果OS很忙,此时就没时间去释放你,只要终止的进程发出一个信号告诉操作系统不要再调度我了。

1.S阻塞态+R运行态

一个进程,使用资源的时候,可不仅仅是在CPU中申请资源的,进程可能申请更多的其他资源:如磁盘网卡,显卡,声卡等
在这里插入图片描述
进程被调度的时候,就是根据优先级排队形成队列的过程,只是进程被调度申请的时候CPU资源,同理,我们申请其他慢设备的资源也是需要排队的,每个慢设备自身都维护了一个运行队列,当进程访问某些资源(磁盘网卡),该资源如果暂时没有准备好,或者正在给其他进程提供服务此时

  • 1 当前进程需要从runqueue中移除
  • 2 将当前进程放入对应慢设备的描述结构体中的等待队列,当该资源准备就绪的时候,才会被重新放入runqueue中

当我们的进程此时在等待外部资源的时候,该进程的代码不会被执行,此时就表示成进程卡主了,也就是进程阻塞

while(1)
 27   {
 28     cout<<"i am a process: %d"<<getpid()<<endl;
 29     sleep(1);                                                                                                                     
 30   }

在这里插入图片描述
此时查看进程的状态显示是S,也就是阻塞状态,因为这个程序90%的情况都在等,因为显示器的外设太慢了,等显示器就绪,所以这个进程的状态处于S

while(1)
 27   {
 28    // cout<<"i am a process: %d"<<getpid()<<endl;
 29    // sleep(1);                                              
 30   }

在这里插入图片描述
此时这个进程不访问任何外设也就不会有任何等待,此时进程的PCB就是在等待队列移来移去,此时的进程处于一种r运行状态
S状态时,等待的资源不就绪,操作系统唤醒她,由s–>R是一种前度睡眠,可以被OS随时唤醒,我们自己也可随时中断

2.D阻塞(不可中断)

服务器压力过大,OS是会终止用户进程的
在这里插入图片描述

D状态也叫做深度睡眠,不可被中断睡眠,OS无法杀掉进程,只能等D状态睡眠自己醒过来,也就是等磁盘读写完毕给出回应,D状态也就变成了R状态,此时kill -9无法杀死

3.Z僵尸状态andX死亡状态

Linux中一个进程退出的时候,一般不会直接进入X(死亡状态)而是进入Z(僵尸状态),因为进程被创造出来的时候一定是为了完成一个任务的,当进程退出的时候,我们无法知道进程是否完成任务了,一般要将进程的执行结果告知给父进程,所以进程退出的时候维持一个Z状态,为了维护进程的退出信息,可以放父进程或者OS系统读取,信息的读取是通过进程等待来读取的。
现在模拟一个僵尸进程
如果创建子进程,子进程退出了,父进程不退出,也不等待子进程,子进程的状态就会变成僵尸进程

using namespace std; 
  5 int main()
  6 {
  7   pid_t id = fork();
  8   if(id == 0)
  9   {
 10     //child
 11     int cnt = 5;
 12     while(cnt)
 13     {
 14       cout<<"我是子进程,我还剩下:"<<cnt--<<"秒"<<endl;
 15       sleep(1);                                              
 16     }
 17       cout<<"我是子进程,我已经僵尸了,等待被检测"<<endl;
 18       exit(0);
 19   }
 20   else
 21   {
 22 
 23      while(1)
 24      {
 25        cout<<"我是父进程,我永不退出"<<endl;
 26        sleep(1);
 27      }
 28 
 29   }

在这里插入图片描述
问:长时间僵尸进程会有什么问题?
如果没有人回收子进程的僵尸,该状态会一直维持,维护状态本身也是需要数据维护的,也是属于进程的基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB就需要被维护,因此,如果一个父进程创建了很多子进程,一直不回收的话,就造成了会有内存资源的浪费也就是内存泄漏,所以如何避免呢?(后面说,涉及到进程等待和信号)

4.孤儿进程

如果父进程先退出了,子进程没有退出,此时子进程就会变成孤儿进程,一般情况下被操作系统进程init接管并回收其资源,如果系统进程init也无法回收孤儿进程资源,那么该孤儿进程就会一直存在,直到系统重启。

5,进程死亡之后OS做了什么

操作系统会维护进程资源的释放和回收,并向进程的父进程发送SIGCHLD信号通知其子进程已经死亡,如果父进程没有及时处理信号,则操作系统会维护进程的状态为僵尸进程,直到父进程回收其进程

五.状态总结:

Linux中的状态对应操作系统中的状态

在这里插入图片描述

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

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

相关文章

数据库系统工程师 —— 第六章 数据库技术基础

文章目录 &#x1f4c2; 第六章、数据库技术基础 &#x1f4c1; 6.1 基本概念 &#x1f4d6; 6.1.1 数据库与数据库管理系统 &#x1f4d6; 6.1.2 数据库技术的发展 &#x1f4d6; 6.1.3 DBMS的功能和特点 &#x1f4d6; 6.1.4 数据库系统的体系结构 &#x1f4d6; 6.1.5 数据库…

极致鸿蒙——华为MatePad系列安装AidLux,一个自带vscode的Python编译环境

看着刚刚人入手的华为鸿蒙系统MatePad11平板&#xff0c;是如此的美轮美奂&#xff0c;但是总感觉少了点什么&#xff0c;少了点什么呢&#xff1f;是编程环境&#xff0c;我爱MatePad&#xff0c;也爱编程&#xff0c;那如果可以在MatePad上编程&#xff0c;会发生什么&#x…

Ae:3D 变换小工具与 3D 轴模式

◆ ◆ ◆ 3D 变换小工具 3D 变换小工具 3D Gizmo是用不同颜色标志的直观的调整工具&#xff0c;可用来缩放、定位和旋转 3D 图层、摄像机图层和灯光图层。 如上图所示&#xff0c;不同的颜色表示不同的轴。红色表示 X 轴&#xff0c;绿色表示 Y 轴&#xff0c;蓝色表示 Z 轴。…

有趣的 Kotlin 0x15:data object

简介 Kotlin 早在 1.7.20版本就引入了一种新的对象声明类型&#xff1a;data object&#xff0c;但是处于Experimental 阶段 。data object 与常规object 在概念上表现一致&#xff0c;但带有开箱即用且语义清晰的 toString 函数。而在 1.8.20 版本&#xff0c;data class 的语…

webstorm 创建harthat项目

Getting started with Hardhat | Ethereum development environment for professionals by Nomic FoundationGetting started with Hardhathttps://hardhat.org/hardhat-runner/docs/getting-started#quick-start安装环境 npm install --save-dev hardhat 创建项目 npx hard…

基数树RadixTree

转自&#xff1a;基数树RadixTree - 知乎 1. 基数树概述 对于长整型数据的映射&#xff0c;如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题。radix树就是针对这种稀疏的长整型数据查找&#xff0c;能快速且节省空间地完成映射。借助于Radix树&#xff0c;我们可以实现…

IntelliJ IDEA Run时报“无效的源发行版:16“错误

在新建Java项目时&#xff0c;run运行main方法时&#xff0c;报错 “java: 错误: 无效的源发行版&#xff1a;16”&#xff0c;了解一番后原来自己创建项目时&#xff0c;Project language level 没有和Project SDK版本相匹配。 还原创建项目步骤&#xff1a; 一、创建项目 …

Python语音增强

img { margin: auto; display: block } 简介 音频时域波形具有以下特征&#xff1a;音调&#xff0c;响度&#xff0c;质量。我们在进行数据增强时&#xff0c;最好只做一些小改动&#xff0c;使得增强数据和源数据存在较小差异即可&#xff0c;切记不能改变原有数据的结构&…

3.0 响应式系统的设计与实现

1、Proxy代理对象 Proxy用于对一个普通对象代理&#xff0c;实现对象的拦截和自定义&#xff0c;如拦截其赋值、枚举、函数调用等。里面包含了很多组捕获器&#xff08;trap&#xff09;&#xff0c;在代理对象执行相应的操作时捕获&#xff0c;然后在内部实现自定义。 const…

将PDF文件转换为JPG格式图片的3种简单方法

如何在线将PDF文件转换成图片格式&#xff1f;如果您在使用PDF文件时只需要其中一页或几页的内容&#xff0c;将PDF转换为图片可以使您更方便地使用这些内容。下面介绍三种简单易用的PDF转图片的方法。 方法一&#xff1a;记灵在线工具 记灵在线工具是一个免费的在线PDF转换工…

方太也造车?

听说方太也造车了&#xff1f; 造车闹剧层出不穷 近年来&#xff0c;随着智能汽车概念的风行&#xff0c;各大品牌也掀起了一股造车的热潮。一时间&#xff0c;互联网、房地产、家电、手机……各行各业的企业都纷纷粉墨登场&#xff0c;各种造车闹剧层出不穷。 然而很快人们就发…

【三十天精通Vue 3】第二十七天 如何用Vue 3和TensorFlow.js实现人脸识别Web应用?

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、项目简介1.1 概述1.2 功能特点1.3 技术栈二、准备工作2.1 环境搭建2.2 项目初始化2.3 引入依赖

Bus动态刷新

Bus动态刷新全局广播配置实现 启动 EurekaMain7001ConfigcenterMain3344ConfigclientMain3355ConfigclicntMain3366 运维工程师 修改Gitee上配置文件内容&#xff0c;增加版本号发送POST请求curl -X POST "http://localhost:3344/actuator/bus-refresh" —次发送…

【C++进阶之路】第二篇:多态 抽象类 单继承和多继承关系中的虚函数表

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;多态的概念&#xff0c;多态的构成条件&#xff0c;虚函数重写&#xff0c;C11final和overrid&#xff0c;重…

谈谈我对Edge浏览器分屏功能的使用感受

谈谈我对Edge浏览器分屏功能的使用感受 前言 最近&#xff0c;微软为 Microsoft Edge 浏览器的稳定版本带来了分屏浏览 (Split Screen) 这个新玩意儿&#xff0c;这个功能允许用户在同一个页面以左右视图的形式并排打开两个标签页&#xff0c;类似于软件的分屏。 各位看官如果想…

将经纬度坐标在ArcGIS软件中生成系列矢量数据

目录 环境介绍&#xff1a; 操作内容&#xff1a; 操作步骤&#xff1a; 1、将经纬度坐标值编辑在excel中&#xff0c;注意x、y对应的分别是经度和纬度 2、打开ArcMap软件&#xff0c;加载.xls数据 3、需要选择地理坐标系 4、点矢量数据生成 5、线矢量数据生成 6、面矢量…

2.1 Linux命令行

系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…

Linux多路IO复用:select

1. 多路IO复用 内核监听多个socket文件描述符读写缓冲区属性的变化&#xff0c;若某个文件描述符的读缓冲区有变化&#xff0c;则将该事件告诉应用层。 内核提供多路IO复用的API&#xff1a;select、poll&#xff08;使用较少&#xff09;、epoll。 2. select select原理 用…

设置让Windows每天在指定时间自动关机

其实我们的电脑是可以设置每天在指定的时间点自动关机的&#xff0c;具体操作方法&#xff1a; 1、开打电脑&#xff0c;点击电脑系统左下角windows图标&#xff0c;选择“控制面板”并进入&#xff1b;如图 2、在控制面板界面找到“管理工具”&#xff0c;点击开打&#xff1b…

idea2021.3.x激活教程

第一步: 下载最新的 IDEA 2021.3.3 版本安装包 先从 IDEA 官网下载 IDEA 2021.3.3 版本的安装包&#xff0c;下载链接可以自行百度IDEA官网。 点击下载&#xff0c;耐心等待下载完成。 第二步: 开始安装(已安装可跳过此步骤) 指定安装目录。 勾选创建桌面快捷方式&#xff0…