0%

上下文

首先就要知道,什么是上下文(Context)。一直非常疑惑,到底什么叫上下文。也没太好意思问人,感觉就是很简单的概念。这个观点,也是我去年使用ai的时候,才知道上下文,但是,我理解为上一句话和下一句话,全部组合起来就是上下文,当时,我就是这样去询问ai的。

百度百科的介绍就是:技术系指将一长串的文字或内容,从其中分析出该个段落的摘要以及大意,甚至更进一步,将整篇文章的文意整理出来。此项技术可以应用在解读影片、音讯等档案,使得搜索引擎能够搜寻到文字以外的物件,方便使用者省去大量时间观看影片、聆听音讯,同时也可以帮助使用者提前了解影片与音讯的内容。

上下文简单说来就是一个环境,相对于进程而言,就是进程执行时的环境。
具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。

进程上下文
可以说:
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。

也可以说:
所谓的“进程上下文”,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等。

进程切换:
当内核需要切换到另一个进程时,它需要保存当前进程的 所有状态,
即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。

上下文切换

其实,我们可以把上下文当成一个环境来理解,在RTOS中,每个任务都是属于自己的进程堆栈空间,此时的切换就是可以看成是不同任务之间的切换。这时候上下文环境就是每个任务专属的堆栈空间。

进程上下文的三个部分:用户级上下文、寄存器上下文以及系统级上下文
一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文。

  • 用户级上下文: 正文、数据、用户堆栈以及共享存储区;
  • 寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP);
  • 系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。

当发生进程调度时,进行进程切换就是上下文切换(context switch)。
操作系统必须对上面提到的全部信息进行切换,新调度的进程才能运行。

中断上下文

硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。
这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。

特点:
中断上下文也称原子上下文,该上下文中执行的代码不可阻塞

中断上下文切换:
在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。
但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程 的执行。

中断上下文代码中注意事项
1.运行于进程上下文的内核代码是可抢占的,但中断上下文则会一直运行至结束,不会被抢占。
所以中断处理程序代码要受到一些限制,在中断代码中不能出现实现下面功能的代码:

2.不能-睡眠或者放弃CPU。
因为内核在进入中断之前会关闭进程调度,一旦睡眠或者放弃CPU,这时内核无法调度别的进程来执行,系统就会死掉。牢记:中断服务子程序一定不能睡眠(或者阻塞)。

3.不能-尝试获得信号量
如果获得不到信号量,代码就会睡眠,导致如上中的结果。

4.不能-执行耗时的任务
中断处理应该尽可能快,因为如果一个处理程序是IRQF_DISABLED类型,他执行的时候会禁止所有本地中断线,而内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。中断处理程序的任务尽可能放在中断下半部执行。

5.不能-访问用户空间的虚拟地址
因为中断运行在内核空间。

内核层面看待上下文切换

首先就是切换和保存,这个肯定要调用内核api,然后就是切换虚拟内存,如果是mcu就是直接内存切换,也不用考虑用户和特权之间的虚拟内存不同的问题。给任务一个状态,通知内核去调度它,这有点就绪的意思。

其实没啥东西,就是走一个内核同意,虚拟内存切换,独立堆栈空间切换,用户和特权,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和引导来调度。
设计项目的时候,要注意多系统和多核等诸多情况,作为一个合格的嵌入式工程师,完美支配所有内存和过程,这是必修课呢。这只是一个认识和方案思路,不同公司的思路和实现肯定是不一样的。

起因

今天在写软考题目的时候,我无意间才发现,我居然一直在按位进行寻址,但是实际上都是按照字节取地址的。cpu内通用寄存器的长度取决于机器字长。一下子,我就懵了啊?为什么不是按位取地址?为什么是按照字节?

历史原因

早期的计算机科学太夸张了,早期的计算器五花八门,大家都有各自的方法和规格,当时大家都用字进行寻址,我们知道字不是字节,字的长短是受到系统位数的影响,比如32位的字就是4字节,就是比如IBM 370就是4字节寻址,其他也有一些2字节寻址,1字节寻址等,此时内部的指令也会因为这些寻址而变得非常混乱。我个人觉得可能是因为优化了和统一指令,所以,大家一起选择使用了字节。这就是不断探索中总结出来的实践经验吧。

