进程概念[上]

news2024/10/2 18:14:55

一、冯诺依曼体系结构

冯 • 诺依曼体系结构核心原理为:用户输入的数据先放到内存当中,CPU 读取数据的时候就直接从内存当中读取,CPU 处理完数据后又写回内存当中,然后内存再将数据输出到输出设备当中,最后由输出设备进行输出显示。 

参考来自:冯诺依曼体系结构-CSDN博客

0x01 计算机组成

1.输入设备: 键盘,磁盘,网卡,显卡,话筒,摄像头等
2.输出设备: 显示器,磁盘,网卡,显卡,音响等
3.存储器(内存)
4.运算器&&控制器(cpu)

 0x02 存储器分级结构

二、 操作系统

0x01 什么叫操作系统?

操作系统是一款专门针对软硬件资源进行管理工作的软件
操作系统对下管理好软硬件资源
对上为普通用户提供良好的运行环境,为程序员提供各种基本功能

此时就会出现一个问题:操作系统如何提供各种基本功能呢?

因为操作系统不相信任何用户,所以会采用系统调用接口去完成各种基本功能的调用

0x02 操作系统的作用是什么?

以管理好软硬件资源的方式,给用户提供稳定的,高效的,安全的运行环境

0x03 如何进行管理?

先描述被管理对象,再把多个管理对象之间产生联系,使用特性的数据结构组织起来 --- 先描述,再组织(可以将对目标的管理转化成对数据的管理)
比如从校长的角度,校长想要给一个学习成绩好的学生奖励,但是有一个学校有很多的学生,那么校长如何进行管理呢?此时就可以将每一个学生的数据聚合起来,形成学生的属性,然后再通过数据结构,将多个学生的聚合数据之间产生关联,这就叫先描述,再组织

三、进程

0x01 初看什么叫做进程?

初步来说进程是加载到内存的程序

0x02 那么如何管理进程呢?

当然也是先描述,再组织,任何进程在形成之时,操作系统要为该进程创建PCB --- 进程控制块

0x03 为什么要有PCB?

因为管理进程的方式是先描述再组织,要描述进程,那么就需要使用结构体来描述进程的相关属性

0x04 什么叫做PCB?

PCB: 一个结构体类型,在Linux系统中,PCB具体就是
struct task_struct
{
        //进程的所有的属性
}

0x05  如何看见进程

①运行程序后

PID:进程号,当程序运行时就会有当前进程的进程号

②结束程序后

CTRL+C后,就结束了进程

提示:
ps axj : 查看所有进程
head -1: 只显示结果的第一行,即每一列的列名
曾经我们所有的启动程序的过程,本质上都是再系统上面创建进程

0x06  再看进程

 进程加载到内存中,有了进程控制块,那么所有进程管理任务与进程对应的程序毫无关系,与进程对应的内核创建的的该进程的PCB强相关,就相当于当你面试的时候,面试官不是看你长的有多帅,有多美,而是看所收集到的数据来进行筛选,所以你是否能进面,就与这些数据强相关

 0x07 如何获取PID?

 ①getpid()

头文件:

#include<sys/types.h>
#include<unistd.h>
介绍:
PID是task_struct的内容之一,是描述本进程的唯一表示符,用来区别其他进程

 ②获取PID

#include<stdio.h>    
#include<sys/types.h>    
#include<unistd.h>    
int main()    
{    
  while(1)    
  {    
    printf("pid: %d\n",getpid());        
    sleep(1);                                                                                                                                                                                                    
  }    
  return 0;    
}

 

③关闭进程的俩个方式

(1) CTRL + C
(2) kill + 9 进程号

0X08 如何获取PPID?

①获取PPID

#include<stdio.h>    
#include<sys/types.h>    
#include<unistd.h>    
int main()    
{    
  while(1)    
  {    
    printf("getppid: %d\n",getppid());                                                 
    sleep(1);    
  }    
  return 0;    
}  


 0x09 状态

①退出码&退出信号

0x10 上下文

① 上下文数据

进程执行时处理器的寄存器中的数据

② 进程切换

