探索Linux -- 冯诺依曼体系、初始操作系统、初始进程、fork函数

news2024/11/24 16:42:21

一、冯诺依曼体系结构

1、概念

冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。

最早的计算机器仅内含固定用途的程序。若想要改变此机器的程序,就必须更改线路、更改结构甚至重新设计此机器。当然最早的计算机并没有设计成那种可编程化。当时所谓的"重写程序"指的是纸笔设计程序步骤,接着制订工程细节,再施工将机器的电路配线或结构改变。

然后储存程序型电脑的概念改变了这一切,通俗的理解冯·诺伊曼结构与储存程序型电脑是互相通用的名词。

冯·诺依曼提出抛弃十进制,采用二进制作为数字计算机的数制基础。同时,预先编制计算程序,然后由计算机来按照人们事前制定的计算顺序来执行数值计算工作。并且大家把冯·诺依曼的这个理论称为冯·诺依曼体系结构。

冯诺依曼体系结构由这几个部分组成:

  1. 输入设备:键盘、鼠标、话筒、摄像头等等
  2. 输出设备:显示器、打印机、磁盘等等
  3. 存储器(通常指的是内存):内存是一种掉电易失的存储介质
  4. 中央处理器(CPU):由运算器和控制器组成

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。而目前为止我们所认识的计算机都是由一个个硬件设备构成的,这些硬件设备都是独立的

 在这个体系中,所有设备都是要连接的。拿什么链接?拿线连接。拿什么线连接?用总线连接,而所有的线都被集成在主板上,主板就是各个硬件设备之间互相集联的场所

2、计算机存储结构

所有的设备都是要连接的,这句话不是目的而是手段通过连接所有设备达到设备之间数据的流动的目的

而设备之间数据的流动的本质是设备之间数据的来回拷贝,拷贝的整体速度是决定计算机效率的重要指标

原本输入输出设备是直接与CPU连接的,但是输入输出设备距离CPU太远,导致设备的访问非常耗时间,与此同时,由于CPU处理的效率很快,所以这种组合的效率会以硬件设备为标准,计算机的效率会变得很慢!!

因此操作系统引入存储器也就是内存来充当CPU与硬件设备之间的媒介

为什么要有内存?

  1. 引入内存把效率问题转化为软件问题
  2. 引入内存充当CPU与硬件设备之间的媒介,减少了CPU对外部硬件的访问次数,可以使计算机的效率得到提高
  3. 内存的造价比CPU的造价低,可以使计算机的成本降低

程序在运行的时候,必须先加载到内存中,这是为什么?

由于冯诺依曼体系的规定,外设的数据必须先加载到内存中,再由内存交给CPU去执行!

 总结:

  • 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)外设(输入或输出设备)
  • 要输入或者输出数据,也只能写入内存或者从内存中读取
  • 一句话,所有设备都只能直接和内存打交道。

二、操作系统(Operator System) 

1、概念

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:

  • 内核(进程管理,内存管理,文件管理,驱动管理)
  • 其他程序(例如函数库,shell程序等等)

OS是一种软件,当我们要使用计算机时,操作系统就是第一个被加载的程序。

2、设计OS的目的

  • 与硬件交互
  • 管理所有的软硬件资源
  • 为用户程序(应用程序)提供一个良好的执行环境

为什么要有操作系统(的管理)?

对下管理好软硬件资源  --  手段

对上提供一个稳定、高效、安全的运行环境 -- 目的(为了能让用户用的舒服)

3、定位

在整个计算机软硬件架构中,操作系统的定位是:一款纯正的“搞管理”的软件。

3.1 如何理解"管理"

管理无非就是两种情况

  1. 管理者  -->  做决策的人叫做管理者
  2. 被管理者  -->  做执行的人叫做被管理者

而管理者和被管理者不需要见面,管理者可以通过管理被管理者的信息也就是数据进行管理。

就好比我们在一家大公司上班,可能到离职或者退休都见不到几次大老板。那我们上班的工资,绩效,考勤啥的数据就由老板来进行管理。

3.2 对于计算机而言 

硬件部分:

 

计算机管理硬件:

本质就是一个先描述,再组织的过程

  1. 描述起来,用struct结构体
  2. 组织起来,用链表或者其他高效的数据结构 

这样对每个硬件设备建立一个负责描述它们属性的结构体,就可以对数据的管理转向对某种数据结构的管理

在数据量较大的情况下,管理者该如何管理?

每个硬件建立的结构体并用链表把结构体给连接起来,然后再写一批对链表增删改查的代码

这样管理者的所有决策的工作都变成了对链表的增删查改

对被管理者的管理工作也变成对链表的增删查改

软件部分(以用户使用为主):

 

我们为什么要设计操作系统这么一个软件?

目的就是为了对上也就是给用户一个安全、稳定、高效的运行环境。为了保证这些,操作系统就不允许任何人跳过操作系统提供的接口函数来访问操作系统、驱动以及底层硬件设备

所以系统提供了一系列调用接口来给用户,使其方便访问操作系统

这些接口就叫做系统调用接口!

而这些操作系统提供的接口函数都是由C语言设计的函数

但由于系统提供的接口函数数量过多且操作起来对于用户来说有些复杂,于是为了用户的使用方便,操作系统将提供的这些接口函数封装成lib库。像lib库这样的方便用户使用的接口叫做用户操作接口

这样用户就可以通过访问库中的库文件,也可以跳过lib库直接使用系统调用函数

4、系统调用和库函数概念

 系统调用

在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用

库函数

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

像我们使用的printf函数和scanf函数,它们运行都是需要硬件设备的。这证明它们既是C语言中的库函数,也是封装了操作系统提供的系统调用接口。这样才能才能通过操作系统来访问硬件设备!

 在不同的系统中,当用户想要调用库中的函数时。lib库所封装的接口也会不一样,在Linux系统下,lib库就封装Linux系统提供的系统调用接口。在Windows系统下就封装Windows系统提供的系统调用系统。

这就体现了编程语言的跨平台性

 

三、初识进程

 1、基本概念

  • 课本概念:程序的一个执行实例,正在执行的程序等
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体
  • 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元

1. 可以同时启动多个程序,那就得将多个程序加载到内存中

2. 操作系统就得管理多个加载到内存的程序

3. 操作系统如何管理加载到内存的程序呢?先描述,再组织

先描述:

  • 存放在硬盘中的可执行的二进制文件给写入内存时,由于操作系统并不认识这些二进制文件。所以操作系统为了对这些二进制文件加以管理,特地给每个二进制文件都设立了一个描述该文件的结构体变量,接着把该文件对应的属性(标识符、进程ID、状态等等)给写进该结构体中

再组织:

  • 后面操作系统为了方便管理这些结构体,所以就用链表的形式将这些结构体给链接起来。所以对进程的管理转化为对结构体的管理继而在转化为对链表的增删改查

所以到头来什么是进程?

进程 = 可执行程序 + 内核的数据结构 

 

2、描述进程 -- PCB

可执行程序我们知道是什么,那这个内核数据结构又是什么呢? 

内核数据结构是操作系统内核中用于组织和管理系统资源的数据形式或组织方式。这些数据结构通常用于描述和维护系统的状态、进程信息、内存分配、文件系统、设备驱动等方面的内容。

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

PCB也是内核数据结构中的一份子

 3、Linux中的PCB  --  task_struct

task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息

3.1 task_struct内容分类

  • 标示符(pid): 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。

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

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

  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针上(PCB通过内存指针找到进程的数据)

  • 下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。

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

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

  • CPU执行的本质:取指令 -> 分析指令 -> 执行指令。就这样一直循环,直到程序退出CPU。
  • 中央处理器CPU中存在一种指针叫eip/pc指针,这种指针指向的是正在执行语句的下一条语句的地址。
  • 程序中的函数跳转、判断、循环的本质都是修改CPU中的eip/pc指针。
  • eip/pc指针指向哪个进程的代码就代表着哪个进程正在运行。

4、查看进程

4.1 ps指令  --  用于查看当前运行的进程的运行状态

选项:

参数:

常用的ps指令:

ps ajx | head -1 && ps ajx | grep 进程名

 

 在Linux中,进程的标示符用pid表示,标示符用来确定唯一的一个进程,区别别的进程

