计算机是如何工作的(笔记)

目录

寄存器

操作系统

进程(process)

CPU

pcb中关于进程调度相关的属性


寄存器

用来存储数据的单位,是CPU的一部分

寄存器,存储空间更小,访问速度更快,成本更高,掉电后数据会丢失

寄存器的速度和从内存速度的差距是极大的,3~4个数量级

寄存器用途:辅助CPU完成指令的执行,一条指令,不仅仅是指令本身,同时还有操作数

操作数通常是要在寄存器中保存的

由于寄存器和内存之间速度和空间上差异太大了,难以协调工作

CPU 往往又引入了 “缓存” (cache) 来调和寄存器和内存之间的速度

CPU 上要进行一系列运算,在运算的过程中,要反复用到一组内存中的数据,这些数据要频繁使用,又要频繁访问内存,同时这些数据又比较多,在寄存器中又存不下,就可以放到缓存中了

缓存的存储空间介于 寄存器 和 内存 之间

由于寄存器和内存之间差距太大了,搞一个缓存还不够用,后来又搞了一个

现代的CPU 都是这种典型的3级缓存的结构

 缓存大小,对于有些场景,是非常影响到CPU 的性能的 


操作系统

是一个搞管理的软件

操作系统存在的意义:

1、对下,要管理各种硬件设备

2、对上,要给应用程序提供一个稳定的运行环境


进程(process)

进程是程序的实例化,是一个正在运行中的程序、

这是一个所谓的程序,但是这个程序当前并没有正在运行

没有正在运行的程序,不叫进程

同一个程序,运行多次,就可能会产生多个进程

平时所说的程序,指的是 exe 的可执行文件,进程得是把程序跑起来

打开任务管理器,此时看到的这些,都是进程 

程序是一个可执行文件,只是在硬盘上的一个东西(静态的)

如果双击程序,此时操作系统就会把可执行文件中的数据和指令,加载到内存中,并且让cpu去执行这里的指令,完成一系列相关的工作,运行起来的(动态的)进程

进程能够干活,说明进程能够消耗一定的硬件资源

可执行程序,只是占用了硬盘空间,而进程会消耗cpu资源、内存资源、硬盘、网络带宽.....

进程是系统分配硬件资源的基本单位

一台正在运行的计算机中,大概率是包含很多进程的,一旦东西多了,就需要套考虑“管理”

管理的前提是数量非常多,如果只需要考虑一两个进程,不用涉及到这么多

此时,针对计算机中“进程”的管理,核心思路是:先描述,再组织

1、会使用一个专门的结构体来记录一个进程里面各个属性

结构体就是一个低配的类

PCB(进程控制块) 是我们用来描述进程的一个结构体,Linux 中的PCB,在源码中是一个task_struck结构体

2、会使用一系列的数据结构,把多个进程进行一个有效的组织,随时方便进行遍历、查找、汇总数据....

通常是使用双向链表这样的方式来组织

当使用双向链表来组织的时候

a)查看进程的列表,本质上就是在遍历这个链表

b)插入一个进程,就是创建了一个PCB结构体,并且插入到链表上

c)销毁一个进程,就是把这个pcb结构体从链表上删除并释放

PCB中大概有哪些信息呢?

1、pid进程的标识 

在同一个系统上,同一时刻中,每个进程的pid一定是不同的

有的时候,运行的是一个 .exe 但是实际上可能会涉及到多个进程

 2、内存指针

表示了,该进程对应的内存资源是什么样的

内存资源中最主要要存储的就是从exe可执行文件中加载过来的指令和数据,此外还需要保存一些运行过程中的中间结果

指令是指二进制的指令,都是在程序员开发这个程序的时候,最终编译生成的结果,也就是程序员写的代码的逻辑

3、文件描述符表

硬盘是硬件,应用程序一般是没法直接接触到"硬件"这一层的

实际上是操作系统抽象成“文件”这样的概念,程序操作的是文件,而文件实际上是存储在硬盘上的

每个进程就会有一个“文件描述符表” 来记录当前这个进程正在使用哪些文件

操作系统打开一个文件,就会产生一个“文件描述符”(就相当于文件的身份标识一样,当然只是在进程的内部生效的),同时会使用文件描述符表(类似于数组)把文件描述符给组织起来


CPU

进程是需要在cpu上来执行指令的

进程如果是演员,cpu就是拍摄场地,每个进程要想执行cpu里面的命令,完成想要的任务,都需要在cpu上执行

一台机器上,进程同一个时刻有百八十个,但是cpu只有一个,这该怎么办呢?

轮着用就行了,也就是进程的调度