①CPU中存放着寻多寄存器,寄存器中保存着当前正在运行的程序的临时数据
②运行队列run_queue中的每一个结点都是一个task_struct ,通过指针找到相应的代码和数据
③每次有结点是运行状态的时候就可以加载到CPU中进行运行,但是进程的代码可能不是很短时间就能运行完成
④可以假设,规定每个进程单词运行的时间片是5ms,那么第一个进程在CPU中运行5ms之后,就得从CPU中拿出,再去运行队列之后进行重新排队,重新进行运行
⑤所以再单CPU的情况下,用户感受到的多个进程同时在运行,本质是通过CPU的快速切换完成的

从上述可以得出一个结论:

进程在运行期间是有切换的,进程可能存在大量的临时数据,而这些临时数据是在CPU的寄存器中保存

但是又会得出一个疑惑点:

CPU里面的寄存器只有一套

 这时就要提到保护上下文和恢复上下文的操作了:

当一个task_struct结点在CPU运行之后,那么此时它要重新去排队了,那么此时CPU寄存器中所保存的临时数据就会被保存到task_struct中,这就是保护上下文
而当这个task_struct结点又到它运行到CPU中时,那么之前保存的数据又会被重新加载到CPU的寄存器当中继续使用,这就叫恢复上下文
可以更通俗的讲就是:让你去做其他的事情,但是又不耽误现在要做的事情,当你要回来继续做这件事时,可以继续做这件事情

从上述可知,通过上下文,我们能感受到进程是被切换的

 四、查看进程

0x01 通过/proc系统文件夹查进程信息

 进程启动之后会在/proc目录下形成目录,以自身的PID号作为目录文件名,形成对应文件夹,当这个对应的进程退出时,这个文件夹就会消失

 0x02 查看当前进程所对应的属性

 0x03 查看当前正在执行的程序

提示:

cwd:表示当前工作目录,当执行命令或打开文件时所参考的相对路径
exe:表示我们当前正在执行的程序

五、创建子进程

0x01 创建第一个子进程

#include<stdio.h>    
#include<sys/types.h>    
#include<unistd.h>    
int main()    
{    
   int ret = fork();    
    
   if(ret > 0)    
   {    
      printf("hello \n");    
   }    
   else    
   {    
      printf("world\n");                                                               
   }    
    
  return 0;    
} 

从之前所学中我们可以猜想,执行的结果必然是if和else中的一个,但是结果真的是这样吗?

从结果中可以看出,竟然是if和else都执行了,这是为什么呢?

这是因为创建了子进程

从上面的代码中我们可能还有些疑惑,这到底是什么意思,那么我们再来看个代码:

  #include<stdio.h>    
  #include<sys/types.h>    
  #include<unistd.h>    
  int main()    
  {    
    int ret = fork();    
      
    while(1)                                                                           
    {    
      printf("PID:%d,PPID:%d\n",getpid(),getppid());    
      sleep(1);    
    }    
    return 0;    
  }  

 从上述代码和结果中我们又可以看出,俩个进程的PID号竟然是不一样的,因为一个是父进程,另一个是子进程

0x02 理解fork()创建子进程

①创建的子进程与在操作系统角度创建进程的方式是没有任何差别的,也是系统里多了一个进程,即多了一份与进程相关的内核数据结构task_struct和数据代码,但是此处的数据代码会继承父进程的代码数据,
②内核数据结构task_struct也会以父进程为模板,初始化子进程的task_struct

③fork()之后,子进程和父进程代码是共享的,但代码只有一份,是不可以被修改的
④数据其实也是共享的,但这要考虑到修改的情况

0x03 写时拷贝

在 Linux 中,调用 fork()创建子进程时,只是读取的时候共享一份,当需要修改的时候,并不会将父进程的所有数据复制,而是会找一块空间,将父进程该页数据复制一份给子进程 ,以此来保证进程之间的独立性
参考:【Linux】写时复制(CopyOnWrite)|写时拷贝|rcu_bandaoyu的博客-CSDN博客

 0x04 fork()返回值

我们创建子进程,就是为了和父进程干不一样的事情,那么这就需要fork()的返回值来完成
创建子进程失败:    <0

创建子进程成功:     给父进程返回子进程的PID, 给子进程返回0

