【linux】:进程概念

news2024/9/22 19:44:02

 

 

文章目录

  • 冯诺依曼体系结构
  • 一:操作系统
  • 二:  进程
  • 总结

 


冯诺依曼体系结构

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。

冯诺依曼体系如下图:

7cf84eab1fc746adb53c6175fa2a21f6.png

那么输入设备有哪些呢?如键盘,鼠标,话筒,摄像头,磁盘等。

存储器就是我们经常说的内存了。

输出设备有网卡,声卡,音响等。

cpu含有运算器和控制器等。

那么为什么冯诺依曼要有内存呢?直接让输入设备连接cpu到输出设备不是更方便吗,大家看如果是下面这个体系怎么样?

743256ce086548b48f10b06dcb04e626.png

首先这样的体系是没问题的,可以直接让输入设备直接和cpu沟通,但问题在于cpu的运行速度非常快,而输入设备和输出设备都属于外设,外设一般都会比较慢,就比如磁盘和内存的比较,磁盘如果将数据存入会一直存在,而内存是一种掉电易失的介质如果你使用的电脑台式电脑突然停电关机了那么内存里的数据就没有了,但是相对于磁盘,内存的速度比较快。冯诺依曼体系之所以让外设与内存沟通是因为要防止木桶原理,cpu的算力太快了是外设远远比不上的,而有内存的存在就可以大大的缓解木桶原理带来的效率慢的问题。因为有了内存的存在,我们可以对数据进行预加载,CPU以后在进行数据计算的时候,根本就不需要访问外设了,而只要直接伸手向内存要就可以了。

结论一:在数据层面,一般CPU不和外设直接沟通,而是直接只和内存沟通。这也就回答了为什么我们的程序必须先被加载到内存中,因为这是体系结构决定的。

那么在硬件层面,单机和跨主机之间数据是如何流向的呢?看下图:

4ec1545f9b1b4728ac8ddc1f2ff35576.png

举个例子:比如我们用qq给别人发送消息,先从键盘输入要发送的消息,然后将数据经过内存被CPU运行后再回到内存然后将数据交给输出设备,这个时候给别人发消息的那个人的屏幕会先显示出发送的消息,然后经过网络等到接收消息的人的输入设备然后经过内存,cpu然后显示到对方的屏幕上。 


 

一、操作系统

操作系统是进行软硬件资源管理软件的。任何一个计算机系统都包含一个基本的程序集合,称为操作系统(OS),笼统的理解,操作系统包括:内核(进程管理,内存管理,文件管理,驱动管理),其他程序(例如函数库,shell程序等等)

那么如何理解操作系统对硬件做管理呢?我们举个例子:就比如学生,是谁在管理学生呢,当然是校长在管理学生了,校长主要是决策,辅导员主要是去执行校长做出的决策,而学生是参与执行的对象,在校长管理期间,校长只需要向各级领导发放指令管理学生,而不会直接和学生沟通管理。所以我们得出以下结论:1.管理者和被管理者其实是不需要直接沟通的。

2.管理的本质:对被管理的对象的数据进行管理

3.用什么管理呢?数据结构。

管理的本质就是先描述,在组织。就像各个不同的程序,先将这些程序描述为一个个的结构体,然后以链表的形式进行对单个节点的修改也就是管理。

而像我们刚刚举得学生的例子中,校长就是操作系统,辅导员就是硬件驱动,学生就是硬件或软件。

那么操作系统为什么对软硬件资源进行管理呢?操作系统对下通过管理好软硬件资源(手段),对上给用户提供良好(安全,稳定,高效,功能丰富)的执行环境(目的)。

那么操作系统是如何给用户提供良好的执行环境的呢?操作系统通过暴露出一些系统接口供用户操作使用,这里就好比银行一样,银行为人们服务是窗口式服务,像金库等一些重要的地方是不会对用户进行开放的,而开放的地方也会用窗口封装起来避免遭到破坏,所以操作系统是不会相信任何一个用户的,它只是暴露出一些可以供用户使用的接口去使用,同时还要保证操作系统内部的安全,所以这些接口是经过一层又一层的封装,而这些由操作系统提供的接口又被称为系统调用。

系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很利于更上层用户或者开发者进行二次开发。

二、进程

我们现在大多数人都接触过电脑,那么我们以windows为例,windows中的进程是什么样的呢,大家看下图:

3c41ec7b57d641a6b64b097e081e83c0.png

 因为windows是图形化操作的所以这些进程看起来非常生动形象。那么这些进程该如何去理解呢?

