根据面经准备面试-第二期-2026字节跳动嵌入式软开提前批

还想看哪家公司可以评论区评论,有些笔误证明自己没开

2.FreeRTOS任务调度,调度策略

3、优先级反转

4、QT和LVGL

5、OTA

6、对此加密和非对称加密

7、线程和进程,进程间的通信方式

8、线程同步机制9、死锁

10、堆、栈、内存分区

11、heap4的算法

12、tcp,udp,三次握手,四次挥手

13、DNS

14、智能指针

15、虚函数

16、链表

17、手撕——回文字符串判断

18、手撕——翻转链表

2. FreeRTOS 任务调度及调度策略

答:freertos的任务调度是抢占式的,核心是根据任务优先级决定执行哪个任务

核心:优先级抢占:高优先级任务就绪时,立即打断低优先级级任务(除非低优先级持有互斥锁)

时间片轮转:同优先级任务采用时间片轮转的方式(开启configuse——time-slicing),每个任务运行一个时间片(由configtick———rate-hz决定,10ms后切换)

协作式调度:通过taskyteld主动让出cpu,需关闭抢占,

3.优先级反转:低优先级任务持有高优先级任务需要的资源时,导致高优先级任务被阻塞,中等优先级任务反而能运行

打破优先级高的先执行

  • 任务 L(低优先级)获取互斥锁 M;
  • 任务 H(高优先级)需要锁 M,因 L 持有而阻塞;
  • 任务 M(中优先级)就绪,抢占 L 的 CPU,导致 H 长时间阻塞。