而每个进程都会有自己的父进程,父进程的标示符用ppid表示。

从上图中我们可以看出,每当我们创立一个新的进程时,其对应的pid都会刷新!!

4.2 getpid() 和 getppid()

  • getpid( ) 函数用来获取当前进程的标示符pid
  • getppid( ) 函数用来获取当前进程的父进程的标示符ppid
  • geipid 和 getppid 这两个函数都被包含在头文件<unistd.h>和<sys/types.h>中

4.3 进程的信息可以通过/proc 系统文件查看

tip:只有当进程存在时,才能根据进程的pid查看进程的信息

ls  /proc/进程pid

 当我们把正在执行的可执行程序给删掉后,此时进程对应的信息显示可执行程序已经被删除。

尽管程序已经被删除,但是进程却从未停止运行

因为在磁盘中的可执行程序被写入内存并转化为进程后,就和磁盘上的.exe问件没有任何关系了

当我们在/proc 系统文件中能看到当前进程所对应的工作目录cwd

所以我们可以通过修改进程的工作目录来改变程序中文件创建的位置

首先我们先介绍用于修改进程工作目录的指令  --  chdir

 可执行文件:

结果:

 

通过把进程的工作目录改到家目录,这样在程序中创建的文件就不会在原来的工作目录而是在修改后的目录下。 

5、 父进程与子进程

 进程只有在程序运行后被写入内存中,才会形成进程。

而每个普通进程都会有它的父进程,它的父进程就是-bash

 为什么我们不手动创建一个进程呢?可以使用fork()函数来手动创建子进程

5.1 fork()函数:

  • fork有两个返回值

  • 父子进程代码共享数据各自开辟空间私有一份(采用写时拷贝)

  • 想让父子进程分别做不同的事

5.1.1  fork函数的疑问:
        1. 为什么上图程序中的两个死循环都能跑?
  • 创建进程时,系统中就会多一个进程。但是每个进程除了有系统创建的PCB外,还会有自己的代码和数据。而子进程刚创建出来的时候只有系统为其创建的PCB,没有属于自己的代码和数据,于是子进程就共享了父进程的代码和数据
  • 子进程被创建出来后,系统会为其创建PCB。但父进程会将本身PCB的大部分数据复制到子进程的PCB中,子进程也需要自己的标示符(pid)和父进程的标示符(ppid)
  • 对于CPU来说,创建一个进程无非就是多调度一个进程。所以CPU会同时调度父进程和子进程,从而执行父进程和子进程的代码

 

        2. 对于fork的返回值,为什么给父进程返回子进程的pid,给子进程返回0?

每一个子进程有且只有一个父进程,但是父进程会有很多个子进程(父   :子 = n   :1)。所以子进程为了让父进程找到自己就必须把自己的标示符(pid)返回给父进程,而子进程就只需要在乎是否被创建成功,所以返回值就只要返回0即可。

        3. 为什么fork函数会返回两次?

首先我们得先知道,当程序运行到return语句时,程序的核心代码已经跑完。

所以在fork函数中,当程序运行到return语句时,代表子进程已经被创建出来。所以父子两个执行流会分别return一次,就出现两个返回值。

        4.  返回值是同一个变量,为什么既大于0,又小于0?

首先我们得先了解一个概念:(任意)进程之间具有独立性,互相并不影响!

tip:共享代码并不影响独立性,因为代码在加载到内存之后是不可能发生改变的!

  • 由于父进程的代码和数据是对子进程共享的,但是代码是只读的,而数据就有可能会被父进程或子进程进行修改
  • 在子进程被创建后,系统就采用写时拷贝,使得父子进程代码共享,数据各自开辟一块空间。

写时拷贝:

当父/子进程想要修改数据时,系统为了防止共享的数据被随意修改,就为被修改数据开辟一块额外的空间并把想要修改的值写入。这样父/子进程就只需要对新开辟的空间的数据进行修改即可

补充:

在Linux中,可以使用同一个变量名来表示不同的内存

在fork函数返回时,return的本质就是返回。当发生写时拷贝后,父进程和子进程虽然是同一个变量,但相同变量写入的值也会不同

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

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