首先,我们以前的任何启动并运行程序的行为,都是由操作系统帮助我们将程序转化为进程完成特定的任务。

如下图:

87e683ec700e47baa6d6473871ab618f.png

首先我们要运行一个程序,这个程序保存在磁盘中,当双击运行就把这个程序的代码和数据加载到内存中,每加载一个程序的代码和数据操作系统都会将这个程序的代码和程序用pcb/task_struct保存起来,并且将这些程序的代码和数据连接起来像链表一样进行控制,用户想要优先使用哪个软件就将这个软件的pcb/task_struct加载到CPU中进行运行,所以对于进程的管理就转化为了对pcb/task_struck进行链表的增删查改。进程不是内存中的代码和数据,进程是代码和数据加该进程在内核中加载的pcb/task_struct合起来。

结论:进程 = 内核关于进程的相关数据结构 + 当前进程的代码和数据

描述进程-PCB:进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。课本上称之为PCB,linux操作系统下的PCB是task_struck

为什么要有pcb呢?我们前面说过操作系统管理的本质是先描述在组织,而进程的描述就是靠pcb。

task_struck内容分类

标识符:描述本进程的唯一标识符,用来区别其他进程。

状态:任务状态,退出代码,退出信号等

优先级:相对于其他进程的优先级

程序计数器:程序中即将被执行的下一条指令的地址

内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。

上下文数据:进程执行时处理器的寄存器中的数据

I/O状态信息:包括显示的I\O请求,分配给进程的I\O设备和被进程使用的文件列表。

记账信息:可能包括处理器的时间总和,使用的时钟数总和,时间限制,记账号等

其他信息。

下面我们在linux系统下演示进程的存在:

首先创建一个.c文件用来写一个死循环程序,这样方便我们看到进程:

30a751a0541c4af48b261293756a51d5.png

然后我们创建一个并写出一个一个简单的Makefile文件:

551b5d7594d44a3f8e959988606ced59.png 文件中冒号的左边依赖于冒号的右边,也就是说没有process依赖于myprocess.c,gcc - o中的$@符号是指冒号左边的文件,$^是指冒号右边的文件。

55987f4d764d4703b55a19da3563375d.png

 然后我们写了一个简单的死循环代码,现在开始运行。

5ad5055c509a477f8b779a49431be79d.png

现在这个可执行程序已经跑起来了,根据我们上面所讲的,先将代码和数据加载到内存,然后变成一个task_struct,这就变成一个进程了,那么怎么看到这个进程呢?先复制一个会话,在新会话中用ps axj命令可以查看所有的进程,然后我们利用管道来过滤只想看我的进程。

392d5350ad554e3da4d6b098922933d4.png

 然后我们再利用管道head -1查看第一行

a3281b20d29d4d7da795da041e1fb6a0.png

然后我们利用逻辑与拿到我们进程的信息:

a53902410dcf47df94de31ad5c3c2220.png 这个时候我们就拿到了进程的属性,最后一行的grep是什么呢?这是因为我们利用grep去过滤进程,而grep本身也是一个进程,所以进程中可以看到grep,那么如果我们不想看到grep该怎么操作呢?只需要在刚刚的命令下多加一个管道grep -v grep就过滤掉grep这个进程了。

028fb5b955714c1683653a93a81a9f9e.png

b71bec0d2b104ad0a38cf318b1fc970c.png 我们在开一个会话运行这个死循环程序,然后看看他们的进程属性。

e3faddcb9ffd429c9c110b2e9af84488.png

这个时候我们就能看到有两个myprocess可执行程序他们两个很明显是两个不同的进程,任何一个进程都有自己的pid,除了上面这种查看进程的方式,我们还有在系统根目录查看进程的方式:

b3a9cc8b6e394201bca9a81596d6f091.png proc就是进程的缩写,图中红色就是刚刚我们所查看的进程在根目录下显示的情况

702321a6187445c49327b2d4b3576b63.png

 我们利用访问文件的方式去查看新增的进程的属性:

c60741ec7b5348458149ef7b1630d87e.png

接下来我们将进程用ctrl+c终止了。

d48a79d11bf8485297d2126c5ab04230.png 当我们将程序结束后就看不到相对应的进程了。

刚刚我们看到了进程对应的pid,那么我们能不能在写程序的时候就获取到pid呢?答案是可以的,我们可以用getpid()函数来获取pid。