解决办法:优先级继承:低优先级任务持有高优先级任务需要的锁时,临时提升到高优先级,防止被中等优先级任务抢占(FreeRTOS 的vSemaphoreCreateBinary()互斥锁默认支持)。

  • 优先级天花板:给资源设置固定 “天花板优先级”,任何持有该资源的任务都临时提升到天花板优先级。
  • 4.QT 和 LVGL 的区别

    QT LVGL

    定位

    跨平台 GUI 框架(支持桌面 / 嵌入式)

    轻量级嵌入式 GUI 库(专注资源受限设备)

    资源占用

    较大(需 MB 级内存)

    极小(KB 级内存,适合 MCU)

    适用场景

    复杂界面(如工业控制屏、车载系统)

    简单界面(如智能手表、家电显示屏)

    渲染方式

    支持硬件加速(OpenGL)

    主要软件渲染,支持部分硬件加速

    开发语言

    C++

    C

    5、OTA

    定义:通过无线方式(如 Wi-Fi、蓝牙)远程升级设备固件,无需物理连接。

    流程

    1. 设备从服务器下载固件包(需校验版本号,避免重复升级);
    2. 校验固件完整性(如 CRC、MD5)和合法性(如签名验证);
    3. 将固件写入备用分区(双分区设计,避免升级失败变砖);
    4. 重启设备,从新分区启动,若失败则回退到原分区。

    这里拓展一下IAP,设备自己升级自己的程序。简单说,就是设备里已经有一个能运行的程序(叫 “bootloader” 或 “APP1”),这个程序可以把新的固件(比如新 APP)写到自己的存储里,然后重启运行新程序。

    关系:OTA 是 “远程获取新固件” 的过程,而 IAP 是 “设备本地安装新固件” 的核心技术。没有 IAP,OTA 拿到新固件也没法升级

    IAP核心原理:设备存储(flash),分成两个区域

    boot loader区域,进门线运行程序,负责检查是否有新固件,如果有就启动升级(IAP的核心)

    app区域,平时正常工作区域

    需要升级时,1.新固件通过OTA传到设备,先存在临时区域

    2.bootloader启动,发现有新固件,就从临时区域搬到app区域,覆盖掉旧程序

    3。搬完后重启,bootloader直接运行app区域

    IAP具体流程,以单片机+flash

    1.给存储分区,吧设备flash分成3个区域:bootloader放IAP升级程序

    app区:放正常的工作程序

    临时缓冲区域:暂存OTA下载的新固件(也可以用内存,内存小分段存)

    2.正常运行,bootloader跳转到app

    设备上电先运行bootloader,检查是否需要升级,(比如看一个标记位:如果用户触发了升级,或 OTA 下载了新固件,就设为 “需要升级”)

    3.触发升级:收到新固件

    • 比如通过 OTA 从服务器下载新固件(假设叫 “new_app.bin”),存到临时缓冲区。
    • 下载完成后,设置一个 “升级标记”(比如在 Flash 的某个固定地址写 1,表示需要升级),然后重启设备
    • 4. IAP 核心:Bootloader 写入新固件

      设备重启,再次运行 Bootloader:

    • 检测到 “升级标记 = 1”,开始执行升级逻辑。
    • 读取临时缓冲区的新固件数据,逐段写到 APP 区(覆盖旧程序)。注意:写 Flash 时要先擦除对应区域(Flash 特性:必须先擦除才能写)。
    • 写完后,校验新固件是否完整(比如算 MD5 值,和服务器给的对比,防止下载出错)。

    5. 完成升级:清除标记,跳转新 APP

    • 校验通过后,清除 “升级标记”(写 0),删除临时缓冲区的旧固件。
    • 重启设备,Bootloader 检测到 “不需要升级”,跳转到 APP 区,此时运行的就是新程序了。

    6. 异常处理:防止变砖

    • 如果写固件时突然断电,重启后 Bootloader 发现 “升级标记 = 1 但 APP 区不完整”,会等待重新下载固件后再次升级。
    • 如果新固件校验失败(比如损坏),Bootloader 会保留旧 APP,提示升级失败。

    6.对称加密与非对称加密

    回答:对称加密(如 AES、DES),加密和解密用同一密钥,快(适合大数据量,如文件),依赖密钥保管(泄露则不安全)

    非对称加密(如 RSA、ECC),公钥(公开)加密,私钥(保密)解密,慢(适合小数据,如密钥交换),公钥公开不影响安全,私钥保密即可

    结合使用:HTTPS 中,先用非对称加密交换对称密钥(如 RSA),再用对称加密传输数据(如 AES),兼顾安全和效率。

    7、线程和进程,进程间的通信方式

    进程:系统资源分配的基本单位,有独立内存空间,切换开销大

    线程:进程内的执行单元,共享进程内存,切换开销小,是调度的基本单位

    进程间通信的方式

    管道,匿名管道,父子进程,命名管道,基于文件系统

    消息队列,内核中的消息链表,进程按类型收发消息

    共享内存,最快的进程间通信方式,内核

    • 信号量:用于同步(如控制资源访问次数)。
    • 信号:进程间异步通知(如SIGINT终止进程)。

    8、线程同步机制

    线程共享线程资源,需要同步机制避免冲突

    互斥锁,独占资源,同一时间仅仅一个线程访问

    条件变量:线程间同步,生产者消费者模型,生产者通知消费者有数据

    信号量:控制并发树,允许3个线程同时访问资源

    读写锁:读多写少场景优化,多个读线程可同时访问,写线程独占

    原子操作:无锁同步(如atomic_int,适合简单计数)

    9、死锁

    定义:两个或多个线程互相等待对方释放资源,导致永久阻塞。

    必要条件

    1. 互斥:资源只能被一个线程持有;
    2. 持有并等待:线程持有部分资源,同时等待其他资源;
    3. 不可剥夺:资源不能被强制剥夺;
    4. 循环等待:线程间形成等待环路(如 A 等 B 的资源,B 等 A 的资源)。

    预防方法

    • 按固定顺序申请资源(打破循环等待);
    • 申请资源时一次性获取所有需要的资源(打破持有并等待);
    • 超时释放资源(如pthread_mutex_timedlock)。

    10、堆、栈、内存分区

    内存分区

    • :存放局部变量、函数参数,由编译器自动分配释放(如int a = 10;),大小固定(通常几 MB),速度快。
    • :动态内存(如malloc/new分配),需手动释放(否则内存泄漏),大小灵活(可到 GB 级),速度较慢。
    • 全局 / 静态区:存放全局变量、静态变量(static),程序启动时分配,结束时释放。
    • 常量区:存放字符串常量(如"hello"),只读。
    • 代码区:存放程序指令(二进制代码),只读。

    例如:int g_var;(全局区),void func() { int s_var; }(栈),int *p = malloc(10);(堆)。

    11、heap4的算法

    heap4 是 FreeRTOS 的内存分配算法,基于 “最佳适配” 策略,适合中小规模内存管理:

    • 原理:内存被分成多个块,每个块包含 “大小 + 已分配标志” 的头部;
    • 分配:遍历所有空闲块,选择能容纳请求大小的最小块,分割后分配;
    • 释放:释放时检查相邻块是否空闲,若空闲则合并(减少内存碎片)。

    12、tcp,udp,三次握手,四次挥手

    TCP 与 UDP

    • TCP:面向连接、可靠传输(重传、确认机制)、流式数据(无边界),用于文件传输、HTTP 等。
    • UDP:无连接、不可靠(无重传)、报文式(有边界),用于实时通信(如视频、DNS)。

    TCP 三次握手(建立连接):

    1. 客户端→服务器:SYN(请求连接,序号 x);
    2. 服务器→客户端:SYN+ACK(同意连接,序号 y,确认 x+1);
    3. 客户端→服务器:ACK(确认 y+1)。(确保双方收发能力正常)

    TCP 四次挥手(断开连接):

    1. 客户端→服务器:FIN(请求断开,序号 x);
    2. 服务器→客户端:ACK(确认 x+1);
    3. 服务器→客户端:FIN(准备断开,序号 y);
    4. 客户端→服务器:ACK(确认 y+1)。(因服务器可能还有数据要发,需分两次确认)

    13、DNS

    作用:将域名(如www.baidu.com)解析为 IP 地址(如180.101.50.242),方便用户记忆。

    解析流程

    1. 本地主机查询 DNS 缓存,若有则直接返回;
    2. 无缓存则查询本地 DNS 服务器(如路由器);
    3. 本地 DNS 服务器逐级查询根域名服务器→顶级域名服务器(.com)→权威域名服务器,获取 IP 后返回给主机。

    类型:A 记录(域名→IPv4)、AAAA 记录(域名→IPv6)、CNAME 记录(域名别名)。

    14、智能指针

    自动管理动态内存(new分配),避免内存泄漏(忘记delete)。

    unique——ptr独占所有权,不允许拷贝,只能移动(std::move

    shared-ptr共享所有权,通过引用计数管理,计数为 0 时释放内存

    weak_ptr配合shared_ptr使用,不增加引用计数,解决循环引用问题。

    15、虚函数

    实现多态(“一个接口,多种实现”),父类指针可调用子类重写的函数。

    每个包含虚函数的类有一个 “虚函数表(vtable)”,存储虚函数地址;对象包含 “虚表指针(vptr)”,指向类的虚函数表,调用时通过 vptr 找到实际函数

    16、链表

    定义:由节点组成的线性数据结构,节点包含数据和指向下一节点的指针,无需连续内存。

    类型

    • 单链表:每个节点只有 next 指针;
    • 双向链表:节点有 prev 和 next 指针,可双向遍历;
    • 循环链表:尾节点 next 指向头节点,可循环访问。

    优点:插入 / 删除高效(O (1),只需修改指针);

    缺点:随机访问差(O (n),需从头遍历)。

    17、手撕——回文字符串判断

    18、手撕——翻转链表

    #面试问题记录#
    全部评论
    这问的这么多,涉及面还这么广,换我肯定被刷了
    点赞 回复 分享
    发布于 08-29 14:29 陕西

    相关推荐

    11-23 15:14
    中原工学院 Java
    程序员花海_:实习和校招简历正确格式应该是教育背景+实习+项目经历+个人评价 其中项目经历注意要体现业务 实习经历里面的业务更是要自圆其说 简历模板尽可能保持干净整洁 不要太花哨的
    点赞 评论 收藏
    分享
    评论
    点赞
    12
    分享

    创作者周榜

    更多
    牛客网
    牛客网在线编程
    牛客网题解
    牛客企业服务