0%

CPU工作原理和内核

起因

其实,大学的时候,我是一个纯纯的废物,我天天脑子都是玩乐打游戏,自我麻痹,自我欺骗,说没事的,船到桥头自然直。同时,我内心还有一种不甘堕落的心态,现在想想,当初我还真是又当又立,一边娱乐一边反思,乐死了。所以啊,大学里面的好多东西,我都没学,现在就得从头开始了。即便我如此,我脑子里面还是有一点点关于微机的知识,比如51单片机,他的cpu工作地址从0开始,然后0x03 然后 0x10 然后 0x13。但是,还学了一点点汇编。可是,最近,我在思考,为什么我的代码可以被cpu识别到呢?突然我想来了微机原理了!微机不就是计算机吗?不就是cpu?所以,有这么几天,都是思考cpu是怎么工作的。

CPU

CPU是什么?中央处理器。千万不要用人类思想看待cpu,cpu就是一个取指令,取数据,然后控制和运算的一个处理器。啊?不是哥们[虾],这不是废话?这句话,就是揭开cpu神秘面纱的最重要的一句话,那么我回到上面那个问题,cpu是怎么工作的我们的C语言代码三大语句结构,顺序循环判断。其实,不论如何,我们代码是有方向的,他的本质还是从上往下顺序写。巧了,cpu也是从上往下顺序读取地址操作,我们可以用上面的51的cpu来分析(所有的cpu大致逻辑都是相似的),我们是不是只要把代码写到cpu执行的地址上面,是不是就可以实现cpu操作这个地址呢?所以,我们就知道为什么嵌入式要那么多的交叉编译了!这个交叉编译和中间件就是为了把代码生成目标文件而且还把代码映射到正确的地址上面。只要,我们的代码和数据放在cpu提前约定好的地址上,那么,是不是就实现了代码运行了?

这里只是用了pc指针顺序执行的例子,还没用到手动控制pc指针跳转的功能。假设此时我们跳转成功,那么我们得提前在这个目的地址写好代码和准备数据,这个代码也是根据cpu的顺序操作来映射过去的。没东西的话,cpu就直接傻逼了,直接懵了,就会段错误啊,崩溃啥的,根本没东西,让它怎么执行。

还有取数据,也是从特定的位置拿去数据,我们知道内存分为代码段、data、bbs、堆栈所以取数据也是从提前制定的数据位置进行调用哦,同理的。

引导程序

引导程序,一般有bios,uboot,bootloader。那么引导文件是为了干嘛的?还是根据上面的51分析,我们可以看到,它是傻傻的根据提前制定好的地址开始运行,那肯定是不合适的啊?代码有大小,系统有要求,系统还得升级,系统还得跳转到其他模块工作,系统还得要兼容,系统还得要移植。所以,如果还是根据原本的傻乎乎的工作,肯定是满足不了,所寻求的灵活性,还不能理解,为什么要引导程序吗?一个pc,难道只有windows吗、linux、ubuntu、kail、MAC、IOS都是可以作为我们的系统。我们设计开发板的,是硬件有,但是软件从一开始就不是固定的,引导程序就是为了帮助系统可以使用其他系统或者升级系统。引导程序开始之后就会接管cpu,然后看本地是否存在系统,存在就把cpu的指向指向目标区域。这就实现了系统开机。
mcu不是一定要bootloader,但是越高级的设备,它就越需要引导来帮助切换系统,升级系统等诸多操作。这个的本质是利用cpu的控制总线,来控制程序跳转,控制cpu运行方向。

系统

系统,若干部分相互联系、相互作用,形成的具有某些功能的整体。在嵌入式中,就是资源管理和分配。系统还分等级,这里可以看之前的系统选择那些博客,里面就有我对于系统的看法和我个人的理解。
windows、安卓、ios、mac、linux、鸿蒙、澎湃….太多了,那么系统是什么?系统为什么那么厉害?其实,不要神话系统了,不要神话任何技术,去面对和学习它,所谓的系统就是程序。它也是通过把系统放在特定的位置上,等待cpu或者引导程序来调用它。我们可以学习一个freertos,这是一个开源的,系统,所以,我们就可以仔细拜读一下。它有内存管理,系统任何调度,系统延时,系统中断,系统资源管理。它就是一个非常简易的系统了,但是功能可不少,因此,系统就是把可应用程序和系统程序一起编译形成的程序,这个程序变成目标程序就可以被cpu调用了。
千万不要用人类思想看待cpu。cpu是没有脑子的,它就是根据人类的要求,来对数据进行特殊处理。此时,所谓的系统和程序就是一段没有价值的二进制。那不可能啊?我那么大的系统,你跟我说,它没价值?这里,我们要明白,价值不是cpu不是电脑赋予的,是人类赋予的。这里举个例子,我有1斤苹果,1斤西瓜,要得到它们的价格,我就把1斤苹果乘5交给cpu处理,一斤西瓜x2交给cpu处理,所以,此时cpu处理完毕之后就是得到了7。这个7此时有意义吗?没有意义的,因为人类还没给他单位,所以,此时系统再通过特定的程序和指令,让cpu来调度实现对io的控制,此时进行对外输出输入功能了,通过特定的输入输出操作,就可以给这个7赋予一个钱的概念。这个时候,系统才有意义。