9bd489ad416045e3a81bc84f2b1b45d2.png

 因为getpid()这个函数所需要包含的头文件为#include <unistd.h>  和 #include <sys/types.h>所以我们多加了这个头文件,那么我们来运行一下。注意:修改.c文件后切记make clean一下然后再重新make生成可执行程序。

d46bd1c9e03b42aa837370fe9b544950.png

 可以看到我们获取到了pid,现在去验证一个是否正确。

0108a467341145d8acf01384ecd62dc5.png

 很明显是正确的,之前我们就看到了pid旁边的ppid那么ppid是什么呢?ppid其实是这个进程的父进程,每个进程都会有子进程和父进程,下面我们以同样的方式获取一下父进程的pid:

9d768c9be74a4b698ec222b95aea0730.png

3c58d89d8d7b4c6d80165c08f3698319.png

c61f175308d04c4ea3e3d99cedcbf302.png

 进过验证我们也能发现是正确的。然后我们再重新运行一下程序:

2010fd79e8b74e5dac7ef913b4c2504f.png

这个时候我们发现子进程变了但是父进程还是刚刚的15611这是什么原因呢?那么我们就去查查这个父进程是什么:

9e91fec147fc4a9fb7051497d4cd509a.png279b77fc86df41db941d9d70431c6a47.png

 通过检查我们发现父进程竟然是bash。bash是命令行解释器,bash本质上也是一个进程,因为bash有独立的pid。接下来我们得出结论:

1.命令行启动的所有的程序,最终都会变成进程,而该进程对应的父进程都是bash。

刚刚我们采用的都是ctrl + c的方式结束程序,现在我们用命令的方式去结束,kill -9 +pid就能杀掉一个进程。

7785fca9a97e46b0a63206d4562f0548.png

e5e10ecea4424eaeb74ddc926a776809.png

ac2d76240b17426d8a26a4279f94c553.png 我们可以看到确实将刚刚运行的程序结束了,那么如果杀掉了bash会怎么样呢?

如果我们直接杀掉了bash,那么命令行编辑器就会崩溃我们就无法继续输入命令只能先关闭xshell重新连接才可以。

接下来我们演示一下如何创建一个子进程:

创建子进程我们需要使用fork函数,先来看一下fork函数的使用规则:

55f24046393c427f8bcf2e31f383c4b7.png

3fbe9678f94f42dcaf2cd1a8724ebcbe.png 我们可以看到fork的作用是创建一个子进程,头文件是#include <unistd.h>。

fork的返回值是给父进程返回子进程pid,给子进程返回对应的0值

我们先讲刚刚myprocess.c里的代码先批量化注释掉,如何批量化注释呢?首先在命令模式下按ctrl v 左下角出现V,然后用HJKL四个方向键选出要注释的区域,然后切换为大写,再输入i然后输入//,然后ESC退出即可。

那么如何取消注释呢?直接输入方式切换为小写,然后u一下。当然我们也可以继续使用批量化取消注释的方法,先在命令模式下ctrl v,然后L选择区域,然后直接输入d就能取消注释了。

eecab6d2998b4ea0bb9bfa0f11186d5e.png

55d0b5da6e0e4bd6b76fa26038d510d9.png 首先上图中我们用fork创建了一个子进程,本来这个程序应该只有一个进程由于fork的存在从两行打印变成3行打印,并且创建出来的子进程的pid和ppid都与A完全一样。因为fork的返回值是给父进程返回子进程的pid,所以通过上图我们可以看到ret是22431这是子进程的pid,22431的父进程就是22430了。而给子进程返回0值也可以看到22431这个子进程的ret确实为0。那么为什么一个函数会有两个返回值呢?下面我们用一个程序来解释为什么:

262cb83ed27748f08dc738fdd4a56aac.png

注意:1.fork之后,执行流会变成两个执行流

2.fork之后,谁先运行由调度器决定

3.fork之后,fork之后的代码共享,通常我们通过if和else if来执行分流。

6b0f7943c3e1411087e8173699908526.png

 再说返回值的问题先来说一下fork做了什么,如下图:

550eddbad9864ce7847e03dd58a94dd8.png

 我们很清楚程序运行后会将代码和数据加载到内存中,然后操作系统会将这些描述为task_struct结构体,父进程有自己的PCB和代码和数据,而当我们创建子进程的时候,会在内核当中再创建一个进程所对应的PCB,与父进程不同的是操作系统会修改子进程的一些数据比如pid和ppid,但是这两个PCB都指向一份代码和数据。而进程在运行的时候是具有独立性的,父子进程也同样具有独立性,比如下面我们将一个进程杀掉那么另外的进程还会继续运行:

c393edd517ab4484b9314797f258b968.png

df7710d6bf814fd391dfc44ea1345590.png 0ebc124f671b49e39a7b01aa9fe208f5.png

从上图中我们可以看到当我们杀死子进程时父进程还会继续运行,这就证明了进程具有独立性。

刚刚我们说过父子进程指向同一份代码和数据,那么为什么子进程都结束了父进程的代码和数据不受影响呢?因为对于代码来说代码是只读的,而数据中当有一个执行流尝试修改数据的时候,OS会自动给我们当前进程触发写时拷贝。

当我们函数内部准备执行return的时候,我们的主体功能已经完成,所以执行return的时候由于return也是一个语句,父子进程都会执行这个语句所以才会出现两个返回值,而由于写时拷贝所以能接收到两个返回值。

总结

以上只是linux中关于进程的一小部分,下一篇将持续更新linux进程的概念

要去了解进程应该先了解冯诺依曼体系结构以及操作系统,这样我们在学习进程的时候有一些看不懂的东西才能弄明白,同时进程这部分概念较多所以需要大家理解概念后尝试去通过代码证明概念的正确性,这样才能深入的理解进程。

 

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

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

相关文章

时间复杂度和空间复杂度(1)

目录 1、算法效率 2、时间复杂度 1、定义 2、大O的渐进表示法 3、常见时间复杂度计算举例 3、空间复杂度 4、练习 例1、消失的数字 例2、旋转数组 1、算法效率 算法在编写成可执行程序后&#xff0c;运行时需要耗费计算机的时间资源和空间(内存)资源。因此衡量一个算法…

第八届蓝桥杯省赛——4承压计算(二维数组,嵌套循环)

题目&#xff1a;X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。每块金属原料的外形、尺寸完全一致&#xff0c;但重量不同。金属材料被严格地堆放成金字塔形。7 5 8 7 8 8 9 2 7 2 8 1 4 9 1 8 1 8 8 4 1 7 9 6 1 4 5 4 5 6 5 5 6 9 5 6 5 5 4 7 9 3 5 5 1 7 5 7 9 7 4…

Unity 渲染流程管线

渲染流程图可以把它理解为一个流程&#xff0c;就是我们告诉GPU一堆数据&#xff0c;最后得出来一副二维图像&#xff0c;而这些数据就包括了”视点、三维物体、光源、照明模型、纹理”等元素。参考如下图(来自视频)CPU应用阶段剔除视锥剔除由Unity依据Camera直接完成&#xff…

PowerShell Install Tomcat

Tomcat 前言 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首选。对于一个初学者来说&#xff0c;可以这样认为&#xff0c;当…

什么是百分比堆积条形图?

条形图实际上范围很广&#xff0c;它是以横置图形展示数据的一种图表类型。百分比堆积条形图即以堆积条形图的形式来显示多个数据序列&#xff0c;但是每个堆积元素的累积比例始终总计为 100%。它主要用于显示一段时间内的多项数据占比情况。 百分比堆叠条形图将多个数据集的条…

C++修炼之练气期一层——命名空间

目录 1.引例 2.命名空间的定义 3.命名空间的使用 4.命名空间使用注意事项 1.引例 #include <stdio.h> #include <stdlib.h>int rand 10;int main() {printf("%d\n", rand);return 0; } 当我们用C语言写下这样的代码&#xff0c;看着并没有什么语法…

Kubernetes06:Controller (Deployment无状态应用)

Kubernetes06:Controller 1、什么是controller 管理和运行容器的对象&#xff0c;是一个物理概念 在集群上管理和运行容器的对象 2、Pod和Controller之间的关系 Pod是通过controller来实现应用的运维 比如伸缩、滚动升级等等操作Pod和Controller之间通过 label 标签建立关系…

thread.join 是干什么的?原理是什么?

Thread.join 加了join&#xff0c;表示join的线程的修改对于join之外的代码是可见的。 代码示例&#xff1a; public class JoinDemo {private static int i 1000;public static void main(String[] args) {new Thread(()->{i 3000;}).start();System.out.println("…

C++学习笔记-异常处理