物理结构

其实,我们可以思考一下,如果寻址,总是寻找一个地方的高低电平,这其实是对开发来说,是毁灭的打击,这就像寄存器编程一样非常痛苦,如果是按照字节寻址就可以得到一个字符,这个意义就很大了,可以组成一段话,可以组成有用的数据。所以,就设计成了一个字线上面有8个位的物理结构设计,此时,也可以做到对位操作,也可以寻址,一举两得。

下面就是一个最基础的位的存储单元

下面是一个字线的物理结构

效率

这个字节选择,肯定不是简单你说我们大家都来用字节,我就用字节的,肯定是因为开发效率高,目前c语言最小的数据类型就是char,我们也确实感觉char作为最小用来开发非常简单,如果是一个一个01组合,那不得了,人得疯掉。还有就是执行效率问题,比如我们使用结构体对齐的时候,就知道,这是为了牺牲空间换取时间效率,因为cpu需要提前根据数据类型来进行对应的寄存器调度和处理。如果按照位来操作,那cpu对其和操作就变成非常复杂。其实,还可以举例子呗,就拿flash和eeprom,那我们知道flash都是按照页来进行操作,因为它快啊,不论是刷新还是写入都是快的,因为他是一块一块处理,如果都和eeprom对一个一个位进行操作,不但效率低下,而且内部线路设计也非常复杂。

结语

综上所述,我个人觉得,选择字节作为寻址和编程基础,是经过大家对设计探索和研究所得到最优解。用过keil都知道,都是会选择开启优化2为主的,这也就是处于一个空间和时间相对平衡的过程,不优化和优化3都是一个比较一般的表现。这也是上古时代,前人用时间和实践一步一步走出来的选择,然后再定下来的结构,确实还是很合理的、很可靠的、很好用的。

文件系统

文件系统,就是来管理物理层面的硬盘,cd,u盘等存储设备,常见的spi,qspi,iic来读取flash和eeporm那些存储设备,这些空间的管理就需要文件系统了,这样可以方便用户知道剩余空间和打开文件。比如有NTFS、FATFS、FAT32等

文件io

我们也知道,我们在开发程序的时候,也是少不了open close write read这些文件io的,还有目录io,不过,为什么我可以使用这些api开发不出现问题呢?

不同的文件系统,它的分配、api、属性、特性都不一样,总不能开发的时候,还一个一个对着这些不同文件系统的api来进行处理吧?

换个思路理解,此时我有一个u盘,我插到linux开发板中,此时就会系统就会识别到一个存储设备,就会自动配置一个设备符,/dev/sda1,此时就可以mount挂载在特定的目录中,此时就可以读取了。此时,可以发现,不论u盘是什么属性什么系统,只要mount挂载上来就可以被读取,这就是虚拟文件系统帮的忙。

虚拟文件系统

一个系统不可能只有一个文件系统的,大家安装固态的时候,分区的时候,肯定就会选择一个文件系统进行格式化比如NTFS,这个时候,这个固态的文件系统就是NTFS了,同时还有一个大小、速率等属性就被系统读取到了,此时,只有把分区执行完毕才能在我的电脑中看到新增加的分盘。这和上面哪个挂载是一个原理。

有了这个虚拟文件系统,就可以极大的方便用户层的开发、使用和管理。本质上就是对多层的文件系统进行一次统一的封装,封装完毕之后,就可以方便上层开发了,所以,哪怕我只有一个2t的固态,我也可以分为1个E盘,一个F盘,至于这个E和F就是虚拟文件系统分出来的东西,实际上的空间就是这个2t的NTFS的固态啦。

总结

虚拟文件系统,只是一个对多个文件系统的api的一次封装,所有文件系统在接入系统的时候,都要主动去对接这个虚拟系统所提供的api,可以认为就是把函数对准虚拟文件系统的函数指针来,然后通过虚拟文件系统的封装,就可以提供给上层开发和管理啦。

编码