多核

​ 看到这里,都知道,我们肯定不能只玩那么简单的啊?那肯定得上多核啊!!!!我们都知道多核,有同构多核和异构多核!这两个多核就会带来非常大得麻烦,这里抛出来问题咯。系统如何实现中断?系统如何实现资源分配?系统如何分配cpu?多核的时候,怎么保证系统不崩溃?
第一个问题,多核中断管理。

方案1,就是各自处理各自的,然后通过中间的共享内存来进行通信告诉对方
方案2,就是各自处理各自的,但是,有主核心和从核心,从核心执行完毕自己的中断必须告诉主核心中断执行完毕
方案3,每一个核心触发了中断都要告诉主控,通过主控中的系统来进行调度,看那个cpu是空闲的
方案4,可以把中断总线连接到一起,这也的话,就可以实现一方控制全场,难度和设计非常复杂

第二个问题,资源分配。
如果是同构多核,那么就需要做很多的pv,互斥,竞争,抢占的处理了
如果是异构多核,那么就需要主控来进行处理和管理了,因为此时每个核心都是各自独立的内存,只有中间有缓冲区
内存和总线可以用来通信。

第三个问题,如何保证不崩溃?
这个问题,是不是有点被问懵了?
如果是异构,这个其实不好遇到的。但是同构就不一样了。我们上面做了我们对于系统的看法和定义,它就是一段代码,对还是不对?代码,就有三大结构,顺序循环判断。系统如果多核心处理?那我代码有顺序、时间、逻辑、过程、通信、顺序、功能内聚。数据、标记、控制、外部、公共、内容耦合。还有互斥怎么办?有先后怎么办?需要同步怎么办?那我的系统还没开始就崩溃了,你这个核心处理一下,那个核心处理一下,顺序都乱没了,玩个屁的系统啊。这怎么办?是不是有点懵了。其实,我们可以回到freertos的实例中看一看。首先就是内存分配,系统初始化,线程创建,然后就是系统调度了!聪明的人已经知道了是怎么解决得了!没错就是系统调度!只有开启系统调度之后,才会可能使用多核操作,再次之前都是系统初始化!我们就有方案了。

方案1,它们是需要同步和顺序的,如果真的需要多核心来初始化的话,那么互斥和顺序的结果,就要增加限制,竞
争管理,同步等诸多操作
方案2,在单一核心上面进行系统初始化完毕,线程创建完毕(这个就是调用api,告诉多核这个是可以多任务运行的),
一切init都ok了,再开启系统调度,运行多个任务多个cpu进行操作,这个方案也是最简单,最好实现的。

如果你看到这里了,你不会以为我的思考就此停止了吧?嘻嘻,还有呢!

多系统

​ 自始至终了,没人定义,只能有一个系统吧?我们知道系统要进行资源分配和管理,那么内存冲突怎么办?这个系统凭什么让另一个系统调度?我们上面考虑都是单系统多核,但是没考虑多系统多核心的情况。此时cpu真的要被玩坏了。
​ 比如使用freertos+fatfs这就是一个实时系统+文件管理系统,它们可以完美的共存,这不会相互冲突?不会相互
打架?两者都是管内存的啊。
​ 这里,我提出一个概念,就是主系统和从系统概念,每个主系统都是需要管理整个项目的所有内存的(包括后续挂载的),而从系统不能设计太底层的内存管理和资源调度,资源调度和底层内存管理只有主系统才有资格管理。那么fatfs怎么办?很简单啊,主系统调用fatfs的api这样就实现了再fatfs中资源统计,但似乎fatfs的初始化中就被考虑到了是主系统来控制内存,fatfs,不过知识提醒主系统,这一段空间中数据是一个文件哦,不是单纯的数据,你可以拿出来用哦!所以,此时fatfs是没有控制内存的,它不过是记录了这段内存是文件罢了。影响不了主系统对于内存的支配。
​ 所以,我们再进行多系统的设计的时候,就要注意,主从之分,主只有一个,从可以多个,但是必须要根据从的api和规则进行调用。从系统之间也要注意,防止冲突了,比如不要来两个文件管理系统,这样很容易混乱的。

总结

cpu的运行其实本质就越是受它的架构影响,有x86的架构,有arm的架构,有ibm的架构,powerpc等,它们的cpu起始位置不同它们的cpu运行方向和逻辑也是不同的,但是还是有一个默认顺序的。此时,我可以通过编程他的pc指针,来告诉它下一步该干什么。注意了,前提是你的引导得在它cpu最初的工作路径上,运行引导才能接管cpu的控制。cpu也是顺序的,cpu也是可以跳转的,它和你的代码是一一对应的,所以,那些复杂的编译和处理就是为了把目标文件映射到正确的路径上,方便cpu和引导来调度。
设计项目的时候,要注意多系统和多核等诸多情况,作为一个合格的嵌入式工程师,完美支配所有内存和过程,这是必修课呢。这只是一个认识和方案思路,不同公司的思路和实现肯定是不一样的。

-------------下次的来访是什么时候呢[doge]-------------