0x05 父子进程可以做不同的事情

#include<iostream>                                                                     
#include<unistd.h>

int main()
{
  pid_t id = fork();
  if(id > 0)
  {
    while(true)
    {
      std::cout << "parent:" << getpid() << "  "<< getppid() << std::endl;
      sleep(2);
    }
  }
  else if(id == 0)
  {
    while(true)
    {
       std::cout << "child:" << getpid() << "  "<< getppid() << std::endl;
       sleep(2);
    }
  }
  else
  {
    //如果进程创建失败,什么也不做  
  }

  return 0;
}           

 此时,我们会有一个问题,fork()之后,父子进程谁先运行?

这个是不确定的,这是有调度器所决定的

六、 进程的状态信息

0x01 进程的状态信息在哪里呢?

在task_struct中

0x02 进程状态的意义

方便操作系统快速判断进程,完成特定的功能,比如调度,调度本质上也是一种分类

 0x03 运行状态(R状态)

运行状态并不意味着进程一定在运行中,表明进程要么是在运行中,要么是在运行队列中,即当前进程已经被放在了运行队列当中,随时等待CPU进行调度

#include<iostream>    
#include<unistd.h>    
    
int main()    
{    
  while(true); //没有等待外设,只是排队CPU资源,比较快,所以一直处于运行状态                                                                        
  return 0;    
}  

提示:

R+:"+"表示在前台运行,ctrl +c进行停止
没有"+"则处于后台运行: 如果想要后台运行进程,则./test &,ctrl +c是停止不了的,只有通过kill + 9 + 进程号停止

0x04  睡眠状态&磁盘休眠状态(S状态&D状态)

当完成某种任务的时候,任务条件不具备,需要进程进行某种等待,也就是当进程等待外部设备条件时,就会放入等待队列,这时的状态就是S状态或者D状态

 S睡眠状态: 意味着进程在等待时间完成,可以被操作系统消除,也可以叫做可中断睡眠状态

#include<iostream>    
#include<unistd.h>    
    
int main()    
{    
  while(true)    
  {    
    std::cout << "hello world" << std::endl;                                           
  }    
  return 0;    
}   


为什么代码一直在运行,确实S状态呢?

因为正在打印到显示器上,外设的速度是比较慢的,等待外设就需要花费时间的,只是看起来比较快,其实进程一直是在处于休眠状态

 D磁盘休眠状态: 这个状态的进程通常会等待IO结束,即当进程在等磁盘处理数据并返回,但是此时进程什么事也没做,此时操作系统想要消除这个进程,但是如果消除了这个进程,那么磁盘处理好数据后那返回给谁呢?,所以这个进程不能被消除,所以D状态也可以叫做不可中断睡眠状态 

 0x05 挂起状态&唤醒进程

我们把从运行状态的task_struct(run_queue),放到等待队列,就叫挂起状态(阻塞)
从等待队列,放到运行队列,被CPU调度就叫做唤醒进程

提示:
①进程在运行的时候,有可能因为运行的需要,可能会在不同的队列里
②在不同的队列里,所处的状态也可能是不一样的

 0x06 停止状态(T状态)

可以通过发送 SIGSTOP 信号给进程来停止( T )进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。

提示:
①kill -l :列出所有可用信号
②查看正在运行的进程的PID
③kill -信号编码 进程号
④进行查看是否处于T状态

0x07 死亡状态(X状态)

这个状态只是一个返回状态,你不会在任务列表里看到这个状态

回收进程资源 = 进程相关的数据结构 + 代码和数据

0x08 僵尸状态(Z状态)

僵尸状态是为了辨别退出死亡的原因,而这些原因也是数据,保存在task_struct中,一个进程退出并不是直接进入死亡状态,而是先进入僵尸状态,再进入死亡状态

#include<iostream>    
#include<unistd.h>    
using namespace std;    
int main()    
{    
  pid_t id = fork();    
  if(id == 0)    
  {    
    while(true)    
    {    
      cout << " I am child,running\n" << endl;    
      sleep(2);    
    }    
  }    
  else    
  {    
    cout << "parent do nothing\n" << endl;    
    sleep(50);                                                                                                   
  }    
    
  return 0;    
}  

 进行监控进程:

while :; do ps axj | head -1 && ps axj | grep test | grep -v grep; sleep 1;echo "###################" done;

 当进程正在运行时,父进程一直处于运行状态,但是此时子进程被干掉,但是没有得到父进程的回收,此时子进程所处的状态就是僵尸状态

 0x09 孤儿进程

当父进程被干掉,但子进程还在运行,此时的子进程就叫做孤儿进程,孤儿进程的父进程会变成操作系统

#include<iostream> 
#include<unistd.h>    
#include<stdlib.h>
using namespace std;
int main()
{
  pid_t id = fork();
  if(id == 0)
  {
    while(true)
    {
      cout << " I am child,running\n" << endl;
      sleep(2);
    }
  }
  else
  {
    cout << "parent do nothing\n" << endl;
    sleep(10);
    exit(1);
  }

  return 0;                                                                                                      
}

 

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

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

相关文章

【已解决】HTTP method names must be tokens

该接口应该是http&#xff0c;但是在平台中的填写成https&#xff0c;导致的问题&#xff0c;所以将对应的接口修改为http即可

C#面对对象(英雄联盟人物管理系统)

目录 英雄信息类 因为要在两个窗体里面调用字典&#xff0c;所以要写两个类来构建全局变量 添加功能 查询功能 英雄信息类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp…

2023-10-13 LeetCode每日一题(避免洪水泛滥)

2023-10-13每日一题 一、题目编号 1488. 避免洪水泛滥二、题目链接 点击跳转到题目位置 三、题目描述 你的国家有无数个湖泊&#xff0c;所有湖泊一开始都是空的。当第 n 个湖泊下雨前是空的&#xff0c;那么它就会装满水。如果第 n 个湖泊下雨前是 满的 &#xff0c;这个…

《Unity Shader入门精要》笔记08

文章目录 Unity的渲染路径前向渲染路径前向渲染路径原理Unity中的前向渲染BassPassAdditional Pass 内置的光照变量和函数 延迟渲染路径延迟渲染的原理Unity中的延迟渲染可访问的内置变量和函数 Unity的光源类型光源类型有什么影响平行光点光源聚光灯 在前向渲染中处理不同的光…

Linux友人帐之系统管理与虚拟机相关

一、虚拟机相关操作 1.1虚拟机克隆 虚拟机克隆是指将一个已经安装好的虚拟机复制出一个或多个完全相同的副本&#xff0c;包括虚拟机的配置、操作系统、应用程序等&#xff0c;从而节省安装和配置的时间和资源。 虚拟机克隆的主要用途有&#xff1a; 创建多个相同或相似的虚拟…

使用Python实现网页中图片的批量下载和水印添加保存

数字时代&#xff0c;图片已经成为我们生活中的一部分。无论是社交媒体上的照片&#xff0c;还是网页中的图片元素&#xff0c;我们都希望能够方便地下载并进行个性化的处理。 假设你是一位设计师&#xff0c;你经常需要从网页上下载大量的图片素材&#xff0c;并为这些图片添加…

深入了解基数排序:原理、性能分析与 Java 实现

基数排序&#xff08;Radix Sort&#xff09;是一种非比较性排序算法&#xff0c;它根据元素的每个位上的值来进行排序。基数排序适用于整数或字符串等数据类型的排序。本文将详细介绍基数排序的原理、性能分析及java实现。 基数排序原理 基数排序的基本原理是按照低位先排序&…

如何解决找不到msvcr100.dll问题,msvcr100.dll丢失的多种修复方案

当我的电脑出现MSVCR100.DLL丢失这个问题时&#xff0c;我感到非常困扰。我试图通过重新安装Visual C 2010 Redistributable Package来解决这个问题&#xff0c;但是这个方法并不总是有效。有些时候&#xff0c;即使我重新安装了整个软件包&#xff0c;MSVCR100.DLL文件仍然找不…

政策加码聚焦工业现代化发展,团队聚能驱动AI机器视觉高质量发展