一个问题是程序在执行期间产生了一个例外。 C异常是一个特殊的情况在程序运行时&#xff0c;比如试图除以零而引致的响应结果。 异常提供一种方法来从一个程序到另一个程序的一个部分转移控制。 C异常处理建立在三个关键字&#xff1a; try, catch,和 throw。 throw: 程序抛出…

72. import 导入标准模块(os模块)

72. import 导入标准模块(os模块) 文章目录72. import 导入标准模块(os模块)1. 标准模块知识回顾2. os 模块的基本介绍3. import 导入标准模块1. 方法12. 方法21. 导包不同2. 声明不同3. 路径不同4. 概括3. 方法34. 方法44. 调用模块或库中的类、函数、变量5. os模块的路径操作…

Git ---- 国内代码托管中心-码云

Git ---- 国内代码托管中心-码云1. 简介2. 码云账号注册和登录3. 码云创建远程仓库4. IDEA 集成码云1. IDEA 安装码云插件2. IDEA 连接码云5. 码云复制 GitHub 项目1. 简介 众所周知&#xff0c;GitHub 服务器在国外&#xff0c;使用 GitHub 作为项目托管网站&#xff0c;如果…

InnoDB数据页结构__盛放记录的大盒子

一、不同类型的页简介 前边我们简单提了一下页的概念&#xff0c;它是InnoDB管理存储空间的基本单位&#xff0c;一个页的大小一般是16KB。InnoDB为了不同的目的而设计了许多种不同类型的页&#xff0c;比如存放空间头部信息的页&#xff0c;存放Insert Buffer信息的页&#xf…

「TCG 规范解读」TCG 软件栈 TSS (上)

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alliance,TCPA)所开发的规范。现在的规范都不是最终稿,都…

谈谈XR关键技术及VR/AR/MR/XR关系

一、先别被VR/AR/MR/XR搞晕&#xff0c;说说区别虚拟现实&#xff08;Virtual Reality&#xff0c;VR&#xff09;、增强现实&#xff08;Augmented Reality&#xff0c;AR&#xff09;等业务以其三维化、自然交互、空间计算等完全不同于当前移动互联网的特性&#xff0c;被认为…

Kylin V10桌面版arm3568 源码安装redis

上传redis-5.0.14.tar.gz到/home/kylin/下载&#xff1b;解压kylinkylin:~/下载$ tar -zxvf redis-5.0.14.tar.gz/opt下新建redis目录&#xff0c;并将上面解压的文件夹移到此处kylinkylin:~/下载$ sudo mv redis-5.0.14 /opt/redis/编译&#xff1a;kylinkylin:/opt/redis/red…

ACP、PMP、NPDP含金量哪个高?

在自个的领域而言&#xff0c;知名度、报考人数相对较高&#xff0c;这里我就说下他们的含金量吧。&#xff08;含资料&#xff09; 【ACP】 项目管理相关的证书 1、增加项目管理能力&#xff0c;并且对你拥有的知识与技能起到了很好的证明。不断提高自己的能力&#xff0c;不…

软件测试之场景法

场景法 1. 概述 1.1 为什么使用场景法设计测试用例 大多数业务软件由后台管理&#xff08;比如&#xff1a;用户管理、角色管理、权限管理等等各种管理&#xff09;和工作流等几个部分组成。终端用户&#xff0c;期望软件能够实现业务需求&#xff0c;而不是简单的功能的组合…

webpack热更新原理(面试大概率会问)

搭建webpack环境 创建一个项目 mkdir dev-erver && cd dev-server npm init -y // 快速创建一个项目配置 npm i webpack webpack-dev-server webpack-cli --save-dev mkdir src // 创建资源目录 mkdir dist // 输出目录 touch webpack.dev.js // 因为是在开发环境需要…

三层架构+MVC

前言图 什么是三层架构 什么是三层架构 什么是系统架构 所谓系统架构是指&#xff0c;整合应用系统程序大的结构。经常提到的系统结构有两种&#xff1a;三层架构与MVC。这两种结构既有区别&#xff0c;又有联系。但这两种结构的使用&#xff0c;均是为了降低系统模块间的耦合…

这七个100%提高Python代码性能的技巧,一定要知道

B站|公众号&#xff1a;啥都会一点的研究生 相关阅读 整理了几个100%会踩的Python细节坑&#xff0c;提前防止脑血栓 整理了十个100%提高效率的Python编程技巧&#xff0c;更上一层楼 Python-列表&#xff0c;从基础到进阶用法大总结&#xff0c;进来查漏补缺 Python-元组&…