​ 什么是编码啊?我们都是adc有,采样量化编码(实际操作种还有滤波),它就是用来保存实际生活中的数据。人类是无法完美实现现实的情形,所以,模电转数电,一定就是经历了抽样,就是丢失,采样率越高就越接近实际但是,采样成功了,就需要输出出来,所以,此时就是依赖编码使用数字信号的方法存下来,然后输出出去。我们日常生活中,最常见的就是图片,视频,音频,字符,压缩.这个博客,只是提一下有什么常见编码,用到的时候再去学习。在这里总结一下,所谓的编码就是将信息或数据转换成特定格式或代码的过程,以便于存储、传输或处理。编码可以应用于各种数据类型,包括图片、视频、音频以及其他形式的数据,它们都是将一种形式的数据或信息转换为另一种形式,以实现特定的功能或目标。

图片格式编码

这个图片的编码模式就太多太多了,多的吓人

1
jpeg、png、gif、bmp、svg、pcx、tga、exif、fpx、psd、cdr、pcd、ufp、eps、ai、raw、WMF等
音频格式编码

音频编码:入门看这篇就够了丨音视频基础 - 知乎 (zhihu.com)

可以参考这个博客

1
2
3
4
5
6
7
8
主要目的是为了下面三个
1)时域冗余
2)频域冗余
3)听觉冗余

常见编码有
PCM 编码 脉冲编码调制(Pulse Code Modulation)
AAC 编码 Advanced Audio Coding
视频格式编码

视频编码格式全面解析 - 知乎 (zhihu.com)

可以参考这个博客

1
2
3
4
5
6
7
ffmpeg
H.264
VC-1是软件巨头微软力推
MPEG-7致力于视听数据信息编码的表达
新势力的WebM
MPEG-2和MPEG -1
MPEG -4
字符格式编码
1
2
3
4
5
Unicode 就是 UTF-8、UTF-16、UTF-32  (Unicode Transformation Format) 二进制格式来表示 Unicode 字符
BOM 就是byte-order mark 的缩写,是 "字节序标记" 的意思
ASCII
GB2312`、`GB18030 、GBK
常用也就是utf-8,GBK 、BG2312,有的时候不支持这个编码就需要使用api来进行编码切换了,这个在python很常见的
信号编码
1
2
3
4
5
6
极化码
卷积码
PCM
Polar码
LDPC码
Turbo码
校验编码
1
2
3
4
5
6
纠错编码
汉明码
里德所罗门编码
低密度奇偶校验码
涡轮码
CRC
加密编码
1
2
3
4
5
6
对称加密编码
非对称加密编码
数字签名
MD5、SHA 系列、HMAC 系列、RSA、AES、DES、3DES、RC4、Rabbit、SM 系列
恺撒密码、栅栏密码、猪圈密码、摩斯密码、培根密码、维吉尼亚密码、与佛论禅、当铺密码
那些密码本都算
压缩编码
1
2
哈夫曼编码
LZ编码 LZ77
总结

可能大家觉得这期博客很水,是因为我本人其实对这些编码确实是不熟的,但是如果实际开发中,连编码都不知道的话,那么是很费力,尤其是像方案和创新的时候,不是说记得多少,有多少知识就有用了,任何一件事情,只要学习百分之60或者有一个正确的概念,在实现的时候再去学习,这才是有用的,一直基于理论的学习是没有重要意义的。编码终究是协议来着,就算使用也是调用库,调用api,所以,我们只要知道这是什么编码,什么地方可以用到编码,可能用到什么编码,我有没有可能在工程中使用到或者切换编码。不会真想看着编码规则,手搓代码吧?那是最愚蠢的行为,花费巨量时间,干着已经成熟的事,别人甚至连优化都做好了,难道硬要用自己手搓的吗?

起因

今天复习了一下网络编程,里面就有一个然后复习一下多路复用。突然,我想到了一件事情,多路复用,肯定就要对存储了套接字的数据类型进行遍历,如链表数组二叉树等。但是遍历过程,就无法实现像tcp和udp那样堵塞等待了啊!那么怎么还能正常实现网络通讯呢!突然我想起来了,我刚学c语言的时候的烦恼。缓冲区!

缓冲区

顾名思义,就是作为数据缓冲,常见于输入和输出中,还记得刚学c语言的时候,printf scanf fput啥的,遇到\n清空缓冲区,刷新缓冲区等东西,都是的。当时就是,非常恼火,为啥要这个破缓冲区啊!现在,就明白,缓冲区是一个非常好的东西。

缓冲区基础作用