CPU是只有一个,但是舞台不只是一个,现在的cpu都是多核心的cpu

此时,我这个cpu是8个舞台,但是要拍戏的剧组有几十上百个,仍然是不够的,这个时候就要考虑到调度,调度的时候有下面两种情况:

1、并行

在同一时刻,两个进程同时运行在两个cpu逻辑核心上

2、并发

两个进程在同一个舞台上,轮着上

由于cpu切换进程速度极快,微观上,这两个进程是串行执行的,宏观上,看起来这两个进程是“同时”进行的

操作系统,在调度这些进程的时候,可能是按照并行的方式来调度,也可能是按照并发的方式来调度

在应用程序这一层,感知不到(在系统内核中能感知到),由于感知不到是哪种方式调动,并且这两种调动方式在宏观上的体现是一样的,通常也会用 “并发” 这个词代指 “并行” 和 “并发”


pcb中关于进程调度相关的属性

这些属性也就描述了进程对应的cpu资源的使用情况

(1)状态

就绪状态:一个进程已经随时做好了在cpu上执行的准备

阻塞状态 / 睡眠状态:有的时候,进程没有准备好被调度到cpu上

状态之间是可以相互转换的 

实际上,进程在系统中状态还有很多种,其中最关键的就是 就绪 和 阻塞 状态

(2)优先级

系统给进程进行调度的时候,也不完全是公平的,也会根据优先级的不同,来决定时间分配的权限,就可以把系统资源调配给更重要的进程上了

(3)上下文

这些进程是轮着上的,一次运行不完,就需要保证下次上cpu的时候,能够从上次运行的位置,继续往后运行

对于操作系统来说,所记录的上下文就是该进程在执行过程中,cpu的寄存器中对应的数据

这些寄存器,有的是存一些中间结果,有的是才能一些特定含义的数据(比如下一条指令是在哪里,比如当前函数的调用关系)这些寄存器中的数据就需要在进程离开cpu之前,都保存好,保存到对应进程的pcb的上下文字段中(内存中)

下次该进程回到cpu执行,就可以把pcb中的上下文里的数据恢复到对应的寄存器中,这个时候,进程就是和上次执行的状态一模一样了 

(4)记账信息

相当于是一个统计信息

会统计每个进程在cpu上都执行多久了,执行了多少指令了

是对于进度的调度工作进行一个“兜底”

例如:如果我发现给C排的时间太少了,接下来就给C多排一点时间


每个进程,都需要有一定的内存资源

早期的操作系统,就是直接把物理内存分配给进程,就带来一个严重问题:

一旦某个进程内部代码写出了bug,内存访问越界了,就可能影响到别的进程

C语言中有一个东西叫做指针(指针是个变量,存了个整数,这个整数就是内存的地址)

使用指针,尤其是解引用指针的时候,就需要保证当前这个指针指向的是有效的内存,否则解引用操作就可能引起 未定义行为

这个保证是由人工保证的,这就很容易出现指针越界,指向了不该指向的内存(野指针)的情况、

按照上述,直接分配物理内存的模型,此时一旦指针越界指向到其它位置,就会影响到别的进程的执行,会非常影响系统的稳定性

后来,操作系统就引入了 “虚拟地址空间” 这样的概念,有效解决上述的问题

虚拟地址,并非是在物理内存上真实存在的地址,只是在该进程中存在

不同的进程中,可以存在相同的虚拟地址,但是实际上对应到的是不同的物理地址

虚拟地址和物理地址,操作系统可以灵活的进行转换

但是对于应用程序来说,只能看到虚拟地址,看不到真实的地址

虚拟地址的好处:

这样设定之后,每个进程的有效的虚拟地址,都是固定范围

1、这样使用该虚拟地址的内存,都需要操作系统进行转换成物理地址的过程,这个转换过程中,就可以针对虚拟地址是否有效做出一个校验,将之前的人工保证变成了系统自动检查

2、当系统发现这里检查出了非法的地址的使用,就可以及时的通知这个进程,甚至直接让进程挂掉,避免影响到其它的进程,提高了整个系统的稳定性

在虚拟地址空间的加持下,进程就具有了独立性:每个进程都有自己的虚拟空间,一个进程无法直接访问或者修改其它进程虚拟地址空间的内容,强化了系统的稳定性

通过虚拟地址空间,把进程隔离开了,但是有的时候,还需要让进程之间,产生点配合 / 联系

进程间通信:就是在进程隔离性的进程上开一个口子,能够有限制的进行相互影响

进程之间具体用来通信的办法有很多,无论用哪种办法,本质都是一样的:找一个公共的区域,多个进程都能访问到的区域,借助公共区域来完成数据的交换

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值