(嵌入式面经)第11章 20+公司面经杂谈(一):华为、博世、韶音
预计2025.03.11,完成优化/完善该内容,敬请期待!!!
(以下为学习过程中的粗略知识点,还未经过优化/完善,后续会变成更有条理的形式!!!)
2.1 面经华为
2.1.1 设计模式:
2.1.2 TCP UDP流:
TCP 是流协议,没有明确的消息边界,因此可能会发生粘包和拆包现象。粘包是指多个数据包被粘在一起发送,接收方无法分辨出数据包的边界;拆包是指一个数据包被拆分成多个小包发送。要解决这个问题,可以采取以下措施:
固定长度:在数据包中定义固定的长度字段,接收方根据长度字段读取数据包。
分隔符:在数据包之间使用特殊的分隔符(如 \n 或 \0)来标记数据包的结束,接收方根据分隔符来拆分数据包。
消息头:在数据包前添加消息头,消息头中包含数据包的长度信息。接收方首先读取消息头,然后根据长度信息读取数据包的内容。
自定义协议:设计应用层协议,包含数据包的起始标志、长度字段等信息,用于标识数据包的边界。
一、粘包与拆包是什么?
TCP在接受数据的时候,有一个滑动窗口来控制接受数据的大小,这个滑动窗口你就可以理解为一个缓冲区的大小。缓冲区满了就会把数据发送。数据包的大小是不固定的,有时候比缓冲区大有时候小。
如果一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题;
如果一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包,也就是将一个大的包拆分为多个小包进行发送。
二、粘包与拆包为什么发生?
1.TCP会发生粘包问题:TCP 是面向连接的传输协议,TCP 传输的数据是以流的形式,而流数据是没有明确的开始结尾边界,所以 TCP 也没办法判断哪一段流属于一个消息;TCP协议是流式协议;所谓流式协议,即协议的内容是像流水一样的字节流,内容与内容之间没有明确的分界标志,需要认为手动地去给这些协议划分边界。
粘包时:发送方每次写入数据 < 接收方套接字(Socket)缓冲区大小。
拆包时:发送方每次写入数据 > 接收方套接字(Socket)缓冲区大小。
2.UDP不会发生粘包问题:UDP具有保护消息边界,在每个UDP包中就有了消息头(UDP长度、源端口、目的端口、校验和)。
粘包拆包问题在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中
2.1.3 压力面
1. 问做项目或实习过程中遇到难题,怎么解决;
2. 你觉得目前为止遇到的最大的挫折是什么,如何解决;
3. 团队合作有分歧怎么解决;
在会上让他们互相阐述观点,互相说服。时间充足的话拿出demo,时间紧张要根据经验来看,后续也可以进行调整
4. 遇到压力大怎么解决;
多线程的时候,手头有很多事情要做。冷静分析,划分优先级。做计划
5. 遇到不会的问题如何去做,说一个大概的思路或流程,最好结合某个项目说;
6. 对华为的认识,为什么应聘华为;
7. 为什么不选择互联网行业?
首先是科研方向长期学习的知识跟嵌入式比较契合,其次互联网也很少嵌入式的岗位,主要业务也不在这里,感觉未来技术成长等都没有华为带来的多
8. 对其他的制造业公司有什么认识?选几个介绍分析下他们的优缺点?
9. 你觉得华为实习带给你什么?如果你不选择华为的话主要是因为什么?
10. 你对无线或者通信行业有什么认识看法?你对行业的选择是基于什么?
11. 项目的背景是什么?
12. 项目有哪些难点?
13. 项目开发过程中遇到问题是如何解决的?
14. 有没有参加一些软件开发相关的竞赛?
15. 自己未来的职业规划是什么?
职业规划还没有特别的清晰,还是学生,眼界比较窄,目前大概就是想一方面专心技术,成为技术专家,另一方面走技术管理路线,可能需要入职之后继续精进后再做判断。
16. 为了达成这些规划具体会做些行动?
进入公司后,遇到技术专家与技术管理路线的大佬,请教,会分析要达到这个规划所需要的更具体的行动,但是首先要精进自己的技术。
17. 如何看待华为公司?
以客户为中心,以奋斗者为本,长期坚持艰苦奋斗。对每一个有技术肯努力的员工,有很好的福利,也有更大的平台。1.平台大,公司知名,国内外影响大,有排面 2.薪水高,有能力的人不缺发展机会 3.每年招的人多,机会稍多 4.工作地点多,选择自由度大 5.什么专业的人都有机会去应聘,专业宽容度大
18. 为什么想来华为公司进行实习?
19. 能够实习多长时间?
2.2 面经博世
2.2.1 编译器怎么优化的?
Volatile关键字:当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用volatile,则编译器将对所声明的语句进行优化。
使用场景:
1) 中断服务程序中修改的供其它程序检测的变量需要加 volatile;
2) 多任务环境下各任务间共享的标志应该加 volatile;
该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程,也就是说,线程一和线程二使用同一个变量、
但是由于编译器优化,导致线程一更改该变量后,将其缓存在寄存器中,还没来得及其更新到内存中,线程二使用到该变量时,从内存中读取该变量,就无法获取到该变量的真实值。
为什么要做这种优化?
因为cpu从寄存器中读写数据远快于cpu从内存中读写数据,线程一使用完该变量后,就将其存放在了寄存器,然而线程二并不知道线程一把该变量放在了寄存器中,还傻傻的从内存中读取该变量,肯定读不到正确的值(即更新后的值)
(3) 存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能由不同意义;
高速缓存(Cache)是一种用于存储和访问频繁使用的数据的高速存储器,旨在提高系统性能,减少访问主存储器的延迟。它位于CPU与主内存(RAM)之间,充当两者之间的“缓冲区”。通过使用Cache,系统能够更快地访问那些被频繁访问的数据,从而提高计算效率。
编译器优化:内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。对常规内存进行优化的时候,这些优化是透明的,而且效率很好。由编译器优化或者硬件重新排序引起的问题的解决办法是在从硬件(或者其他处理器)的角度看必须以特定顺序执行的操作之间设置内存屏障(memory barrier),linux 提供了一个宏解决编译器的执行顺序问题。
详解C/C++中volatile关键字_volatile c-CSDN博客
2.2.2 优先级反转?
多个线程操作 / 访问同一块区域(代码),这块代码就称为临界区,上述例子中的共享内存块就是临界区。线程互斥是指对于临界区资源访问的排它性。当多个线程都要使用临界区资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步。
共享内存块
使用信号量会导致的另一个潜在问题是线程优先级翻转问题。所谓优先级翻转,即当一个高优先级线程试图通过信号量机制访问共享资源时,如果该信号量已被一低优先级线程持有,而这个低优先级线程在运行过程中可能又被其它一些中等优先级的线程抢占,因此造成高优先级线程被许多具有较低优先级的线程阻塞,实时性难以得到保证。如下图所示:有优先级为 A、B 和 C 的三个线程,优先级 A> B > C。线程 A,B 处于挂起状态,等待某一事件触发,线程 C 正在运行,此时线程 C 开始使用某一共享资源 M。在使用过程中,线程 A 等待的事件到来,线程 A 转为就绪态,因为它比线程 C 优先级高,所以立即执行。但是当线程 A 要使用共享资源 M 时,由于其正在被线程 C 使用,因此线程 A 被挂起切换到线程 C 运行。如果此时线程 B 等待的事件到来,则线程 B 转为就绪态。由于线程 B 的优先级比线程 C 高,且线程B没有用到共享资源 M ,因此线程 B 开始运行,直到其运行完毕,线程 C 才开始运行。只有当线程 C 释放共享资源 M 后,线程 A 才得以执行。在这种情况下,优先级发生了翻转:线程 B 先于线程 A 运行。这样便不能保证高优先级线程的响应时间。
在 RT-Thread 操作系统中,互斥量可以解决优先级翻转问题,实现的是优先级继承协议 (Sha, 1990)。优先级继承是通过在线程 A 尝试获取共享资源而被挂起的期间内,将线程 C 的优先级提升到线程 A 的优先级别,从而解决优先级翻转引起的问题。这样能够防止 C(间接地防止 A)被 B 抢占,如下图所示。优先级继承是指,提高某个占有某种资源的低优先级线程的优先级,使之与所有等待该资源的线程中优先级最高的那个线程的优先级相等,然后执行,而当这个低优先级线程释放该资源时,优先级重新回到初始设定。因此,继承优先级的线程避免了系统资源被任何中间优先级的线程抢占。
【操作系统】优先级反转、优先级继承、优先级天花板_优先级继承和优先级天花板的区别-CSDN博客
2.2.3 独立看门狗和窗口开门狗
STM32有两个看门狗,一个是独立看门狗另外一个是窗口看门狗,独立看门狗号称宠物狗,窗口看门狗号称警犬,本章我们主要分析独立看门狗的功能框图和它的应用。独立看门狗用通俗一点的话来解释就是一个12位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即IWDG_RESET。如果在计数没减到0之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。看门狗功能由 VDD 电压域供电,在停止模式和待机模式下仍能工作。
STM32有两个看门狗,一个是独立看门狗,一个是窗口看门狗。我们知道独立看门狗的工作原理就是一个递减计数器不断的往下递减计数,当减到0之前如果没有喂狗的话,产生复位。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值0X40时还不喂狗的话,产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义
在嵌入式系统中,看门狗(Watchdog)是用于监测系统状态并在系统发生故障时进行复位的机制。看门狗可以分为两种主要类型:独立看门狗(Independent Watchdog, IWDG)和窗口看门狗(Win
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
作者简介:仅用大半年时间0基础天坑急转嵌入式开发,逆袭成功拿下华为、vivo、小米等15个offer,面试经验60+,收藏20+面经,分享自己的求职历程与学习心得。 专栏内容:最新求职与学习经验,详细讲解了嵌入式开发的学习路径、项目经验分享、简历优化技巧、面试心得及实习经验,从测评,笔试,技术面,HR面,AI面,主管面,谈薪一站式服务,助你突破技术瓶颈、打破信息差,争取更多大厂offer。