缓冲区,最基础的作用就是
输入方面,临时存放数据并告诉cpu来执行中断,防止cpu因为有高优先级任务导致数据丢失。
输出方面,快速连贯的发送,不需要来回执行发送,可以一步到位批量处理,减少硬件资源的消耗。
接收方面,甚至说还可以实现因为两者速率不对等,可以实现一个速率的缓冲,平衡速度差异。
比如两者都是9600波特率,但是硬件的时钟肯定是不可能都一致的。所以数据就可以全部存到缓冲区
等cpu过来拿就好了,哪怕多了一两帧也可以实现速率通信,注意不要太离谱了,而且接收端要采用定期拿走、中断空闲一次性接收拿走、轮询提取等方法。不然可能会导致通信堵塞卡死,数据丢失等诸多问题。

缓冲区系统层面作用

自然我们是离不开系统来分析的,其实缓冲区还有一点就是为了防止内核的多次调用了。我们的应用层一般是处于
用户状态,除了用户状态所有都是特权状态,此时用户状态是无法进行任何底层操作的,只有通过系统调用,软中
断,异常才能让cpu变为特权模式,此时才能去调用底层。
一般系统都是要防止,应用层随意调用底层,所以,容易出现很多段错误,总线错误等,就是为了保护底层,这也
是为了系统的稳定和文件系统的稳定,是非常合理的。所以应用层必须想要发送数据,那么就要使用系统调用,不
可能发一个字节,就调用一次系统调用,那么效率肯定是大打折扣的。同理接收也是这道理。
arm的特权一共有7种,如下图所示:

每次触发大量的接收,就会导致cpu被直接调度到特权模式,此时对于资源是一种极大的浪费,导致系统需要在两个状态反复切换,极大影响效率。所以引入缓冲区之后,输出可以一连串发送出去,这样进入内核的时候就少了,输入也是,可以选择空闲状态接收或者dma接收,这样就可以实现缓冲区收发,牺牲一些实时性,来换取效率和资源,是很赚的。

结语

因为有了缓冲区的存在,系统的资源和调度变得更好管理,效率和资源利用率也得到了提高,但是可不避免的损失了实时性。这也解决了很多因为cpu无法及时到来导致数据丢失问题。cpu毕竟是大家的。所以一开始的多路复用的问题也就是迎刃而解了

TCP/IP
UDP
HTTP
DNS
HTTPS
SNMP
STMP
SSH
SSL
POP
IMAP
MIME
TELNET
IGMP
TFTP
FTP
ICMP
DHCP
TLS
PPPoE
PPP
dhcp
static
PPPoA
3g(PPP over EV-DO, CDMA, UMTS or GRPS )
PPtP(Point-to-Point Tunneling Protocol)
IGRP
RIP
OSPF
EIGRP
EGP
BGP
IS-IS

起因

之前一直没搞懂,这两个的区别,甚至以为可以一起使用,哈哈哈,两个还是有很大的本质区别的。首先就是实时性了。还有成本,效率,使用场景都是不同的。

性质

都是基于差分信号来实现的,数据发送和传输,所以,它们有着一样的电气特性。但是,他们的数据和工作原理是完全不同的。最直接比较吧,CAN是全主机,MODBUS是一主多从。因为CAN有线与操作,所以,0电平就会被当成显性电平,从而获得话语权。显性电平和隐性电平也是can独有的。而MODBUS就是在485的技术上,增加一些对于帧的要求,对于时序的要求。相比起CAN来说,数据帧和查错能力完全不能比

MODBUS

Modbus协议是一种用于工业控制的网络通讯协议,可以片面的理解为,Modbus协议一种机器与机器之间进行数据、信息传递的一种格式规范。
Modbus协议还遵循主从协议,支持单主机,多从机,最多支持247个从机设备。并且,在同一个通信线路上只会有一个主机,所有的通讯过程全部由主机主动发起,从机接收到主机请求后,会对请求做出响应。从机不会主动进行数据的发送,从机之间也不会有通讯过程。
Modbus的通讯方式有:串行通讯方式、以太网通讯方式、串行-以太网转换方式、无线通讯方式

MODBUS确实可以用于网络tcp通信,不过这个我确实没用过,以后用到再补充。