相关文章

安卓应用开发学习:查看手机传感器信息

一、引言 在手机app的开发中经常会用到手机的传感器&#xff0c;在《Android App 开发进阶与项目实战》一书的第10章就介绍了传感器的一些功能和用法。要想使用传感器&#xff0c;首先得知道手机具备哪些传感器。书中有传感器类型取值的说明&#xff0c;并提供了一个查看手机传…

vulnhub系列:DC-9

vulnhub系列&#xff1a;DC-9 靶机下载 一、信息收集 nmap扫描存活&#xff0c;根据mac地址寻找IP nmap 192.168.23.0/24nmap扫描IP 端口等信息 nmap 192.168.23.144 -p- -sV -Pn -O访问80端口 dirsearch目录扫描 python3 dirsearch.py -u http://192.168.23.144/页面查看…

8.12-基于gtids的主从复制搭建+lvs

一、LVS 1.角色 主机名ip地址功能web01192.168.2.101rsweb02192.168.2.102realserveenat内网:192.168.2.103 外网:192.168.2.120directorserver,ntpdns192.168.2.105dns 2..web服务器 [rootweb01 ~]# yum -y install nginx ​ [rootweb01 ~]# echo "web01" > …

【kruskal】最小生成树算法详解

最小生成树kruskal 洛谷 P3366 【模板】最小生成树 算法介绍 最小生成树&#xff08;Minimum Spanning Tree, MST&#xff09;是一个无向图中连接所有顶点的边的集合&#xff0c;这个集合满足两点&#xff1a;第一&#xff0c;它是一棵树&#xff0c;即任意两个顶点之间恰好有…

打靶记录9——Vikings

靶机下载地址&#xff1a;https://www.vulnhub.com/entry/vikings-1,741/ 难度&#xff1a; 低&#xff08;中&#xff09;&#xff0c;CTF风格的靶机 目标&#xff1a; 取得 root 权限 2 个flag 涉及的攻击方法&#xff1a; 主机发现端口扫描Web信息收集编码转换/文件还…

ThinkPHP5.1.C+CmsEasy-SQL注入

目录 1、ThinkPHP 中存在的 SQL注入 漏洞&#xff08; select 方法注入&#xff09; 1.1环境配置 1.1.1将 composer.json 文件的 require 字段设置成如下&#xff1a; 1.1.2设置application/index/controller/Index.php 文件 1.1.3在 application/database.php 文件中配置…

Xcode 在原生集成flutter项目

笔者公司有一个从2017年就开始开发的iOS和安卓原生项目&#xff0c;现在计划从外到内开始进行项目迁徙。 1》从gitee拉取flutter端的代码&#xff1b;&#xff08;Android报错Exception: Podfile missing&#xff09; 2》替换Xcode里的cocopods里Podfile的路径 然后报警 然后…

centos7.9删除home分区扩容至根分区

一、说明 拿到新服务器查看磁盘空间分为根(/),home,swap,boot/efi。home分区站到整个分区的87%以上。和预设的不一致&#xff0c;需要把home删除&#xff0c;扩容至根分区。 新服务器的分区是通过lvm划分的。 二、查看磁盘 三、查看磁盘分区 四、卸载home 卸载前做好备份&a…

自由职业四年,我整理了一些建议

我是勋荣&#xff0c;一个独立开发者。运营了自己的社群&#xff0c;有自己的软件产品。目前还在探索各种副业的路上~ 1我的独立开发之路 刚毕业就找不到Android岗位的我瑟瑟发抖。在广州&#xff0c;稀里糊涂做了Java后端开发。有一天加班 通宵&#xff0c;早上借住在同事家…

机器学习速成第三集——无监督学习之聚类(理论部分)!

目录 聚类的定义和原理 常见的聚类算法 应用场景 总结 无监督学习中聚类算法的最新进展是什么&#xff1f; K-Means聚类算法在处理大规模数据集时的性能优化方法有哪些&#xff1f; 并行计算模型&#xff1a; 多核处理器优化&#xff1a; 分层抽样&#xff1a; 特征缩…

【数值计算方法】非线性方程求根-数值实验

