CPU查找数据的两种方式物理寻址和虚拟寻址、为什么使用虚拟内存、Linux虚拟内存用户空间和内核空间、什么是上下文、什么是进程阻塞、什么是文件描述符
CPU查找数据的两种方式:物理寻址和虚拟寻址
物理寻址的系统:CPU直接访问主存
主存和辅存?
在计算机里面,内存也被称为主存,硬盘称之为辅存。
物理地址?
在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址(Physical Address),又叫实际地址或绝对地址。
内存的物理地址?
主存可以理解为是一个很长的数组,一个字节就是一个单元,它可以划分成很多连续的单元。每一个单元都有一个唯一的地址,这个地址可以理解为内存的物理地址。
在早期的计算里面,如果CPU需要使用内存,必须通过物理地址去直接访问主存,看起来和合乎情理,但是有很多问题:
1.进程直接访问主存的物理地址
现在的操作系统有多个用户,也会有很多个任务同时执行,这些所有的进程会共享主存,也就是说大家会瓜分有限的主存的内容,如果你的设计是每个进程有自己专属的物理地址,每个进程会独自占有主存的一个物理地址块,这样很快主存就会被瓜分完。
所以,肯定是希望同一个主存的物理地址,在不同的时刻,可以被多个进程共享。
2.进程可以直接操作主存
一个进程会修改其它进程的内存的数据,那么就会破坏物理地址的空间,程序运行会出现异常,这个问题就很严重了。
所以,肯定是希望多个进程在不同的时间可以共享同一块主存的内容,但是多个进程在操作的时候是互相隔离的。
那么怎么实现呢?
需要有一个东西去协调和分配和指挥物理地址,在CPU和主存之间加一个中间层,这个时候CPU再去访问主存的时候,就不再使用物理地址,而是通过一个虚拟的地址,由中间层将这个虚拟的地址转换成物理地址,最终获得物理数据,这个中间层叫做MMU(内存管理单元:Memory Management Unit)。
虚拟寻址的系统:CPU访问虚拟地址,再映射到物理地址进行访问
虚拟存储器(虚拟内存)
在CPU和主存之间加一个中间层,这个时候CPU再去访问主存的时候,就不再使用物理地址,而是通过一个虚拟的地址,由中间层将这个虚拟的地址转换成物理地址,最终获得物理数据,这个中间层叫做MMU(内存管理单元:Memory Management Unit)。
有了MMU之后,CPU需要使用内存的时候,会通过一个虚拟的地址映射到一个物理地址上拿到主存,每个进程在创建的时候,都会去分配一个虚拟地址,通过映射的方式去操作,这个时候进程就不能直接操作主存的物理地址了,因为它都不知道是操作哪一块主存的数据。
因此大多数系统都使用了虚拟内存,如Windows虚拟内存,Linux虚拟内存交换空间
在Windows中,虚拟内存是磁盘上的一部分,也就是为什么你的C盘会少很多个g的空间,那个就是虚拟内存用掉了。
不同位数的操作系统,虚拟内存大小关系
在不同位数的操作系统中,虚拟内存的大小是不一样的。
Windows的32位系统中,虚拟地址(虚拟内存) 的大小就是232=4G,在64位系统中就是264=1024*1021TB,很夸张,实际根本用不到这么大。
Linux系统中,通过命令cat /proc/cpuinfo查看linux系统CPU详细信息,address sizes就是CPU的物理内存和虚拟内存位数,248=256TB
# address sizes输出:46位物理地址,48位虚拟地址
address sizes : 46 bits physical, 48 bits virtual
cat /proc/meminfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 94
model name : Intel(R) Xeon(R) Gold 6133 CPU @ 2.50GHz
stepping : 3
microcode : 0x1
cpu MHz : 2494.140
cache size : 28160 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 arat
bogomips : 4988.28
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 94
model name : Intel(R) Xeon(R) Gold 6133 CPU @ 2.50GHz
stepping : 3
microcode : 0x1
cpu MHz : 2494.140
cache size : 28160 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 arat
bogomips : 4988.28
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
总结:为什么使用虚拟内存?
- 虚拟内存可以把同一块物理内存映射到不同的虚拟地址空间,在不同的进程之间实现内存共享
- 对物理内存进行隔离,这样不同进程的操作互不影响
- 虚拟内存空间的大小远远大于实际的物理内存
- 虚拟内存可以提供更大的地址空间,并且地址空间是连续的,这样编写程序去访问会更加简单
Linux虚拟内存:用户空间和内核空间
Linux中虚拟内存又分为两块,用户空间和内核空间
用户空间里面放的是用户的应用程序、代码、数据
内核空间里面放的是操作系统内核的代码、数据
它们都是虚拟内存空间的一部分,都是对物理内存的映射,如果你的进程是在用户空间的,那么称之为用户态,如果是在内核空间的话,称之为内核态。
用户态和内核态的区别
内核态可以访问受保护的内存的空间,也可以访问底层的硬件设备,可以执行任意的命令,调用系统的一切资源
用户态只能进行简单的运算,不能操作系统资源,如果要操作的话,必须通过系统调用接口(System Call Interface),才能向内核发出操作指令
Linux这样划分是为了避免用户进程会直接操作内核,保证内核的安全所以这样设计
什么是进程切换?
操作系统4核,可以同时运行几百个任务,理论上如果是并行执行的话,那么只可能同时执行4个任务,所以任务的执行是并发执行的。系统有CPU的时间的分片的算法,会在很短的时间内将CPU轮流分配给它们,所以我们看起来就像是这些应用程序同时运行,是交替执行的过程,那么也就是说内核必须有能力将一个进程暂停、挂起、阻塞、恢复,然后实现并发执行的效果,这种行为或动作就是进程的切换。
什么是上下文?
每个任务在运行之前,CPU必须要知道任务从哪里加载,从哪里开始运行,也就是CPU必须先给进程设置好它在寄存器和程序计数器的数据,这两个数据就是CPU的上下文,如果没有上下文,就恢复不了,因为找不到上一步执行的状态,这个状态就叫做上下文,是保存在系统内核里的
挂起和恢复的过程这种进程的切换,就叫做上下文切换
因为CPU从内存中找到了你的上下文,然后继续执行任务,所以看起来就是连续执行的一样,上下文的切换需要完成一系列的工作,所以说 上下文的切换是一项比较消耗资源和时间的操作,因此要尽量避免上下文的切换
什么是进程阻塞
正在运行的进程由于提出系统服务请求(如I/O操作),但因为某种原因未得到操作系统的立即响应,该进程只能调用阻塞原语把自己变成 阻塞状态,阻塞状态不会占用CPU的资源
什么是文件描述符(File Descriptor)
Linux里面一切皆文件,包括你的硬件设备。文件描述符FD是内核为了高效管理已被打开的文件所创建的索引(一个非负的整数),用于指向被打开的文件,所有执行I/O操作的系统调用(System Call)都通过文件描述符
文件描述符 | 缩写 | 描述 |
---|---|---|
0 | STDIN | 标准输入(键盘) |
1 | STDOUT | 标准输出(显示器) |
2 | STDERR | 标准错误(显示器) |