随着智能制造进程的持续推进&#xff0c;新一代信息技术引领着第四次工业革命&#xff0c;机器视觉技术乘着东风实现高速发展&#xff0c;其视觉创新应用产品全面铺开&#xff0c;新应用、新模式不断涌现。深眸科技紧抓时代发展机遇&#xff0c;基于领先的图像算法和自主研究的…

Windows下DataGrip连接Hive

DataGrip连接Hive 1. 启动Hadoop2. 启动hiveserver2服务3. 启动元数据服务4. 启动DG 1. 启动Hadoop 在控制台中输入start-all.cmd后&#xff0c;弹出下图4个终端&#xff08;注意终端的名字&#xff09;2. 启动hiveserver2服务 单独开一个窗口启动hiveserver2服务&#xff0c;…

clone()方法使用时遇到的问题解决方法(JAVA)

我们平时在自定义类型中使用这个方法时会连续遇到 4 个问题。 基础代码如下&#xff1a; class A {int[] a {1,2,3}; }public class Test {public static void main(String[] args) {} } 第一个&#xff1a; 当我们直接调用时报错原因是Object类中的clone方法是被protecte…

什么叫AI自动直播?

AI自动直播是一种使用人工智能技术进行自动直播的程序或系统。 它可以自动录制视频&#xff0c;并在直播平台上进行展示&#xff0c;以吸引观众并提高品牌知名度。AI自动直播通常需要使用特定的软件或平台来实现&#xff0c;并且需要具备一定的编程和人工智能知识。 AI自动直…

win10搭建gtest测试环境+vs2019

首先是下载gtest&#xff0c;这个我已经放在了博客上方资源绑定处&#xff0c;这个适用于win10vs版本&#xff0c;关于liunx版本的不能用这个。 或者百度网盘链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/15m62KAJ29vNe1mrmAcmehA 提取码&#xff1a;vfxz 下…

苹果CMS海螺模版V20修复版/加广告代码 ​适合视频影视类网站使用​

最新苹果CMS海螺模版V20修复版&#xff0c;增加广告代码&#xff0c;适合视频影视类网站使用&#xff0c;有兴趣的可以研究研究。 修复说明&#xff1a; 修复多线路时播放页列表点其他线路还是播放默认线路的问题 修复前台黑白切换和字体颜色切换失效 修复微信二维码没有对…

《进化优化》第4章 遗传算法的数学模型

文章目录 4.1 图式理论4.2 马尔可夫链4.3 进化算法的马尔可夫模型的符号4.4 遗传算法的马尔可夫模型4.4.1 选择4.4.2 变异4.4.3 交叉 4.5 遗传算法的动态系统模型4.5.1 选择4.5.2 变异4.5.3 交叉 4.1 图式理论 图式是描述一组个体的位模式&#xff0c;其中用*来表示不在乎的位…

基于PLC的机械手控制系统设计

目录 摘 要......................................................................................................................... 1 第一章 绪论.............................................................................................................…

什么是promise?如何使用?应用场景?

什么是Promise&#xff1f; Promise是一种用于处理异步操作的JavaScript编程模式。它允许你更优雅地处理异步代码&#xff0c;避免了回调地狱&#xff08;Callback Hell&#xff09;的问题&#xff0c;使代码更易于理解和维护。Promise是ES6&#xff08;ECMAScript 2015&#…

云表:MES系统是工业4.0数字化转型的核心

随着信息技术与工业技术的深度融合&#xff0c;网络、计算机技术、信息技术、软件与自动化技术相互交织&#xff0c;产生了全新的价值模式。在制造领域&#xff0c;这种资源、信息、物品和人相互关联的模式被德国人定义为“工业4.0”&#xff0c;也就是第四次工业革命。工业4.0…

力扣每日一题36:有效的数独

题目描述&#xff1a; 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考…

GEE:基于GLDAS数据集分析土壤湿度的时间序列变化

作者:CSDN @ _养乐多_ 本篇博客将介绍如何使用Google Earth Engine(GEE)进行土壤湿度数据的分析。我们将使用NASA GLDAS(Global Land Data Assimilation System)数据集,其中包括了关于土壤湿度的信息。通过该数据集,我们将了解土壤湿度在特定区域和时间段内的变化,并生…