目录
1.计算机的组成结构
众所周知,计算机最早是用于军事用途的。1946年第一台计算ENIAC在美国夕法尼亚大学亮相。后来计算机慢慢变成民用支撑。计算机的基本结构——冯诺依曼体系结构。
CPU,储存器,输入设备,输出设备。
储存器:内存,外存(硬盘,软盘,U盘,C盘)
内存:运算访问速度快,储存空间小,断电数据容易消失,成本高
外存:运算访问速度慢,储存空间大,断电数据不容易消失,成本低
2.CPU性能分析
CPU是中央处理单元,是一个电脑核心的部分,负责逻辑判断与算术运算。
1.判断CPU的性能主要看核心数是否足够多与频率是否高
这里有有多少个方框就可以认为有多少个核心,此处是20个。
最早CPU是单核心的,相当于田地里只有一个人在干活,后来都在往这一个核心上去卷,想要尽可能地提升速度。
再后来就开始开发多个核心,08年左右英特尔发布双核心CPU,此后出现四核心,八核心等等。
为什么要了解多核心,充分利用多核心CPU资源实现并发编程对于程序员是非常重要的事情。
程序员可以把一个任务拆分成多个,在不同的核心分别进行。
2.频率
1.79GHZ代表一秒可以算1.79亿次,CPU的运算速度可以用频率来描述(简单粗暴理解成一秒可以执行多少个指令)
CPU的频率是根据任务量动态调整的。
频率越高,消耗的电量越高,发热越多。但是计算机都有“功耗墙”,CPU达到一定的温度们会自动降频。做好散热工作可以是计算机的性能大大提高达到超频。
3.CPU寄存器与缓存
储存数据主要是依靠 内存 和 硬盘。
但是CPU在运算的时候也是要把数据从内存上读取到CPU里才能进行运算。
寄存器就是CPU内部储存数据的部分。
寄存器比内存还要小,运算速度比较内存更快(好几个数量级),成本比内存高,断电后数据消失。
如果遇到某个数据经常使用但是寄存器又存放放不下在怎么办?如果一个数据经常被使用是不是要经常进行数据的IO操作?若果是,那么这样一来CPU的运算效率会大大降低。
计算机CPU引入了缓存,解决以上两个问题。
L1空间最小,运行速度最快。
L2其次
L3空间比L1,L2都要大,相对速度最慢,但是要比内存快很多。
如果缓存足够大,在一些场景中性能的提升非常之大。
数据使用频率越高越往上放L1,其次放L2,最后放L3.
4.CPU执行指令的过程
一个CPU能够执行哪些指令在一开始的时候就是设计好的,下面举例部分指令
指令 | 功能说明 | 4位opcode(操作码) | 操作地址或者寄存器 |
LOAD_A | 从RAM的指定地址,将数据加载到A寄存器 | 0010 | 4位RAM地址 |
LOAD_B | 从RAM指定地址,将数据加载到B寄存器 | 0001 | 4位RAM地址 |
STORE_A | 将数据从A寄存器写入RAM的指定地址 | 0100 | 4位RAM地址 |
ADD | 计算两个指定寄存器的数据之和,并将结果放入第二个寄存器 | 1000 | 2位寄存器ID 2位寄存器ID |
RAM 是 随机存取存储器 (Random Access Memory) 的缩写,是计算机系统中用于 临时存储数据 的主要部件
寄存器很少,所以每个寄存器都有专属的名字
C语言写好的程序,先编译成可执行文件exe,双击运行的时候就会把exe加载到内存中。
CPU中存在一个特殊的寄存器,“程序计数器”保存了接下来从哪里开始执行内存指令。
上图就可以认为是从0号位置开始执行,随着指令的执行这里的值也会自增(顺序执行)
如果遇到‘跳转的指令’比如(if ,while,函数调用)会被设置为其他的值。
CPU执行指令的一般步骤
1.读取指令:CPU中有专门的寄存器来读取指令,不同于上文的寄存器A,B;
指令:00101110
2.解析指令:识别出这个指令的功能,以及对应的操作数
0010是操作码,1110是操作数。
找到操作码取指令表里对应什么操作,0010是LOAD_A指令,1110表示一个内存地址
这个指令的工作就是把1110这个地址的数据加载到寄存器A中。
3.执行指令:将寄存器的数据注入CPU,执行完一个指令后程序计数器中的值会++,0->1
接着去执行第二个指令.......
以上过程仅仅是读取一个数据的操作就如此繁琐,可见CPU运算速度是多么快。
5.进程管理
一个操作系统的功能有很多,比如管理不同的硬件设备,为软件的运行提供安全稳定的环境,内存管理,文件管理等等,操作系统是计算机不可或缺的一部分,使计算机系统能够正常运行,并为用户提供一个安全、高效、友好的使用环境。
操作系统内核是操作系统的核心部分也计算机的大脑,负责提供硬件资源与软件资源,为用户提供服务,同时维持其他所有程序的运行等等。
对于操作系统内核来说有一个功能与程序员的日常开发息息相关——进程管理
进程就是正在执行的应用程序,一个应用程序有两种状态
1.没有运行的时候就是一个exe文件,在硬盘上储存着。
2.双击以后运行以后exe文件就会被加载到内存当中,并且加载到CPU的执行指令里面了。
一台计算机即使人为不使用任何程序,系统也会自动运行一些计算机正常运行所必不可少的进程。
执行进程需要一定的硬件资源,进程是操作系统进行资源分配的最小基本单位。
进程管理:
1.描述:通过结构体/类,把进程的个各个属性表示出来
在C/C++中会用结构体/类实现,且结构体用的更加广泛。
在Linux操作系统中,用“PCB”(进程控制块)这样的结构体来描述进程信息的。
2.组织进程:通过相应的数据结构(大多是链表)串联起来并进一步增删查改查....
创建新的进程(双击exe文件),就相当于创建一个PCB结构体加入到链表中,
销毁进程就是把PCB从链表中删去,并且释放这个PCB结构体。
查看进程就是遍历链表依次显示出进程信息。
6.PCB结构体
PCB是一个非常复杂的结构体,里面包含非常多的属性。
6.1.PID进程的标识符
同一个时刻,一个机器中的很多进程之间PID是不会重复的,每个进程都有独特的标识符,系统内部进行的很多操作,都是通过标识符进行锁定相应的结构体的。
6.2.内存指针
描述进程所依赖的指令和数据都存在内存的哪个区域
操作系统运行exe,就会读取exe中的指令和数据,加载到内存中(内存地址)
说明进程的执行需要一定的内存资源
6.3.文件描述符表(顺序表/数组)
描述了进程打开哪些文件(对应硬盘上的数据),打开的文件就会在顺序表上添加一项
说明进程的执行需要一定的硬盘资源。
7.进程的调度
进程的状态,进程的优先级,进程的上下文,进程的进账信息等这些统称为进程的调度。
进程的调度与日常开发息息相关,计算机中同时存在百八十个进程是非常正常的现象。众所周知,计算机的CPU的核心一次只能执行一个进程,那么如此之多的进程如何去分配时间资源呢?
“分时复用”,CPU的同一个核心可以一会执行这个进程,一会执行那个进程。由于计算机的CPU核心运算速度非常之快,肉眼是难以观察到的,所以感官上来说就是一个核心仿佛同时在执行多个进程。这就使“并发执行”。
现在CPU很很多的核心,此时每个核心都可以同时执行不同的进程,这个就是“并行执行”。
并行与并发都称为”并发“,对应的编程手法也称为“并发编程”。
7.1.进程的状态
比如说我有三个朋友ABC,他们都是可以随叫随到的。此时ABC的状态就是“就绪状态“。
同样的,对于处于就绪状态的进程,是可以随时被调度到CPU上执行指令的。
有一天朋友A外出旅游,A不能随叫随到,此时A就处于”阻塞状态“
对于处于阻塞状态的进程无法调度到CPU上执行。之所以阻塞是因为可能此时在进行硬盘的IO操作。
除此之外还有其他别的状态....
7.2进程的优先级
比如三个女性朋友ABC都想要在同一时刻约我出去玩,此时我就要给这三个朋友排个序。
首先周一周二周三与A出去玩,周四周五与B出去玩,周六与C出去玩。
A能提供更大价值所以应该给A安排更多的时间。程序也是一个道理
7.3进程的上下文
在进程的并发执行时,一个进程执行结束后从CPU上调度走,下次再次执行这个进程如何知道从哪里执行呢?
把之前的执行的中间结果(各种CPU寄存器的值)保存起来,以备下次使用。这就是进程的上下文。
举例:有一天与A一起出去游玩去游泳,A跟我说下次再见她要给她买一件泳衣。于是就要把这件事记录到备忘录。
第二天与B去吃饭,B说她爸爸要过生日了想让我帮忙挑选一个礼物。于是又把这个事情记录到备忘录中去了。
如果不把这些事情记录起来,那么下次容易搞混。很有可能给A买了个老花镜,给B爸爸选了一件泳衣。
把事情记录下来就是上下文,对于进程来说就是寄存器中的值。
PCB中有特定的属性可以保存这些寄存器中的值,等到下次再次调度这个PCB时就可以从这个属性中恢复数据到寄存器就行了。上下文就相当于游戏的存档。
7.4进程的进账信息
随着与ABC相处的时间越拉越长,C逐渐感觉到了我的冷漠,于是C想要离我而去,这个时候我不想要C离我而去,于是我给C一些甜头,于是C此时又对我百依百顺了。
同样的,操作系统会统计每个进程在CPU上的执行时间(进程的进账信息),根据这个来进一步进行调整调度。
进程的状态,进程的优先级,进程的上下文,进程的进账信息等这些属性共同构成进程的调度的核心逻辑。调度过程是操作系统内核完成的。