这边就说一下,串行链路吧,就是一个一主多从的模式,主机发送数据给特定从机,从机接收到进行通信,有点iic的味道,一般是建立在485上面的。在iso中属于第七层的应用层,所以,它是可以做到,只要从设备也好些对应从处理,就可以通过485网络实现地址访问和处理了,这其实就是一个广播,对应从机接收到就相应罢了。

如果从机突然没了,主机也是会知道的,这个就看怎么处理了。也要知道一件事情,这个从机出问题是非常麻烦的,设置可能会破坏这个总线链路。

CAN

CAN,这个一看就是车载标配了,可以说,只要是车载就是CAN,基本没有modbus的事情,modbus都是工控那些为主,这是为什么呢?

因为CAN没有主从之分,只有优先级之分,所有人有情况都要立刻反馈到总线之中,比如有刹车信号了,立刻发送到总线之后,此时刹车在发送信号之前就应该执行了,不过是通知总线而已,此时一些其他的制动设备就跟着一起运作,上位应用也因此响应。

不同上面的modbus,它是一主多从,就导致了从机很多时候,是没有主动访问的权限,都是等待主机来一个个询问,这明显是不符合车载需要的,而且车载也确实需要优先级来做到一个先后问题,而且can更加严格,要求也更多,出现问题就多看错误码吧,这个没啥好说的,多调多试,看can手册就会了。而且一个从设备出问题,识别到多次错误还错就会把这个设备屏蔽,这个是一个非常厉害的功能。

一般分为标准帧和扩展帧,看实际的id够不够用吧,一般都是够的。

LIN

LIN(Local Interconnect Network)总线是基于UART/SCI(通用异步收发器/串行接口)的低成本串行通讯协议。其目标定位于车身网络模块节点间的低端通信,主要用于智能传感器和执行器的串行通信,而这正是CAN总线的带宽和功能所不要求的部分。

由于LIN网络在汽车中一般不独立存在,通常会与上层CAN网络相连,形成CAN-LIN网关节点。

什么是LIN总线?高速CAN、容错CAN、LIN总线有什么区别?-CSDN博客

所以就一个CAN-LIN节点挂载CAN总线上面,这个节点下面可以有多个从机,可以把这个节点当成一个主机来看待。

这些从机中有只有一个主机,其他都是从机,一个LIN网络最多可以连接16个节点,也就是15个从机,从机也是智能老实等待主机发送指令,不能越界主动申请发言。

LIN线在物理上是一个上拉到12V的集电极开漏总线,多个节点可以并联到同一根线上,与IIC的SDA类似,但其没有独立的时钟线,靠通信双方约定的波特率进行通信,与UART类似,但由于UART之处在于,其可以通过同步场进行时钟同步,使传输变得更可靠。这样与CAN总线的一对差分双绞线不同,其抗干扰能力大大减弱,通信速率最高只能20Kbps,而CAN可达1Mbps。

LIN线拓扑结构是主从结构的星型模型,所有传输都是master发起,slave不可以主动发起请求。这个其实与modbus更类似。也可以把slave看做消息的发布者,master看成消息的订阅者,想要获取某个变量值,就需要不断问询对应节点对应的报文。这个结构就决定了LIN线传输的消息不可能太多,以保证消息更新的实时性,通常一条LIN线上定义的消息要比一条CAN线上定义的消息少一个数量级。

汽车LIN总线与CAN的区别是什么?-EDN 电子技术设计 (ednchina.com)

使用场景

首先呢,CAN是多主机的,而且MODBUS只有一个主机,所以MODBUS同一时刻只能有一个设备在发送数据。但是很多时候,有些设备是高优先级的,他必须要得到发言,不可能等待其他人执行完毕,而且还要满足大家都发送,所以这个时候线与的作用就出来了,可以多主机仲裁,而且可靠,很多时候好像确实是CAN更好更更可靠,但是CAN更贵,配置也更难,工控的话MDOBUS就足够了。

总结

CAN和MODBUS,各有各自的优劣,主要还是看开发项目的用途。车载终究是涉及到人生安全,标准要更高一点,没办法的,成本也是高的,可靠那些CAN收发器价格就知道了,尤其是车载MCU价格搞得吓人,就是CAN的收发器多。MODBUS,就成本低,更适合工控啦。