第一题 newton method 非线性方程组的向量函数为: F ( x , y ) ( f 1 ( x , y ) f 2 ( x , y ) ) { ( x − 2 ) 2 ( y − 3 2 x ) 2 − 5 0 , 2 ( x − 3 ) 2 ( y / 3 ) 2 − 4 0. F(x,y)\begin{pmatrix} f_1(x,y)\\f_2(x,y)\end{pmatrix}\left.\left\{\begin{array}{…

Linux 基本指令讲解

linux 基本指令 clear 清屏 Alt Enter 全屏/退出全屏 pwd 显示当前用户所处路径 cd 改变目录 cd /root/mikecd … 返回上级目录cd - 返回最近所处的路径cd ~ 直接返回当前用户自己的家目 roor 中&#xff1a;/root普通用户中&#xff1a;/home/mike mkdir 创建一个文件夹(d) …

高可用集群keepalived详解(基础部署与企业应用示例)

目录 一、高可用集群简介 1.1 集群的类型 1.2系统的可用性 1.3 如何实现高可用 1.4 VRRP(虚拟路由冗余协议)---解决静态网关单点风险 1.4.1 VRRP相关术语 1.4.2 VRRP相关技术 二、Keepalived 部署 2.1 keepalived 架构 2.2 环境准备 三、keepalived基本配置 3.1 全局…

UE开发中的设计模式(三) —— 对象池模式

在FPS游戏中&#xff0c;射击会生成子弹&#xff0c;在命中敌人后子弹会被销毁&#xff0c;那么会导致子弹对象频繁地创建和销毁&#xff0c;会造成运行效率降低且会产生内存碎片问题&#xff0c;而对象池模式可以很好地解决这个问题。 文章目录 问题提出概述问题解决总结 问题…

【C语言】常用函数汇总表

目录 1. C语言常用函数汇总表&#xff08;概念功能&#xff09;1.1 输入/输出函数&#xff08;<stdio.h>&#xff09;1.2 字符串操作函数&#xff08;<string.h>&#xff09;1.3 内存管理函数&#xff08;<stdlib.h>&#xff09;1.4 数学函数&#xff08;<…

快排/堆排/归并/冒泡/

常见的内排序算法 插入排序 直接插入排序 原理&#xff1a;相当于扑克牌变成有序&#xff0c;先拿第一张&#xff0c;把他调节成有序&#xff0c;再拿第二张&#xff0c;与第一张相比找到第二张的位置&#xff0c;再继续拿第三张&#xff0c;以此类推。 void InsertSort(in…

Jupyter Notebook修改文件的默认保存路径

1&#xff0c;安装好后Jupyter Notebook的默认保存路径为用户文件夹&#xff0c; 在jupyter中新建的文件会保存在这里 2&#xff0c;新建一个自己想用来存放Jupyter文件的文件夹 3&#xff0c;找到jupyter的config文件&#xff0c;jupyter_notebook_config.py 4&#xff0c;…

俞敏洪,真窝囊?

文&#xff5c;琥珀食酒社 作者 | 璇子 大家都被俞敏洪骗了 当年《中国合伙人》一播出 俞敏洪竟抱怨黄晓明说&#xff1a; “你把我演得太窝囊&#xff01;” 那俞敏洪真的不窝囊吗&#xff1f; 他培养出董宇辉 让他赚了近6亿 结果人没留住、公司也送了人 还要被丈母娘…

NextJS 服务器端代码调试

NextJS 中如何调试服务器端代码&#xff0c;根据官方文档设置 Chrome 调试&#xff0c;这里有个坑&#xff0c;来看下面配置&#xff1a; {"scripts": {"dev": "NODE_OPTIONS--inspect next dev"} }启动成功&#xff0c;有两个端口 9229、9230&…

企业文件加密软件有哪些,2024常用十款文件加密软件推荐

在当今数字化办公环境中&#xff0c;企业文件加密软件是保护商业秘密和敏感数据的关键工具。随着网络攻击和数据泄露事件的增多&#xff0c;选择一款能够提供强有力保护的文件加密软件显得尤为重要。2024年&#xff0c;市场上出现了一系列新的文件加密解决方案&#xff0c;它们…