华勤技术

岗位描述:

1、负责X86/Arm平台Linux驱动开发,OS开发维护。对于Arm产品如OpenBMC也包含Bootloader,Memory、OS定制及维护。

2、负责网络产品、计算产品的驱动及OS架构设计,系统需求设计。应用工具及App开发。

3、负责分解&实现客户的需求,解决测试和客户反馈的问题,确保项目进度按时达成。

岗位要求:

1、熟悉linux或RTOS下底层驱动以及系统开发

2、熟悉操作系统以及编译、链接等基础知识,能熟练应用到debug过,程中,

3、熟练使用各种仪器,调试功能,和调试手段,

4、良好的分析与解决问题能力、学习能力、创新能力和团队合作精神。

首先我觉得这种面试肯定是靠运气。因为他可能现在补录了。所以面试一点技术都没有问。但是你如果是面驱动岗位肯定要会c语言。其次就是你要会一些字符设备驱动或者platform驱动的架构及你要会做过一些这种项目,这就涉及到嵌入式开发,这些东西都是你必须要掌握的。当然面试就是看运气了。

1.自我介绍

面试官您好,我叫林言威,来自西北民族大学电子信息工程专业。非常感谢您给我这次面试的机会。

我很喜欢嵌入式开发,并在校期间积累了丰富的实践经验。我的主要项目经历包括主导开发一款基于AI的智能语音台灯。该项目采用STM32单片机(ARM Cortex-M系列内核)的单片机,集成了光敏、温湿度和超声波等多种传感器,实现了自动调光、坐姿提醒、疲劳监测等多项功能,并支持语音交互和手机远程控制。项目中,我深入掌握了STM32硬件设计、串口通信、PWM控制和多任务开发等关键技术。

此外,我还参与了基于Linux的MQTT智能家居系统开发,使用IMX6ULL(ARM Cortex-A内核)开发板及Linux实时操作系统。

并实现了小程序远程控制功能 。这一经历让我系统掌握了嵌入式Linux开发、驱动开发、MQTT协议移植和多进程/多线程编程。

我的专业技能包括:

  • 熟悉嵌入式Linux应用开发,熟悉系统编程、文件IO、多进程/多线程等技术;
  • 熟练使用STM32等单片机,熟悉寄存器操作、GPIO、UART、IIC等常用接口及总线协议;
  • 具备良好的软硬件协同开发能力和团队协作能力。

我的自我介绍到此结束,谢谢面试官的认真聆听,期待与您的深入交流,也希望能为团队贡献我的力量。

2.主要掌握什么语言(c shell脚本)

我主要掌握C语言和Shell脚本,同时也熟悉C++语言。我熟练运用常用数据结构与算法,比如链表、栈、队列、二分查找和哈希表,并且了解STL库的使用,python 语言。在蓝桥杯省赛中,我也获得了C语言一等奖,我觉得我对这些编程语言还算熟悉。

Python、C(过程)、C++(对象)有什么区别(解释器、编译器、面向过程、面向对象……)

Python、C、C++的区别

  1. 解释器与编译器

    • Python:解释型语言,代码通过解释器逐行执行。
    • **C/C++**:编译型语言,代码先编译成机器码,再执行。
  2. 运行速度

    • Python:运行速度相对较慢,适合快速开发。
    • **C/C++**:运行速度快,适合性能要求高的应用。
  3. 内存管理

    • Python:自动内存管理(垃圾回收)。
    • **C/C++**:手动内存管理,需程序员管理内存。
  4. 面向过程与面向对象

    • Python:支持面向对象编程,也支持函数式编程。
    • C:主要面向过程编程,但支持结构体。
    • **C++**:面向对象编程,支持类、继承、多态等。
  5. 用途

    • Python:适合快速开发、脚本、数据分析、机器学习等。

    • C:适合系统编程、嵌入式开发、性能敏感的应用。

    • **C++**:适合系统编程、游戏开发、高性能应用。

3.用到什么开发软件(答了source insight notepad++ vscode 面试官补充了一个git)

在开发过程中,用到了不同的开发工具和软件来满足不同阶段和需求的开发任务。对于嵌入式项目,我常用 Keil 进行 STM32 等嵌入式项目的开发,同时,我也熟练使用 Linux 下的 GCC 和 GDB,用于嵌入式 Linux 开发,它们帮助我高效完成代码编译和调试。此外,Source Insight 是我用于代码阅读和分析的重要工具,尤其适合大型项目的代码管理和理解;Notepad++ 编辑和查看代码。VSCode 是我日常使用最多的开发工具,它不仅支持多种语言(如 C、C++、Python 和 Shell 脚本),还具备强大的调试功能和丰富的插件生态。

我还学过使用Git进行代码版本控制和代码管理。我也熟悉Makefile,用于自动化编译多文件项目。在图形界面开发方面,我使用QT框架,比如在智能家居系统项目中开发了用户交互界面。这些工具覆盖了从嵌入式到应用开发的全流程,帮助我高效完成开发任务。

4.在项目中遇到的困难以及如何解决带来什么收获( 这个感觉比较重要

项目:灯心智启——基于 AI 技术智能语音台灯的设计与实现

疲劳识别算法方面存在困难

在“灯心智启”智能语音台灯项目中,我遇到过RTC异常复位导致时间丢失的难题。最初,台灯在断电或主控芯片复位后,RTC无法保持准确时间,影响了自动调光等核心功能。

针对这个问题,我首先系统性排查了电路和代码,发现主电源断开时RTC缺乏持续供电是主因。为此,我在硬件上为RTC加装了独立纽扣电池,确保掉电时RTC依然正常运行。同时,在软件层面,优化了RTC初始化流程,通过检测备份寄存器判断是否异常复位,若检测到异常则自动从备份或外部接口恢复时间,确保系统恢复后时间准确。

解决方法

  • 对 模型进行进一步的优化和调整,通过增加训练数据量、调整模型参数等方式,提高模型的准确率。

收获:提高了 问题解决能力 和 相关领域的技术提升 并对技术有了更深入的理解和掌握。

AI 模型训练与移植

K210的模型部署和优化是一个挑战,特别是在有限算力和内存条件下,需要兼顾模型精度与运行效率。为此,我针对实际应用场景,选取了轻量级神经网络结构,并利用K210的硬件加速特性,在K210与STM32主控芯片的数据通信方面,我通过串口协议优化,确保了AI推理结果能够实时反馈到系统控制流程中,有效提升了用户交互体验。

  • 难点描述:项目中涉及到 K210 模型的训练,用于语音交互等功能。AI 模型训练本身需要大量的数据和计算资源,并且要选择合适的算法和模型架构。训练完成后,还需要将模型移植到 STM32 单片机上运行,而单片机的计算能力和存储资源相对有限,这使得模型的优化和移植变得非常困难。
  • 解决方法:在模型训练阶段,可以通过数据增强等技术扩充训练数据集,选择适合嵌入式设备的轻量级神经网络架构,如 TinyML 等。在移植过程中,使用模型量化技术将模型参数从浮点数转换为整数,以减少模型的存储空间和计算量。同时,对模型进行裁剪,去除一些对性能影响不大的层,以适应单片机的资源限制。并且要编写高效的代码来实现模型的推理过程,充分利用单片机的硬件资源,如使用 DMA(直接存储器访问)来加速数据传输。

项目:Linux MQTT 智能家居系统

困难问题描述::

uboot 启动提示找不到设备树文件 无法启动内核 但是直接查看内存卡后看到设备树文件存在 并且在该目录下,并且 在uboot中使用fdt 命令查询设备树都可以查看到

在启动过程中,U-Boot 未能正确加载设备树文件(.dtb),导致内核无法正确识别硬件设备。

解决方法

文件路径问题

  • 解决方法

    • 确保在 U-Boot 中加载设备树文件时使用了正确的路径。例如,如果设备树文件位于内存卡的根目录下,可以使用以下命令加载:

      1
      load mmc 0:1 ${fdt_addr_r} /boot/dtb

      其中,mmc 0:1 表示从第一个 MMC 设备的第一个分区加载文件,${fdt_addr_r} 是设备树文件加载的内存地址。

    • 如果路径中包含特殊字符或空格,确保正确转义或使用引号。

    文件名大小写问题

  • 问题:文件名大小写不匹配。U-Boot 对文件名大小写敏感。

  • 解决方法

    • 确保在 U-Boot 中指定的设备树文件名与实际文件名完全一致,包括大小写。例如,如果文件名是 dtb.dtb,则不能写成 DTB.DTB

环境变量问题

  • 问题:U-Boot 的环境变量可能未正确设置。

  • 解决方法

    • 检查 U-Boot 的环境变量是否正确设置了设备树文件的路径和名称。使用以下命令查看环境变量:

      1
      printenv
    • 如果发现 bootargs 或其他相关变量中缺少设备树文件路径,进行手动设置。例如:

      1
      setenv bootargs ${bootargs} fdt_file=/boot/dtb.dtb

检查启动日志

仔细查看 U-Boot 启动日志,确认设备树文件加载和传递给内核的过程。

示例日志:

1
2
3
4
5
6
U-Boot> boot
...
Loading Kernel from FIT Image at 80000000 ...
Loading Device Tree from FIT Image at 80000000 ...
Booting using the fdt blob at 83000000
...

通过上述步骤,你应该能够解决 U-Boot 启动时找不到设备树文件的问题。

收获

  • 对设备树的理解加深:通过解决这个问题,更加深入地理解了设备树文件的作用以及如何在启动过程中正确加载设备树文件。
  • 调试能力提升:学会了如何在 U-Boot 中进行调试和配置,提升了对 Bootloader 的调试能力。
  • 对启动参数的理解加深:通过解决启动参数问题,更加深入地了解了启动参数的作用以及如何正确传递启动参数。

在Linux MQTT智能家居系统项目中,我遇到的最大困难是

驱动移植和多协议设备的兼容性问题。项目初期,IMX6ULL PRO开发板需要支持多种传感器和外设,但现有驱动与Linux内核版本不完全兼容,导致部分外设无法正常通信,影响了系统的稳定性和实时性。

为解决这一挑战,我首先梳理了设备树配置,结合原理图分析硬件接口,逐步排查驱动加载日志,定位问题根源。随后,我针对性地重写和优化了部分驱动代码,并手动配置GPIO、I2C、PWM等底层参数,确保各类传感器和执行器均能被系统正确识别与控制。同时,针对MQTT协议在Linux下的移植难点,我利用多线程技术和同步机制,提高了消息的实时响应能力。最终,系统实现了通过小程序远程控制,家居环境监测与智能调节功能,整体运行稳定,响应速度提升约40%。

设备树配置

在Linux MQTT智能家居系统项目中,设备树配置是实现各类外设正常工作的关键环节。项目初期,IMX6ULL PRO开发板需要连接多种传感器和执行器,但由于硬件资源分配复杂,设备树节点配置不当会导致驱动无法加载或者资源冲突。

为此,我详细研读了开发板原理图,结合芯片手册梳理每一个外设的GPIO、I2C、PWM等硬件连接关系。在设备树中,逐一配置各外设节点,包括pinctrl子系统的管脚复用、输入子系统的事件映射、lcd显示以及中断资源。每次修改后,我通过dmesg日志和cat /proc/device-tree进行验证,确保驱动能够正确识别和初始化各外设。通过这一系列优化,外设识别率提升至100%,系统稳定性和可扩展性显著增强。

设备树作用

设备树的作用非常关键。设备树本质上是描述硬件资源和连接关系的数据结构,它让操作系统在启动时无需修改内核源码,就能灵活识别和配置不同的外设,比如GPIO、I2C、PWM等。

通过设备树配置,我能够精准地分配硬件资源,避免驱动冲突和资源浪费。例如,在IMX6ULL PRO开发板上,依靠设备树完成了各类传感器和执行器的挂载与初始化,驱动识别效率提升至100%,大大缩短了调试周期。设备树还极大增强了系统的可移植性和扩展性,为后续新增模块提供了便利。

pthread_mutex_lock和pthread_mutex_unlock是Linux多线程编程中常用的互斥锁操作函数。

在我的Linux MQTT智能家居系统项目中,我常用这两个函数来保护多线程对共享资源的访问。pthread_mutex_lock用于加锁,确保当前线程独占访问某一临界区,防止其他线程同时修改数据。操作完成后,调用pthread_mutex_unlock解锁,允许其他线程进入临界区。这样可以有效避免数据竞争和资源冲突。

具体做法是:在访问共享数据(如传感器缓冲区)前,先调用pthread_mutex_lock获取互斥锁,确保当前只有一个线程能操作该数据;操作完成后,立即调用pthread_mutex_unlock释放锁。这样有效防止了数据竞争和异常,提高了系统稳定性。

在每次访问或修改共享数据前,在线程中调用pthread_mutex_lock(&mutex)加锁,确保当前线程独占资源。数据操作完成后,立即调用pthread_mutex_unlock(&mutex)解锁,允许其他线程访问。这样有效防止了数据竞争和异常,系统长时间运行未出现死锁或数据错乱问题。

通过合理使用这两个函数,项目实现了多线程环境下的数据一致性和系统稳定性,系统在长时间运行下稳定率超过99%。未来在贵公司多线程嵌入式开发任务中,我能够熟练运用pthread互斥锁机制,确保系统高效安全运行。

5.简述一下uboot启动流程

第一阶段:ROM code(芯片厂商内置的代码)初始化一些基本的时钟,从选定的设备中去加载FSBL的代码,并启动FSBL第一阶段引导程序代码

第二阶段:FSBL (first stage boot loader) 第一阶段引导程序完成时钟的初始化,初始化DDR,从选定的设备中去加载SSBL第二阶段引导程序的代码,并启动SSBL第二阶段引导程序代码

第三阶段:从外部储存或者网络中加载linux系统,通过启动动画向用户反馈启动过程,启动linux内核

第四阶段:linux内核初始化,挂载根文件系统,启动用户空间的init程序

最后进入到linux用户空间

  1. 时钟设置:配置处理器的时钟和电源管理,确保系统的时钟频率设置正确。

  2. 内存控制器初始化:设置内存控制器,以便能够正确访问SDRAM。

  3. 关闭看门狗:禁用看门狗计时器,防止在引导过程中重置系统。

  4. 关闭中断:禁用所有中断,确保引导过程不会被打断。

  5. 设置栈:初始化处理器的栈指针,为后续的程序执行提供必要的内存空间。

  6. 重定位U-Boot:将U-Boot的代码从非易失性存储器(如NAND或NOR Flash)复制到SDRAM中,这个过程称为重定位。

  7. 清除BSS段:清零所有未初始化的全局变量,为程序的运行提供一个干净的环境。

  8. 硬件设备初始化:初始化串口、网络接口等硬件设备,以便可以与U-Boot进行交互。

  9. 环境变量设置:加载U-Boot的环境变量,这些变量包含了系统启动所需的配置信息。

  10. 加载内核映像:从存储设备中读取操作系统内核映像,并将其加载到SDRAM中。

  11. 设置启动参数:为操作系统内核设置启动参数,这些参数告诉内核硬件的配置信息和启动方式。

  12. 跳转执行内核:最后,U-Boot通过设置处理器的程序计数器(PC)来跳转执行操作系统内核。

5.详细uboot启动流程

首先,在第一阶段,ROM Code(芯片厂商内置的代码)会进行硬件检查、设置基本时钟,并从存储设备(如SPI Flash、eMMC或SD卡)加载第一阶段引导程序FSBL(First Stage Boot Loader)到内存中运行。接着,FSBL负责初始化硬件,包括初始化内存控制器(如DDR)、配置更精确的时钟、禁用看门狗计时器和中断,初始化处理器的栈指针,将U-Boot代码从非易失性存储器重定位到SDRAM中,清零未初始化的全局变量(BSS段),并加载第二阶段引导程序SSBL到内存中运行。在第三阶段,SSBL进一步初始化硬件设备(如串口、网络接口),加载U-Boot的环境变量,从存储设备或网络加载Linux内核映像到SDRAM中,设置启动参数,并可能显示启动动画,最后通过设置处理器的程序计数器跳转执行操作系统内核。进入第四阶段,Linux内核初始化操作系统的核心功能,检测和初始化硬件设备,挂载根文件系统(如ext4、initramfs),并启动用户空间的init程序(如systemdinit),负责启动其他系统服务和程序。最终,计算机进入Linux用户空间,启动用户界面(如图形用户界面或命令行界面),用户可以打开各种应用程序,进行日常操作。整个启动过程环环相扣,确保了计算机能够顺利启动并为用户提供服务。;

10、你能列举一个你最熟悉的协议吗?

I2C协议是一种简单、低速的同步串行通信协议,主要用于连接低速外设,如传感器和存储器。它通过两根线(SDA数据线和SCL时钟线)实现通信,支持多主多从架构,每个从设备都有唯一地址。通信过程包括启动信号、发送设备地址、数据传输和停止信号。I2C协议广泛应用于嵌入式系统,例如连接温湿度传感器、EEPROM或实时时钟等设备。我曾在项目中通过STM32微控制器使用I2C协议读取传感器数据,其简单性和可靠性非常适合低速通信需求。

6.主要用到什么通信协议: I2C UART SPI 简述一下I2C的通信特点以及时序

1. 主要用到的通信协议

1.I2C(Inter-Integrated Circuit)

  • 用途:用于连接低速外设,如传感器、EEPROM等。
  • 特点
    • 多主多从:支持多个主设备和多个从设备。
    • 两线制:使用两条线(SDA和SCL)进行通信,SDA为数据线,SCL为时钟线。
    • 地址寻址:每个从设备都有唯一的地址,主设备通过地址来选择特定的从设备。
    • 速率:标准速率100 kbps,快速速率400 kbps,高速速率3.4 Mbps。
    • 简单:协议简单,适合低速通信。

2.UART(Universal Asynchronous Receiver/Transmitter)

  • 用途:用于串行通信,常用于设备之间的数据传输,如调试接口。
  • 特点
    • 异步通信:不使用时钟线,通过起始位和停止位来同步数据。
    • 单向通信:通常使用两条线(TX和RX)进行全双工通信。
    • 波特率:通信速率可配置,常见的波特率有9600、115200等。
    • 简单:协议简单,适合长距离通信。

3.SPI(Serial Peripheral Interface)

  • 用途:用于高速通信,常用于连接存储器、传感器等。
  • 特点
    • 主从模式:通常有一个主设备和多个从设备。
    • 四线制:使用四条线(SCLK、MOSI、MISO、CS)进行通信。
    • 高速:速率可达几Mbps甚至更高。
    • 简单:协议简单,适合高速通信。

4.CAN(Controller Area Network)

  • 用途:广泛应用于汽车电子、工业自动化等领域。
  • 特点
    • 多节点通信:支持多个设备以总线型拓扑结构连接。
    • 高可靠性:具有强大的错误检测和仲裁机制。
    • 差分信号:使用两条差分信号线(CAN_H和CAN_L),抗干扰能力强。
    • 速率:最高可达1 Mbps。
    • 适用于高噪声环境:适合工业自动化和汽车电子系统。

I2C通信特点及简要时序

I2C是一种两线制通信协议,使用SDA(数据线)和SCL(时钟线)进行通信。它支持多主多从,每个从设备通过唯一的地址进行识别。I2C协议简单,适合低速通信,标准速率为100 kbps,快速速率为400 kbps,高速速率为3.4 Mbps。

其通信时序包括起始条件(SCL为高电平时,SDA从高电平变为低电平)、停止条件(SCL为高电平时,SDA从低电平变为高电平),以及数据传输(每个字节包含8位数据,从最高位开始传输,每个字节后有一个应答位)。

UART通信特点及简要时序

UART是一种异步通信协议,通常使用两条线(TX和RX)进行全双工通信。它不使用时钟线,通过起始位和停止位来同步数据。UART通信速率可配置,常见的波特率有9600、115200等。

其通信时序简单,数据帧由起始位、数据位(通常8位)、可选的奇偶校验位和停止位组成。

SPI通信特点及简要时序

SPI是一种四线制的通信协议,使用SCLK(时钟线)、MOSI(主设备数据输出)、MISO(主设备数据输入)和CS(片选线)。SPI协议简单,适合高速通信,速率可达几Mbps甚至更高。

其通信时序包括主设备提供时钟信号,数据在时钟的上升沿或下降沿被采样,具体取决于通信模式(SPI有四种模式,分别对应不同的时钟极性和相位)。

CAN通信特点及简要时序

CAN是一种多节点通信协议,广泛应用于汽车电子和工业自动化中。它使用两条差分信号线(CAN_H和CAN_L),具有强大的抗干扰能力和错误检测机制。CAN通信速率最高可达1 Mbps。

其通信时序包括帧头(包含标识符和控制信息)、数据段(可变长度,最大8字节)和校验段(CRC校验)。CAN协议通过仲裁机制确保在多个设备同时发送数据时不会发生冲突。

1 给我介绍下spi i2c

1. SPI(Serial Peripheral Interface,串行外设接口)

基本特点

  • 全双工通信(数据可以同时双向传输)
  • 主从模式(一个主设备,多个从设备)
  • 通常有4根线:
    • MOSI(主输出从输入,Master Out Slave In)
    • MISO(主输入从输出,Master In Slave Out)
    • SCLK(时钟信号,Serial Clock)
    • SS/CS(从设备选择,Slave Select/Chip Select)

优点

  • 速度快(10Mbps甚至更高)
  • 协议简单,硬件实现容易
  • 支持多从设备

缺点

  • 需要较多的引脚(每个从设备都需要一个独立的CS线)
  • 没有规范的应答机制(ACK)

应用场景

  • SD卡、Flash存储器、显示屏、传感器等

2. I²C(Inter-Integrated Circuit,集成电路间总线)

基本特点

  • 半双工通信(数据只能单向传输)
  • 多主多从(可以有多个主设备和多个从设备)
  • 只需要2根线
    • SDA(数据线,Serial Data)
    • SCL(时钟线,Serial Clock)

优点

  • 只需两根信号线,节省引脚
  • 支持多个设备挂在同一总线上
  • 有应答机制,通信更可靠

缺点

  • 速度较低(标准模式100kbps,快速模式400kbps,高速模式3.4Mbps)
  • 总线长度和设备数量有限(电容影响信号完整性)

应用场景

  • 温湿度传感器、EEPROM、实时时钟等

SPI 是一种全双工的串行通信协议,通常用于高速通信场景。它使用四根线:SCLK(时钟线)、MOSI(主设备数据输出)、MISO(主设备数据输入)和CS(片选线)。SPI 支持一个主机连接多个从机,通过片选信号来选择当前通信的从机。它的优点是数据传输速度快,适合与存储器、显示屏等设备通信。

I2C 是一种半双工的串行通信协议,通常用于低速通信场景。它只需要两根线:SDA(数据线)和SCL(时钟线)。I2C 支持多主多从架构,通过设备地址来区分不同的设备。它的优点是引脚需求少,适合空间受限的环境,常用于与传感器、EEPROM 等设备通信。

2 i2c的速率有几种,帧的组成,仲裁方法

I2C速率:I2C协议定义了多种速率标准:

  • 标准速率(Standard-mode):最高100 kbps。
  • 快速速率(Fast-mode):最高400 kbps。
  • 快速加速率(Fast-mode Plus):最高1 Mbps。
  • 高速速率(High-speed mode):最高3.4 Mbps。
  • 超速速率(Ultra Fast-mode):最高5 Mbps。

不同速率适用于不同的应用场景,速率越高,对硬件和信号完整性的要求也越高。


I2C帧组成:I2C通信的基本单位是帧,一个完整的帧包括以下部分:

  1. 起始位(Start Condition):SCL为高电平时,SDA从高电平变为低电平。
  2. 数据位(Data Bits):每个字节包含8位数据,从最高位(MSB)开始传输。
  3. 应答位(Acknowledge Bit):每个字节传输后,接收方发送一个应答位,低电平表示应答(ACK),高电平表示不应答(NACK)。
  4. 停止位(Stop Condition):SCL为高电平时,SDA从低电平变为高电平。

I2C仲裁方法:当多个主机同时尝试控制总线时,I2C采用位仲裁机制

  • 在SCL时钟信号为高电平时,如果某个主机检测到SDA线上的电平与其预期发送的电平不一致,则该主机会放弃总线控制权,进入从机模式。
  • 仲裁基于SDA线的电平状态,确保只有一个主机能够成功控制总线,避免数据冲突。

3 spi的4种模式,这些模式有啥区别

  1. 模式0(CPOL=0, CPHA=0):时钟空闲为低,数据在上升沿采样。
  2. 模式1(CPOL=0, CPHA=1):时钟空闲为低,数据在下降沿采样。
  3. 模式2(CPOL=1, CPHA=0):时钟空闲为高,数据在下降沿采样。
  4. 模式3(CPOL=1, CPHA=1):时钟空闲为高,数据在上升沿采样。

区别:主要在于时钟的空闲电平和数据采样的时钟边沿。主从设备必须配置为相同模式,以确保通信正常。

4 用过实时操作系统吗,介绍下启动流程

用过实时操作系统。以常见的RTOS(如FreeRTOS)为例,其启动流程通常包括以下几个关键步骤:

  1. 硬件初始化

    • 在系统启动时,首先进行硬件初始化,包括设置时钟、初始化外设(如GPIO、UART等)和配置中断控制器。
  2. 内核初始化

    • RTOS内核初始化,包括任务调度器、内存管理模块等。例如,FreeRTOS会初始化任务调度器,设置初始任务列表。
  3. 创建初始任务

    • 创建并初始化系统运行所需的初始任务。这些任务通常包括一些后台服务任务和用户定义的任务。
  4. 启动调度器

    • 调度器开始运行,根据任务的优先级和状态进行调度,使系统进入多任务运行状态。
  5. 任务执行

    • 各任务根据调度器的调度,开始执行各自的功能,系统进入稳定运行状态。

    RTOS的启动流程主要包括硬件初始化、内核初始化、创建初始任务、启动调度器和任务执行。这个过程确保系统从硬件启动到多任务运行的平稳过渡。

1、请问I2C协议你有什么了解

回答的很表面,只是说这是一种板间通信的协议,速度如何,优势在哪里等等。。

  • 两线制:使用SDA(数据线)和SCL(时钟线)进行通信。
  • 多主多从:支持多个主设备和多个从设备在同一总线上通信。
  • 速率:标准速率100 kbps,快速速率400 kbps,快速加速率1 Mbps,高速速率3.4 Mbps,超速速率5 Mbps。
  • 帧结构:包括起始位、数据位、应答位和停止位。
  • 仲裁:通过位仲裁机制解决多个主设备同时控制总线的问题。

2、那I2C里面的SDA和SCL是如何进行通信的,主从模式之间地址如何配置等等?

SDA和SCL通信机制

  • SDA(数据线):用于传输数据和地址信息,是双向的,通过上拉电阻保持高电平,设备通过拉低SDA线来传输数据。
  • SCL(时钟线):由主设备控制,用于同步数据传输的时钟信号,确保数据在SCL的高电平期间保持稳定。

通信过程

  • 开始信号:SCL为高电平时,SDA从高电平变为低电平,表示通信开始。
  • 结束信号:SCL为高电平时,SDA从低电平变为高电平,表示通信结束。
  • 数据传输:每个字节传输后,接收方发送一个应答信号(ACK),表示数据已成功接收。

主从模式

  • 主设备:控制SCL时钟线,发起通信,发送地址和数据。
  • 从设备:根据主设备发送的地址,响应通信请求,发送或接收数据。
  • 地址配置:每个从设备都有一个唯一的地址(通常是7位或10位),主设备通过发送地址来选择特定的从设备。

多主设备支持

  • I2C总线允许多个主设备共享同一总线,但一次只允许一个主设备控制总线。

3、I2C协议的数据格式如何,什么时候是数据的起始,什么时候是数据的结束

数据格式

I2C协议的数据传输是按字节进行的,每个字节包含8位数据,从最高位(MSB)开始传输。数据传输的基本单位是一个字节,每个字节传输后,接收方需要发送一个应答位(ACK)或非应答位(NACK)。

起始和结束标志

  • 起始条件
    • 当SCL线为高电平时,SDA线从高电平变为低电平,表示通信开始。
    • 这个信号由主设备发起,用于通知总线上的所有设备通信即将开始。
  • 结束条件
    • 当SCL线为高电平时,SDA线从低电平变为高电平,表示通信结束。
    • 这个信号由主设备发起,用于通知总线上的所有设备通信已经结束。

数据传输过程

  1. 起始条件:主设备拉低SDA线,开始通信。
  2. 发送地址:主设备发送一个字节的地址,包括设备地址和读写位。
  3. 应答位:从设备发送ACK或NACK。
  4. 数据传输:主设备发送或接收数据字节,每个字节后都有一个应答位。
  5. 结束条件:主设备拉高SDA线,结束通信。

针对I2C、SPI和UART三种常用通信接口,我有如下速率配置和优化经验

  • I2C速率:在“灯心智启”项目中,I2C主要用于连接温湿度、光敏等传感器,常用速率为100kHz(标准模式)和400kHz(快速模式),实际应用中多选择400kHz以提升数据采集效率,通信延迟降低约25%。
  • SPI速率:SPI用于STM32与K210等模块的高速数据交互,实际设置为8MHz,能够满足AI模型推理和多传感器协同需求,数据传输效率提升约30%。STM32平台下SPI最高可支持到18MHz以上。
  • UART速率:在台灯和智能家居系统中,UART主要用于模块间调试和数据传输,常用波特率为115200bps,部分场景可配置到4.5Mbps,满足大部分实时通信需求。

5 线程进程的区别

线程进程的主要区别:

  • 资源:进程有独立内存空间,线程共享进程内存。
  • 开销:线程创建和切换快,进程开销大。
  • 通信:线程通信快(共享内存),进程通信慢(需IPC)。
  • 调度:线程是调度单位,切换快;进程切换慢。
  • 独立性:进程独立,崩溃不影响其他进程;线程崩溃可能影响整个进程。

6 freertos 的信号传递有哪些方法

FreeRTOS 提供了五种主要的信号传递方法,分别是队列、信号量、互斥量、事件组和任务通知

1. 队列(Queue)

  • 特点:队列是一种先进先出(FIFO)的数据结构,用于任务与任务、任务与中断之间的通信。
  • 适用场景:适用于需要传递数据的情况,可以存储多个数据项。
  • 示例:任务间传输传感器值、指令等。

2. 信号量(Semaphore)

  • 特点:信号量用于任务同步,不承载数据。FreeRTOS 中的信号量分为二值信号量和计数型信号量。
  • 适用场景:适用于事件通知、任务同步。
  • 示例:中断触发任务启动。

3. 互斥量(Mutex)

  • 特点:互斥量用于保护临界资源,确保同一时间只有一个任务可以访问。
  • 适用场景:适用于保护共享资源。

4. 事件组(Event Group)

  • 特点:事件组可以组合多个事件标志,允许任务等待多个事件中的任意一个或多个。
  • 适用场景:适用于任务需要与多个事件同步的场景。

5. 任务通知(Task Notification)

  • 特点:任务通知是一种轻量级的通信机制,每个任务有一个32位的通知值,可以在任务之间或中断中更新和读取。
  • 适用场景:适用于快速事件触发、中断触发事件通知。

LED 灯驱动程序详细编写

线程间通讯方式,死锁概念

线程间通讯方式

  • 共享内存:线程共享同一进程的内存空间,通过访问共享变量进行通信。需用互斥锁保护临界区。
  • 消息队列:线程间通过消息队列发送和接收消息,实现通信。
  • 信号量:用于线程同步,控制对共享资源的访问。
  • 事件:线程通过等待和触发事件进行同步。
  • 管道:线程间通过管道进行数据传输。

死锁概念

  • 定义:多个线程因相互等待对方持有的资源而无法继续执行的状态。
  • 产生条件
    1. 互斥条件:资源不能同时被多个线程使用。
    2. 请求与保持条件:线程已持有资源,又请求其他资源。
    3. 不可剥夺条件:线程持有的资源不能被强制剥夺。
    4. 循环等待条件:存在一个线程等待资源的循环链。

2.介绍一下i2c

I2C(Inter-Integrated Circuit)是一种半双工、同步串行通信协议,主要用于微控制器和低速外围设备之间的通信。以下是I2C的关键特点:

  • 两线制:使用两条线进行通信,分别是SDA(数据线)和SCL(时钟线)。
  • 多主多从:支持多个主设备和多个从设备在同一总线上通信,通过设备地址区分。
  • 速率:标准速率100 kbps,快速速率400 kbps,快速加速率1 Mbps,高速速率3.4 Mbps,超速速率5 Mbps。
  • 帧结构:包括起始位、数据位、应答位和停止位。
  • 仲裁:通过位仲裁机制解决多个主设备同时控制总线的问题.

3.介绍一下中断

中断是一种机制,允许硬件设备在特定事件发生时通知处理器暂停当前任务,转而执行特定的处理程序(中断服务例程,ISR)。以下是中断的关键特点:

  • 触发条件:硬件设备(如传感器、定时器等)在特定事件发生时(如数据接收完成、定时器溢出等)触发中断信号。
  • 中断信号:硬件设备通过中断引脚向处理器发送信号。
  • 中断处理:处理器暂停当前任务,保存上下文,切换到中断服务例程(ISR)执行。5
  • 中断优先级:多个中断同时发生时,处理器根据优先级选择处理。
  • 中断返回:ISR执行完毕后,处理器恢复上下文,继续执行原任务。

7.项目学到什么新兴的技术

1. 物联网通信协议(MQTT)

  • MQTT协议:MQTT是一种轻量级的消息传输协议,特别适合物联网设备的通信。它支持低带宽、高延迟或不可靠的网络环境,具有高可靠性和低功耗的特点。在项目中,你通过MQTT协议实现了设备与云平台之间的高效通信,包括数据上传和指令接收。
  • 应用场景:MQTT广泛应用于智能家居、工业物联网和车联网等领域。你将MQTT应用于智能家居设备的通信,为后续的智能家居设备互联互通和智能化管理奠定了基础。

2. 前后端分离架构(JsonRPC)

  • JsonRPC:JsonRPC是一种基于JSON格式的远程过程调用(RPC)协议。在项目中,你通过JsonRPC实现了前后台程序的分离,前台程序负责用户界面,后台程序负责硬件操作和业务逻辑。
  • 优势:这种架构降低了前后台程序的耦合度,便于独立开发、维护和扩展。例如,当硬件更换或界面调整时,只需修改对应的部分,无需改动另一部分。

3. 嵌入式Linux开发

  • 驱动开发:你成功移植并实现了多种外设(如DHT11温湿度传感器、SR501红外人体感应器等)的Linux驱动程序。这涉及到对硬件资源的精确管理和外设的正确识别。
  • 设备树配置:通过对设备树(Device Tree)的配置,确保了硬件资源的有效管理。
  • 系统调试与优化:你使用了日志记录、断点调试和网络抓包等方法进行系统调试。同时,通过代码优化和硬件优化提高了系统的性能。

4. 图形用户界面开发(Qt框架)

  • Qt框架:你使用Qt框架开发了用于设备控制和状态显示的图形用户界面,并成功移植到ARM架构的开发板上运行。Qt框架提供了丰富的组件和功能,支持动态交互。
  • 界面设计与实现:通过Qt Designer设计界面布局,并通过代码实现控件的事件处理和数据绑定。

5. 多线程与同步机制

  • 多线程:你实现了多任务间的同步与互斥机制,确保了多线程操作的一致性和稳定性。这在嵌入式系统中非常重要,尤其是在处理多个外设和任务时。
  • 线程管理:你使用了pthread库来管理线程,并确保线程安全。

6. 网络编程

  • Socket编程:你使用了socket函数创建套接字,并通过bind、listen、accept和connect等函数实现了网络通信。这为前后台程序的通信提供了基础。
  • TCP/UDP协议:你理解并应用了TCP和UDP协议的特点,选择了适合项目需求的传输方式。

7. 配置文件处理

  • 配置文件格式:你学习了INI、JSON和XML等配置文件格式,并理解了它们在项目中的作用。配置文件用于存储程序运行时需要的参数,便于程序的维护和升级。

8. 云平台对接

  • 阿里云服务器:你通过MQTT协议实现了设备与阿里云服务器之间的数据交换。这为设备的远程控制和数据管理提供了支持。
  • 网页端交互界面:你开发了网页端交互界面,支持远程控制家居自动化模块。这使得用户可以通过任何联网设备轻松管理家庭环境。

9. 智能家居设备控制协议

  • 自定义协议:你自主设计并实现了一套完整的智能家居设备控制协议。这确保了不同设备之间的兼容性和互操作性,为后续产品的升级和扩展提供了便利。

8.Frtos rtthread线程带来的好处

FreeRTOS 线程带来的好处

  1. 提高系统响应速度
    • 多任务并发处理:FreeRTOS 支持多任务并发运行,每个任务可以独立执行不同功能。例如,在智能家居系统中,一个任务读取温湿度传感器数据,另一个任务控制电机,通过合理分配任务优先级,高优先级任务可以快速响应外部事件,从而提高系统响应速度。
    • 任务调度灵活性:FreeRTOS 提供抢占式调度和轮询调度算法。抢占式调度允许高优先级任务打断低优先级任务,确保关键任务能够及时处理,例如在工业自动化中,紧急故障处理任务可以立即抢占 CPU 资源。
  2. 增强系统可靠性
    • 任务隔离与保护:每个任务在 FreeRTOS 中有独立的堆栈空间和运行上下文,任务之间相互隔离。即使一个任务出现异常,也不会影响其他任务的正常运行,例如在医疗设备中,数据采集任务和用户界面任务相互独立,增强了系统的可靠性。
    • 错误处理机制:FreeRTOS 提供任务挂起、删除和系统重启等错误处理机制,可以及时处理任务错误,避免系统崩溃。
  3. 优化资源利用
    • 动态内存管理:FreeRTOS 提供多种动态内存分配策略,可以根据任务需求动态分配和释放内存,例如在视频监控系统中,根据视频数据的分辨率动态调整内存分配。
    • 任务优先级调整:可以根据系统负载动态调整任务优先级,确保关键任务获得足够的 CPU 时间片,例如在多用户系统中,根据任务负载调整优先级,保证系统整体性能。
  4. 简化开发流程
    • 任务封装与复用:FreeRTOS 允许将功能封装成独立任务,便于代码模块化设计和复用,例如在智能交通系统中,将车辆检测、信号灯控制等功能封装成独立任务。
    • 开发工具支持:FreeRTOS 提供任务状态查看、堆栈溢出检测和任务切换跟踪等工具,帮助开发者快速定位和解决问题,提高开发效率。

RT-Thread 线程带来的好处

  1. 提高系统实时性
    • 微秒级任务调度:RT-Thread 支持微秒级任务调度精度,能够快速响应外部中断和事件,例如在高精度仪器设备中,确保传感器数据的实时采集和处理。
    • 中断优先级管理:RT-Thread 提供中断优先级管理机制,确保高优先级中断能够优先处理,例如在通信设备中,紧急数据包可以快速打断当前任务进行处理。
  2. 增强系统稳定性
    • 内核保护机制:RT-Thread 内核提供内存保护单元(MPU)支持和任务优先级保护,防止任务之间的非法访问和资源冲突,提高系统稳定性。
    • 系统自检与恢复:RT-Thread 可以定期检查系统状态,检测到异常时自动重启或恢复到正常状态,例如在无人飞行器控制系统中,确保飞行安全。
  3. 优化系统性能
    • 轻量级线程切换:RT-Thread 的线程切换开销小,切换速度快,有效提高系统运行效率,例如在多任务处理的嵌入式系统中,频繁的任务切换不会导致性能下降。
    • 资源动态分配与回收:RT-Thread 提供动态内存分配和回收机制,根据任务需求动态调整资源分配,例如在智能穿戴设备中,根据用户切换的功能模块动态调整资源。
  4. 简化开发与维护
    • 组件化开发模式:RT-Thread 采用组件化开发模式,将功能模块封装成独立组件,便于开发和维护,例如在物联网设备开发中,将传感器驱动、网络通信和数据处理等功能封装成组件。
    • 丰富的开发工具:RT-Thread 提供图形化配置工具、调试器和性能分析工具,帮助开发者快速开发和优化系统。

最大的区别在于 FreeRTOS 的轻量级和模块化设计,适合资源受限和功能简单的嵌入式设备;而 RT-Thread 的组件化和微内核架构,适合功能复杂、需要支持多种组件的复杂应用场景。

9.使用信号量主要是什么类型

  1. 二进制信号量(Binary Semaphore)
    也叫互斥锁(Mutex),值只有0和1,主要用于互斥,确保一次只有一个线程可以访问共享资源。
  2. 计数信号量(Counting Semaphore)
    值可以是任意非负整数,用于控制多个线程对有限资源的访问,比如限制同时访问某个资源的线程数量。
  3. 命名信号量(Named Semaphore)
    可以在不同进程之间共享,通过文件系统路径名来标识,用于进程间同步。
  4. 匿名信号量(Anonymous Semaphore)
    只能在同一个进程内的线程之间使用,通常通过内存分配创建,用于线程间同步。
  5. 信号量集(Semaphore Set)
    是一组信号量的集合,可以同时操作多个信号量,适用于更复杂的同步场景。

10.了解原子操作吗 主要用在哪里 有什么好处

了解原子操作。原子操作是指在执行过程中不会被其他线程或进程打断的操作,它要么完全执行,要么完全不执行。

主要用途:

  1. 线程安全的变量更新:当多个线程需要对同一个变量进行读写操作时,原子操作可以确保变量的更新是安全的,不会出现数据竞争问题。
  2. 实现锁机制:原子操作常用于实现互斥锁(Mutex)、自旋锁(Spinlock)等同步机制,确保临界区代码的互斥执行。
  3. 无锁编程:在某些高性能场景下,原子操作可以用于实现无锁数据结构,避免锁的开销,提高系统性能。

好处:

  1. 线程安全:原子操作确保了在多线程环境下对共享变量的操作是安全的,不会出现数据不一致的问题。
  2. 性能优化:相比传统的锁机制,原子操作通常更轻量级,不会引入线程切换的开销,适合对性能要求较高的场景。
  3. 简化代码:使用原子操作可以减少锁的使用,使代码更加简洁,同时降低死锁等并发问题的风险。

11.信号量使用过程有什么问题 自旋锁 互斥锁(面试官补充全局变量会常用到 )

信号量、自旋锁和互斥锁都是线程同步机制,但在使用过程中需要注意一些问题,尤其是在涉及全局变量的场景中。

信号量使用过程中的问题

  1. 死锁风险:如果信号量的使用不当,比如忘记释放信号量或者释放顺序错误,可能会导致死锁。例如,多个线程试图获取同一个信号量,但信号量的数量不足以满足所有线程的需求,可能会导致部分线程永远等待。
  2. 性能问题:信号量的使用可能会导致线程阻塞,尤其是在高并发场景下,线程的频繁阻塞和唤醒会增加系统开销。
  3. 初始化问题:信号量的初始值必须正确设置,否则可能会导致线程饥饿或资源竞争问题。
  4. 复杂性:信号量的使用需要仔细设计,尤其是在涉及多个线程和多个资源的场景中,逻辑可能会变得复杂。

自旋锁和互斥锁的优缺点

自旋锁(Spinlock)

  • 优点
    • 低延迟:适用于锁持有时间非常短的场景。自旋锁不会导致线程切换,因此在锁竞争不激烈时可以快速获取锁。
    • 简单高效:实现相对简单,适合快速同步。
  • 缺点
    • 高CPU占用:如果锁竞争激烈,线程会不断自旋,占用大量CPU资源,导致系统性能下降。
    • 不适合长时间锁持有:如果锁持有时间较长,自旋锁会导致其他线程长时间等待,浪费CPU资源。

互斥锁(Mutex)

  • 优点
    • 公平性:互斥锁会将等待的线程放入等待队列,按照先来后到的顺序获取锁,避免了线程饥饿。
    • 适合长时间锁持有:适用于锁持有时间较长的场景,不会像自旋锁那样浪费CPU资源。
  • 缺点
    • 线程切换开销:当线程获取或释放互斥锁时,可能会导致线程切换,增加系统开销。
    • 性能问题:在高并发场景下,互斥锁的性能可能不如自旋锁,尤其是在锁竞争激烈的情况下。

全局变量的场景

在涉及全局变量的场景中,线程同步机制的选择尤为重要。全局变量通常会被多个线程访问和修改,如果没有适当的同步机制,可能会导致数据竞争和数据不一致的问题。

  • 信号量:可以用于控制多个线程对全局变量的访问,但需要注意死锁和性能问题。
  • 自旋锁:适用于全局变量访问频率高且锁持有时间非常短的场景,但要注意避免CPU资源浪费。
  • 互斥锁:适用于全局变量访问频率高且锁持有时间较长的场景,可以有效避免线程饥饿问题,但要注意线程切换的开销。

总结: 在实际开发中,选择合适的同步机制需要根据具体场景来决定。如果全局变量的访问频率高且锁持有时间非常短,可以考虑使用自旋锁;如果锁持有时间较长,或者需要保证线程的公平性,互斥锁可能是更好的选择。信号量则适用于需要控制多个线程对有限资源访问的场景,但在使用时需要注意初始化值和操作的正确性。

12.主要用的是阻塞还是非阻塞

信号量在使用过程中可能会遇到一些问题,比如如果信号量的初始化值设置不当,可能会导致线程饥饿或死锁。此外,信号量的操作必须成对出现,否则可能会出现资源泄漏或逻辑错误。在高并发场景下,信号量的性能可能不如一些更轻量级的同步机制。

对于自旋锁和互斥锁,它们在全局变量的场景中通常使用阻塞操作。具体来说:

  1. 互斥锁(Mutex)
    • 特点:互斥锁是一种阻塞锁,当一个线程获取锁后,其他线程会被阻塞,直到锁被释放。
    • 适用场景:适用于需要保护全局变量或其他共享资源的场景,尤其是当锁持有时间较长时。
    • 优点:可以有效防止数据竞争,确保线程安全。
    • 缺点:可能会导致线程切换的开销,尤其是在高并发场景下。
  2. 自旋锁(Spinlock)
    • 特点:自旋锁是一种非阻塞锁,线程在尝试获取锁时会不断自旋,直到锁被释放。
    • 适用场景:适用于锁持有时间非常短的场景,比如对全局变量进行快速读写操作。
    • 优点:可以减少线程切换的开销,提高系统性能。
    • 缺点:如果锁竞争激烈,线程会不断占用CPU资源,导致CPU利用率过高。

东莞华勤技术驱动开发二面面经

8.你觉得你的项目难点是什么

AI 模型训练与移植

  • 难点描述:项目中涉及到 K210 模型的训练,用于语音交互等功能。AI 模型训练本身需要大量的数据和计算资源,并且要选择合适的算法和模型架构。训练完成后,还需要将模型移植到 STM32 单片机上运行,而单片机的计算能力和存储资源相对有限,这使得模型的优化和移植变得非常困难。
  • 解决方法:在模型训练阶段,可以通过数据增强等技术扩充训练数据集,选择适合嵌入式设备的轻量级神经网络架构,如 TinyML 等。在移植过程中,使用模型量化技术将模型参数从浮点数转换为整数,以减少模型的存储空间和计算量。同时,对模型进行裁剪,去除一些对性能影响不大的层,以适应单片机的资源限制。并且要编写高效的代码来实现模型的推理过程,充分利用单片机的硬件资源,如使用 DMA(直接存储器访问)来加速数据传输。

Linux MQTT 智能家居系统

(一)驱动开发与设备树配置

  • 难点描述:项目需要移植和开发多种外设的 Linux 驱动程序,如 DHT11 温湿度传感器、SR501 红外人体感应器等。这些外设的硬件接口和通信协议各不相同,而且 Linux 驱动开发涉及到内核代码,需要深入理解 Linux 内核的机制。同时,设备树(Device Tree)的配置也非常关键,它用于描述硬件设备的连接关系和资源分配,如果配置不正确,外设将无法被系统正确识别和管理。
  • 解决方法:在驱动开发方面,需要仔细阅读外设的数据手册,了解其通信协议和硬件接口特性。通过阅读 Linux 内核源码中相关的驱动框架代码,学习如何编写符合 Linux 内核规范的驱动程序。对于设备树配置,要深入学习设备树的语法和规范,参考已有的设备树示例,结合硬件电路图,准确地描述每个外设的连接关系和资源分配。在开发过程中,使用调试工具(如 GDB)和日志记录来排查驱动开发和设备树配置过程中出现的问题。

(二)前后台分离架构的实现与通信

  • 难点描述:项目采用 JsonRPC 实现前后台分离的架构。前台程序负责图形用户界面(GUI)的显示和用户交互,后台程序负责处理硬件操作和业务逻辑。前后台程序通过网络通信(TCP/UDP)进行数据交换,这种架构虽然有诸多优点,但在实现过程中需要解决通信的稳定性、数据传输的效率以及前后台程序之间的同步等问题。例如,当用户在前台界面发送控制指令时,后台程序需要及时响应并执行相应的操作,并且要将操作结果反馈给前台界面。
  • 解决方法:在通信方面,要确保网络连接的稳定性,可以通过设置心跳机制来检测网络连接状态。对于数据传输效率,优化 JsonRPC 的消息格式,减少不必要的数据传输。在前后台同步方面,使用多线程同步机制(如互斥锁、信号量等)来确保数据的一致性。同时,要编写详细的接口文档,明确前后台程序之间的接口规范,以便前后台程序的开发人员能够更好地协作。

9.linux启动过程

  • BIOS/UEFI 启动:BIOS 或 UEFI 负责硬件初始化和自检,并加载引导程序(如 GRUB)。
  • 引导程序(Bootloader):GRUB 会显示启动菜单,加载 Linux 内核和初始化内存文件(initrdinitramfs)到内存中,并将控制权移交给内核。
  • 内核初始化:内核会初始化硬件设备、加载驱动程序,并启动用户空间的初始化进程(如 systemd/sbin/init)。
  • 用户空间初始化systemd 会根据配置文件启动系统服务,包括网络、文件系统挂载、用户登录管理等。
  • 用户登录:用户通过图形界面或终端登录系统,开始使用。

首先,在第一阶段,ROM Code(芯片厂商内置的代码)会进行硬件检查、设置基本时钟,并从存储设备(如SPI Flash、eMMC或SD卡)加载第一阶段引导程序FSBL(First Stage Boot Loader)到内存中运行。接着,FSBL负责初始化硬件,包括初始化内存控制器(如DDR)、配置更精确的时钟、禁用看门狗计时器和中断,初始化处理器的栈指针,将U-Boot代码从非易失性存储器重定位到SDRAM中,清零未初始化的全局变量(BSS段),并加载第二阶段引导程序SSBL到内存中运行。在第三阶段,SSBL进一步初始化硬件设备(如串口、网络接口),加载U-Boot的环境变量,从存储设备或网络加载Linux内核映像到SDRAM中,设置启动参数,并可能显示启动动画,最后通过设置处理器的程序计数器跳转执行操作系统内核。进入第四阶段,Linux内核初始化操作系统的核心功能,检测和初始化硬件设备,挂载根文件系统(如ext4、initramfs),并启动用户空间的init程序(如systemdinit),负责启动其他系统服务和程序。最终,计算机进入Linux用户空间,启动用户界面(如图形用户界面或命令行界面),用户可以打开各种应用程序,进行日常操作。整个启动过程环环相扣,确保了计算机能够顺利启动并为用户提供服务。

const的作用

const 关键字在 C++ 中有以下几个主要作用:

  1. 声明常量:使变量的值在初始化后不可更改。

    1
    const int MAX_SIZE = 100;
  2. 修饰函数参数:保证函数不会修改传入的参数。

    1
    void print(const std::string& str);
  3. 修饰函数返回值:保证返回值不会被修改。

    1
    const std::string getError() const;
  4. 修饰类成员函数:保证成员函数不会修改对象的状态。

    1
    2
    3
    4
    class MyClass {
    public:
    void print() const;
    };
  5. 修饰指针:可以修饰指针本身或指针所指向的内容。

    1
    2
    const int* ptr; // 指针所指向的内容是常量
    int* const ptr; // 指针本身是常量

const 的主要目的是提高代码的安全性和可读性,确保数据不会被意外修改。

static的作用

  1. 局部静态变量

    • 在函数内部定义的静态变量,只在第一次调用时初始化,且在程序运行期间保持存在。

    • 示例

      1
      2
      3
      4
      5
      void func() {
      static int count = 0; // 局部静态变量
      count++;
      std::cout << count << std::endl;
      }
  2. 全局静态变量

    • 在文件作用域中定义的静态变量,只在定义它的文件内可见,不会被其他文件访问。

    • 示例

      1
      static int globalVar = 10; // 全局静态变量
  3. 静态成员变量

    • 类的静态成员变量属于类本身,而不是类的某个对象,因此不需要实例化对象即可访问。

    • 示例

      1
      2
      3
      4
      5
      class MyClass {
      public:
      static int count; // 静态成员变量
      };
      int MyClass::count = 0; // 静态成员变量的定义
  4. 静态成员函数

    • 类的静态成员函数属于类本身,而不是类的某个对象,因此不需要实例化对象即可调用。

    • 示例

      1
      2
      3
      4
      5
      class MyClass {
      public:
      static void print() { std::cout << "Hello" << std::endl; }
      };
      MyClass::print(); // 调用静态成员函数
  5. 静态局部函数

    • 在函数内部定义的静态函数,只在定义它的函数内可见,不会被其他函数访问。

    • 示例

      1
      2
      3
      4
      5
      6
      void outerFunc() {
      static void innerFunc() {
      std::cout << "Inner function" << std::endl;
      }
      innerFunc();
      }

总结

  • 局部静态变量:在函数内部,只在第一次调用时初始化,保持存在。
  • 全局静态变量:在文件作用域中,只在定义它的文件内可见。
  • 静态成员变量:属于类本身,不需要实例化对象即可访问。
  • 静态成员函数:属于类本身,不需要实例化对象即可调用。
  • 静态局部函数:在函数内部,只在定义它的函数内可见。

static 的主要作用是控制变量和函数的作用域和生命周期,提高代码的安全性和可读性。

switch-case中break

  • 作用break 用于终止当前的 case 分支,防止代码继续执行到下一个 case,避免“穿透”。
  • 重要性:如果没有 break,代码会继续执行到下一个 case,直到遇到 breakswitch 结束。
  • 注意:每个 case 后通常都需要 break,除非你希望代码穿透。

栈和堆的区别

1、栈区是系统自动申请自动释放,且空间较小

2、堆区是需要手动申请,手动释放,空间较大

3、栈区常用来存放局部变量等

4、堆区常用来存放全局变量等

5、栈的空间是连续的,而堆不是

进程和线程的区别

进程是程序的运行实例,是资源分配的最小单位,拥有独立的内存空间和系统资源。
线程是进程内的执行单元,是CPU调度的最小单位,共享进程的内存空间,创建和切换开销小,适合高并发任务。

我需要实现多线程的数据采集和处理,因此通过pthread库实现了线程同步

具体做法是:首先,针对多个线程同时访问共享资源(如传感器数据缓冲区)的场景,我采用了pthread_mutex_t互斥锁进行加锁和解锁操作。每当线程需要读写共享数据时,先执行pthread_mutex_lock加锁,操作完成后再pthread_mutex_unlock解锁,防止数据竞争和不一致。

此外,在需要线程间协作的部分,比如一个线程采集数据,另一个线程处理数据时,我还应用了pthread_cond_t条件变量。采集线程采集到数据后,通过pthread_cond_signal通知处理线程,处理线程用pthread_cond_wait等待信号,实现了生产者-消费者模型。这样既避免了忙等,又提升了系统响应效率。

malloc和new的区别,如何开辟内存

malloc是C语言的内存分配函数,需要手动转换指针类型,不自动调用构造函数。new是C++的操作符,自动调用构造函数初始化对象,使用更方便。

  • malloc:C语言函数,只分配内存,不调用构造函数,返回void*指针,需手动转换类型,用free释放。
  • new:C++操作符,分配内存并调用构造函数初始化对象,返回目标类型指针,用delete释放。

如何开辟内存

  • malloc

    1
    2
    int* ptr = (int*)malloc(10 * sizeof(int)); // 分配内存
    free(ptr); // 释放内存
  • new

    1
    2
    int* ptr = new int[10]; // 分配内存
    delete[] ptr; // 释放内存

内存分配的方式

  1. 静态分配:编译时分配,适合全局变量和静态变量。
  2. 自动分配:函数调用时分配,适合局部变量。
  3. 动态分配:运行时通过 malloc 等函数分配,需手动释放,适合动态数据结构。

malloc和free

mallocfree 是 C 语言中用于动态内存分配和释放的函数,它们在 Linux 环境下同样被广泛使用。

malloc

  • 功能:动态分配内存。

  • 声明

    1
    void* malloc(size_t size);
  • 参数

    • size:需要分配的内存大小,以字节为单位。
  • 返回值

    • 成功:返回指向分配内存的指针。
    • 失败:返回 NULL
  • 示例

    1
    2
    3
    4
    5
    6
    int* arr = (int*)malloc(10 * sizeof(int)); // 分配一个包含10个整数的数组
    if (arr == NULL) {
    // 处理内存分配失败的情况
    perror("malloc failed");
    exit(EXIT_FAILURE);
    }

free

  • 功能:释放之前通过 malloc 分配的内存。

  • 声明

    1
    void free(void* ptr);
  • 参数

    • ptr:指向之前通过 malloc 分配的内存的指针。
  • 返回值:无返回值。

  • 注意事项

    • 只能释放通过 malloc 分配的内存。
    • 不要释放同一个指针多次。
  • 示例

    1
    2
    free(arr); // 释放之前分配的内存
    arr = NULL; // 避免悬空指针

2. mallocfree 的使用注意事项

  • 内存泄漏

    • 如果分配了内存但没有释放,会导致内存泄漏。例如:

      c

      复制

      1
      2
      int* ptr = (int*)malloc(10 * sizeof(int));
      // 没有调用 free(ptr);
    • 避免内存泄漏的方法:确保每次调用 malloc 后,都有对应的 free

  • 悬空指针

    • 释放内存后,指针仍然指向已释放的内存地址,称为悬空指针。例如:

      c

      复制

      1
      2
      3
      int* ptr = (int*)malloc(10 * sizeof(int));
      free(ptr);
      // ptr 仍然是一个悬空指针
    • 避免悬空指针的方法:释放内存后,将指针设置为 NULL

      c

      复制

      1
      2
      free(ptr);
      ptr = NULL;
  • 重复释放

    • 不能对同一个指针多次调用 free,否则会导致未定义行为。例如:

      c

      复制

      1
      2
      3
      int* ptr = (int*)malloc(10 * sizeof(int));
      free(ptr);
      free(ptr); // 重复释放
  • 分配失败的处理

    • malloc 可能返回 NULL,需要检查返回值。例如:

      c

      复制

      1
      2
      3
      4
      5
      int* ptr = (int*)malloc(10 * sizeof(int));
      if (ptr == NULL) {
      // 处理内存分配失败的情况
      exit(1);
      }

3. mallocfree 的实现原理

  • malloc 的实现
    • malloc 通常会从堆(Heap)中分配内存。
    • 常见的内存分配算法包括:
      • 首次适应算法(First Fit):从堆的起始位置开始查找第一个足够大的空闲块。
      • 最佳适应算法(Best Fit):从堆中查找最小的足够大的空闲块。
      • 下次适应算法(Next Fit):从上次分配的结束位置开始查找。
      • 伙伴系统(Buddy System):将内存块分成大小相等的伙伴块,按需分配。
    • 现代的 malloc 实现(如 glibc 的 ptmalloc)通常会使用多种算法结合,以提高效率和减少内存碎片。
  • free 的实现
    • free 会将已分配的内存块标记为可用。
    • 如果相邻的内存块也是空闲的,可能会将它们合并成一个更大的空闲块,以减少内存碎片。

4. 内存碎片问题

  • 内存碎片
    • 内存碎片是指内存中存在许多小的空闲块,但没有足够大的连续空间来满足新的内存分配请求。
    • 内存碎片分为内部碎片和外部碎片:
      • 内部碎片:分配的内存块比实际需要的内存大。
      • 外部碎片:内存中存在许多小的空闲块,但没有足够大的连续空间。
  • 解决方法
    • 使用合适的内存分配算法(如伙伴系统)。
    • 定期进行内存整理(如合并空闲块)。
    • 使用内存池(Memory Pool)技术,预先分配一块较大的内存,按需分配小块内存。

5. mallocfree 的性能问题

  • 性能问题
    • mallocfree 的性能可能受到内存分配算法、内存碎片等因素的影响。
    • 频繁的内存分配和释放可能导致性能下降。
  • 优化方法
    • 使用内存池技术,减少对 mallocfree 的调用。
    • 使用高效的内存分配算法。
    • 避免频繁的内存分配和释放,尽量重用内存。

6. 面试中可能被问到的问题

  • 问题 1mallocfree 的区别是什么?
    • 回答malloc 用于动态分配内存,返回指向分配内存的指针;free 用于释放之前通过 malloc 分配的内存,避免内存泄漏。
  • 问题 2:如何避免内存泄漏?
    • 回答:确保每次调用 malloc 后,都有对应的 free。同时,检查 malloc 的返回值,避免分配失败导致的未定义行为。
  • 问题 3:什么是悬空指针?如何避免?
    • 回答:悬空指针是指向已释放内存的指针。避免方法是在释放内存后,将指针设置为 NULL
  • 问题 4mallocfree 的实现原理是什么?
    • 回答malloc 从堆中分配内存,常见的算法包括首次适应、最佳适应等。free 将已分配的内存块标记为可用,并可能合并相邻的空闲块。
  • 问题 5:如何解决内存碎片问题?
    • 回答:使用合适的内存分配算法,如伙伴系统;使用内存池技术;定期进行内存整理。
  • 问题 6:如何优化 mallocfree 的性能?
    • 回答:使用内存池技术减少调用次数;选择高效的内存分配算法;避免频繁的内存分配和释放。

new/delete与malloc/free的区别是什么?

  • 在C++中,申请动态内存和释放动态内存,用new/delete 和 malloc/free都可以,new和malloc动态申请的内存都位于堆中,无法被操作系统回收,需要对应的delete/free来释放空间

void *malloc(int size);

  • 说明:malloc向系统申请分配指定size个字节的内存空间返回类型是 void* 类型void* 表示未确定类型的指针C,C++规定,void* 类型可以强制转换为任何其它类型的指针
  • 对于类的对象而言,malloc/free无法满足动态对象的要求,对象在创建时要自动执行构造函数,在对象消亡之前要自动执行析构函数,而malloc/free 不在编译器控制权限之内,无法执行构造函数和析构函数
  • 当然对于没有资源要清理的类,不调用析构函数也没有太大的问题,即使用free或delete没有区别但万一有一些类的成员是指针,而这个指针又在堆上开辟了空间,这时不调用析构函数去释放这个指针指向的这段空间,就会造成内存泄漏delete会调用析构函数,释放指针成员变量的空间,再销毁对象本身的空间;而free只释放了对象本身的空间,而指针成员所指向的空间没有被释放

具体而言:

  • new 能够自动计算需要分配的内存空间,而malloc需要手工计算字节数
  • new与delete带具体类型的指针,malloc与free返回void类型的指针
  • new 将调用构造函数,而malloc不能;delete将调用析构函数,而free不能
  • malloc/free 需要库文件<stdlib.h>支持,而new/delete不需要库文件支持
  • new操作可以重载,可以自定义内存分配策略,不做内存分配,或者分配到非内存设备上而malloc不能

delete和free被调用后,内存不会不会立即收回,指针也不会指向空,delete或free仅仅是告诉操作系统,这一块内存被释放啦,还可以做其他用途由于没有对这块内存进行写操作,所以内存中的变量数值并没有发生变化,出现野指针的情况,因此,释放完内存后需要将指针向量置为空

几个简单的Linux指令 shell

在面试中,掌握一些基本的 Linux 命令是非常重要的,尤其是对于嵌入式软件工程师岗位。以下是一些常见的 Linux 命令及其用途,适合在面试中展示你的 Linux 操作能力。

1. 文件和目录操作

  • **ls**:列出目录内容

    1
    2
    3
    ls -l       # 以长格式列出文件和目录
    ls -a # 列出所有文件,包括隐藏文件
    ls -la # 以长格式列出所有文件
  • **cd**:切换目录

    1
    2
    3
    cd /path/to/directory   # 切换到指定目录
    cd .. # 切换到上一级目录
    cd # 切换到用户主目录
  • **pwd**:显示当前工作目录

    1
    pwd
  • **mkdir**:创建目录

    1
    2
    mkdir new_directory
    mkdir -p parent/child # 递归创建目录
  • **rm**:删除文件或目录

    1
    2
    3
    rm file.txt             # 删除文件
    rm -r directory # 递归删除目录
    rm -f file.txt # 强制删除文件,不提示
  • **cp**:复制文件或目录

    1
    2
    cp file.txt newfile.txt   # 复制文件
    cp -r directory newdir # 递归复制目录
  • **mv**:移动或重命名文件或目录

    1
    2
    mv file.txt newfile.txt   # 重命名文件
    mv file.txt /path/to/directory # 移动文件

2. 文件查看和编辑

  • **cat**:显示文件内容

    1
    cat file.txt
  • **less**:分页显示文件内容

    1
    less file.txt
  • **head**:显示文件的前几行

    1
    head -n 10 file.txt   # 显示文件的前10行
  • **tail**:显示文件的后几行

    1
    2
    tail -n 10 file.txt   # 显示文件的后10行
    tail -f log.txt # 实时查看文件的新增内容
  • **vinano**:编辑文件

    1
    2
    vi file.txt           # 使用 vi 编辑器
    nano file.txt # 使用 nano 编辑器

3. 权限管理

  • **chmod**:修改文件或目录的权限

    1
    2
    chmod 755 file.txt    # 设置文件权限为 rwxr-xr-x
    chmod +x script.sh # 为脚本添加可执行权限
  • **chown**:更改文件或目录的所有者

    1
    chown user:group file.txt

4. 系统信息

  • **whoami**:显示当前用户

    1
    whoami
  • **uname**:显示系统信息

    1
    2
    3
    uname -a               # 显示所有系统信息
    uname -m # 显示机器硬件架构
    uname -r # 显示内核版本
  • **df**:显示磁盘空间使用情况

    1
    df -h                  # 以易读的格式显示磁盘空间
  • **du**:显示文件或目录的磁盘使用情况

    1
    du -sh directory       # 以易读的格式显示目录的总大小
  • **tophtop**:显示系统进程

    1
    2
    top                    # 显示系统进程(动态更新)
    htop # 更友好的进程查看工具

5. 网络操作

  • **ping**:测试网络连接

    1
    ping -c 4 google.com   # 向目标主机发送4次ICMP请求
  • **ifconfigip**:显示或配置网络接口

    1
    2
    ifconfig               # 显示网络接口信息
    ip addr show # 显示网络接口信息
  • **netstatss**:显示网络连接

    1
    2
    netstat -tuln          # 显示所有监听的TCP/UDP端口
    ss -tuln # 替代 netstat 的工具

6. 查找和搜索

  • **find**:查找文件或目录

    1
    find /path -name "file.txt"  # 在指定路径下查找文件
  • **grep**:搜索文件内容

    1
    2
    grep "pattern" file.txt      # 在文件中搜索匹配的字符串
    grep -r "pattern" /path # 递归搜索目录中的文件

7. 脚本和命令行工具

  • **echo**:输出字符串

    1
    echo "Hello, World!"
  • **date**:显示或设置日期和时间

    1
    date
  • **history**:显示命令历史

    1
    history
  • **alias**:创建命令别名

    1
    alias ll='ls -la'        # 创建别名

8. 系统管理

  • **ps**:显示进程状态

    1
    ps aux                   # 显示所有进程的详细信息
  • **kill**:终止进程

    1
    kill -9 PID              # 强制终止进程
  • **shutdownreboot**:关闭或重启系统

    1
    2
    shutdown -h now          # 立即关机
    reboot # 重启系统

9. 管道和重定向

  • **管道 (|)**:将一个命令的输出作为另一个命令的输入

    1
    ps aux | grep "process_name"  # 查找特定进程
  • **重定向 (>>>)**:将命令的输出重定向到文件

    1
    2
    echo "Hello" > file.txt   # 将输出写入文件(覆盖)
    echo "World" >> file.txt # 将输出追加到文件

10. 压缩和解压

  • **tar**:打包和解包文件

    1
    2
    tar -czvf archive.tar.gz directory/  # 打包并压缩目录
    tar -xzvf archive.tar.gz # 解压文件
  • **gzipgunzip**:压缩和解压文件

    1
    2
    gzip file.txt            # 压缩文件
    gunzip file.txt.gz # 解压文件

面试中可能被问到的问题

  • 问题 1:如何查看当前目录下的所有文件,包括隐藏文件?

    • 回答ls -a
  • 问题 2:如何递归删除一个目录?

    • 回答rm -r directory
  • 问题 3:如何查看文件的前10行?

    • 回答head -n 10 file.txt
  • 问题 4:如何实时查看日志文件的新增内容?

    • 回答tail -f log.txt
  • 问题 5:如何查找某个文件?

    • 回答find /path -name "file.txt"
  • 问题 6:如何终止一个进程?

    • 回答kill -9 PID
  • 问题 7:如何查看系统磁盘空间使用情况?

    • 回答df -h
  • 问题 8:如何将一个命令的输出重定向到文件?

    • 回答command > file.txt

总结

掌握这些基本的 Linux 命令可以帮助你在面试中展示你的 Linux 操作能力。这些命令涵盖了文件操作、权限管理、系统信息查看、网络操作、查找搜索等多个方面,是嵌入式软件工程师必备的技能。

什么是野指针,产后的原因是什么

1、野指针是指向位置是随机的且不正确的

2、产生原因 定义时未初始化,指向位置随机

或者在释放时没有指向null,从而指向垃圾内存

1. 什么是野指针?

比喻:想象你手里拿着一张地图,但地图上的地址是乱写的,或者地图根本就没有地址,你按照这个地图去寻找某个地方,很可能就会迷失方向,甚至走到一个完全错误的地方。

实际操作

  • 野指针:在编程中,指针是一个变量,它用来存储另一个变量的内存地址。如果一个指针指向了一个随机的、不正确的内存地址,或者指向了一个已经被释放的内存地址,这个指针就被称为“野指针”。
  • 野指针的危害:野指针可能会导致程序访问到错误的内存区域,从而引发程序崩溃、数据损坏等不可预测的问题。

2. 产生原因

1. 定义时未初始化

比喻:你手里拿着一张地图,但地图上没有写地址,你不知道它指向哪里,所以你可能会走到一个完全错误的地方。

实际操作

  • 当你定义了一个指针变量,但没有给它一个具体的地址时,这个指针变量的值是随机的。比如:

    1
    int *ptr; // 没有初始化,ptr的值是随机的
  • 这个随机的值可能指向一个完全错误的内存地址,这就是野指针。

2. 释放后未指向NULL

比喻:你手里拿着一张地图,地图上写了一个地址,但这个地址的房子已经被拆掉了。你按照这个地图去寻找,可能会走到一个空地,或者一个完全不同的地方。

实际操作

  • 当你用malloc等函数分配了一块内存,并用一个指针变量指向它,然后释放了这块内存,但没有把指针变量设置为NULL,这个指针变量就会变成野指针。比如:

    1
    2
    3
    int *ptr = malloc(sizeof(int)); // 分配内存
    free(ptr); // 释放内存
    // 此时ptr仍然指向原来的内存地址,但这块内存已经被释放了
  • 如果你继续使用ptr,它就会指向一个已经被释放的内存地址,这就是野指针。

如何避免野指针的问题

1. 初始化指针

建议:在定义指针时,始终初始化指针为NULL或指向一个有效的地址。

示例

1
int *ptr = NULL; // 初始化为NULL

或者:

1
2
int value = 10;
int *ptr = &value; // 初始化为一个有效的地址

解释:初始化为NULL可以让你在后续使用指针时,通过检查是否为NULL来避免使用未初始化的指针。

2. 释放内存后将指针置为NULL

建议:在释放动态分配的内存后,立即将指针置为NULL

示例

1
2
3
4
5
6
7
int *ptr = malloc(sizeof(int));
if (ptr == NULL) {
// 处理内存分配失败的情况
}
// 使用ptr
free(ptr);
ptr = NULL; // 释放内存后将指针置为NULL

解释:这样可以避免指针继续指向已经被释放的内存,从而防止野指针的产生。

3. 检查指针是否为NULL

建议:在使用指针之前,始终检查指针是否为NULL

示例

1
2
3
4
5
6
7
8
9
10
11
int *ptr = malloc(sizeof(int));
if (ptr == NULL) {
// 处理内存分配失败的情况
return -1;
}

// 使用ptr
*ptr = 10;

free(ptr);
ptr = NULL;

解释:通过检查指针是否为NULL,可以避免对未初始化或已经释放的指针进行操作。

4. 使用智能指针(C++)

建议:如果你使用的是C++,尽量使用智能指针(如std::unique_ptrstd::shared_ptr)来管理动态内存。

示例

1
2
3
4
#include <memory>

std::unique_ptr<int> ptr = std::make_unique<int>(10);
// 使用ptr

解释:智能指针会自动管理内存的分配和释放,避免手动管理内存带来的风险。

5. 避免重复释放

建议:确保内存只被释放一次,避免重复释放。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int *ptr = malloc(sizeof(int));
if (ptr == NULL) {
// 处理内存分配失败的情况
return -1;
}

// 使用ptr
free(ptr);
ptr = NULL; // 释放内存后将指针置为NULL

// 避免重复释放
if (ptr != NULL) {
free(ptr);
}

解释:通过将指针置为NULL,可以避免重复释放的问题。

6. 使用工具检测野指针

建议:使用内存检测工具(如valgrind)来检测野指针和内存泄漏问题。

示例

1
valgrind ./your_program

解释valgrind等工具可以检测内存访问错误,帮助你发现野指针问题。

总结

  • 野指针:指向一个随机的、不正确的内存地址的指针。

  • 产生原因

    1. 定义时未初始化:指针变量没有被赋予一个具体的地址,它的值是随机的。
    2. 释放后未指向NULL:指针变量指向的内存被释放了,但指针变量没有被设置为NULL,它仍然指向原来的内存地址。

网络五层协议分别是哪些?

  1. 应用层(Application Layer):负责处理特定的应用程序细节,如电子邮件、文件传输和网页浏览。
  2. 运输层(Transport Layer):负责在网络中的两个节点之间提供可靠的数据传输,常见的协议有TCP和UDP。
  3. 网络层(Network Layer):负责将数据包从源主机移动到目的主机。
  4. 链路层(Link Layer):负责在物理层上传输数据帧,包括以太网等。
  5. 物理层(Physical Layer):负责在物理介质上透明地传输比特流。

-

4、你说你曾经做过某某驱动的移植,那你介绍下某某的驱动,是如何进行的?

硬件连接与初始化

  • 连接:DHT11通过GPIO引脚与开发板相连。
  • 初始化:在驱动中申请GPIO引脚,并设置为输入/输出模式,为数据通信做好准备。

数据采集与解析

  • 启动信号:主机拉低GPIO引脚一段时间后拉高,触发DHT11响应。
  • 接收数据:DHT11逐位发送40位数据(包括温湿度信息和校验位),主机通过检测GPIO引脚的电平变化来读取数据,并解析出温湿度值。

驱动框架搭建与注册

  • 定义驱动结构体:创建platform_driver结构体,包含proberemove函数。
  • 注册驱动:调用platform_driver_register将驱动注册到内核。
  • 设备树匹配:在设备树中添加DHT11设备描述,确保内核能够匹配驱动和硬件。

提供数据接口

  • 创建字符设备:通过register_chrdev注册字符设备,创建设备节点。
  • 实现读写操作:在file_operations中实现read函数,将采集到的温湿度数据提供给上层应用。

测试与优化

  • 功能测试:编写测试程序,通过设备节点读取数据,验证驱动功能。
  • 性能优化:优化延时和数据处理逻辑,确保驱动高效运行。

6、你说你曾经用UART协议做过东西,那你解释下UART协议中的内容

UART协议简介

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器)是一种常用的串行通信协议,用于设备之间的数据传输。它支持全双工通信,即可以同时发送和接收数据。

主要特点

  • 异步通信:发送方和接收方不需要共享时钟信号,通过起始位和停止位来标识数据帧的开始和结束。
  • 数据帧格式:通常由起始位(低电平)、数据位(可配置为7位或8位)、可选的校验位(奇校验、偶校验或无校验)和停止位(高电平)组成。
  • 波特率:通信双方需要约定一个波特率(如9600、115200等),表示每秒传输的位数,以确保数据同步。

工作原理

  1. 发送数据时

    • 发送方将数据位依次发送,起始位为低电平,表示数据帧开始。
    • 数据位按位发送,从最低位到最高位。
    • 如果有校验位,根据校验规则添加校验位。
    • 最后发送停止位,高电平表示数据帧结束。
  2. 接收数据时

    • 接收方检测到起始位后,开始采样数据位。
    • 按照约定的波特率和数据位数,依次读取数据位。
    • 如果有校验位,对接收到的数据进行校验。
    • 最后检测停止位,确认数据帧结束。

    智能指针有哪些

    1. **std::unique_ptr**:

      • 特点:独占所有权,不允许复制,但可以移动。

      • 用途:当需要独占资源时使用,确保资源不会被多个指针共享。

      • 示例

        1
        std::unique_ptr<int> ptr1(new int(10));
    2. **std::shared_ptr**:

      • 特点:共享所有权,通过引用计数管理资源的生命周期。

      • 用途:当多个指针需要共享同一资源时使用。

      • 示例

        1
        2
        std::shared_ptr<int> ptr1(new int(20));
        std::shared_ptr<int> ptr2 = ptr1; // ptr1 和 ptr2 共享同一个资源
    3. **std::weak_ptr**:

      • 特点:弱引用,不增加引用计数,用于打破 std::shared_ptr 的循环引用。

      • 用途:常用于观察但不拥有资源,避免内存泄漏。

      • 示例

        1
        2
        std::shared_ptr<int> ptr1(new int(30));
        std::weak_ptr<int> ptr2 = ptr1; // 弱引用,不增加引用计数

    总结

    • **std::unique_ptr**:独占所有权,适合独占资源。
    • **std::shared_ptr**:共享所有权,适合资源共享。
    • **std::weak_ptr**:弱引用,用于打破循环引用。

    share_ptr和weak_ptr的作用和区别

    **std::shared_ptr**:

    • 作用:管理动态分配的资源,通过引用计数自动管理内存。
    • 特点:可以复制,引用计数会增加;可以移动,引用计数会减少。
    • 适用场景:需要多个指针共享同一资源时。

    **std::weak_ptr**:

    • 作用:提供对 std::shared_ptr 管理的资源的非拥有性引用,避免循环引用。
    • 特点:不增加引用计数,不会阻止资源被释放。
    • 适用场景:用于观察但不拥有资源,避免内存泄漏。

    区别

    1. 引用计数
      • std::shared_ptr:增加引用计数。
      • std::weak_ptr:不增加引用计数。
    2. 生命周期管理
      • std::shared_ptr:管理资源的生命周期。
      • std::weak_ptr:不管理资源的生命周期,仅提供对资源的访问。
    3. 适用场景
      • std::shared_ptr:资源共享。
      • std::weak_ptr:打破循环引用,避免内存泄漏。

    左值和右值

    • 左值(Lvalue)

      • 定义:表示一个有持久存储位置的值,可以被取地址(&)。

      • 示例

        1
        2
        int a = 10; // a 是左值
        int& ref = a; // 引用左值
    • 右值(Rvalue)

      • 定义:表示一个临时的、没有持久存储位置的值,不能被取地址(&)。

      • 示例

        1
        int b = 10 + 20; // 10 + 20 是右值

    区别

    • 存储位置
      • 左值:有持久存储位置。
      • 右值:通常是临时的,没有持久存储位置。
    • 取地址
      • 左值:可以取地址。
      • 右值:不能取地址。
    • 用途
      • 左值:可以被引用(&)。
      • 右值:通常用于移动语义(C++11 引入)。

    示例

    1
    2
    3
    4
    int a = 10; // a 是左值
    int b = 10 + 20; // 10 + 20 是右值
    int& ref = a; // 引用左值
    // int& ref2 = 10 + 20; // 错误,不能引用右值

    右值引用

    • 定义:右值引用是C++11引入的一种引用类型,专门用于绑定到右值(临时对象)。
    • 语法:使用&&声明,例如int&& r = 10;
    • 用途:支持移动语义和完美转发,提高性能,避免不必要的拷贝。
    • 特点
      • 可以绑定到右值(临时对象)。
      • 不能绑定到左值(持久对象)。
      • 用于实现移动构造函数和移动赋值运算符。

    示例

    1
    2
    3
    int&& r = 10; // 绑定到右值
    int a = 10;
    // int&& r2 = a; // 错误,不能绑定到左值

    move原理

    移动语义通过右值引用(T&&)实现,允许资源从一个对象转移到另一个对象,避免不必要的拷贝。主要通过以下机制实现:

    1. 右值引用:绑定到临时对象(右值)。
    2. 移动构造函数:将资源从右值对象转移到新对象。
    3. 移动赋值运算符:将资源从右值对象转移到已有对象。
    4. **std::move**:将左值转换为右值,触发移动语义。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Resource {
    public:
    int* data;

    Resource(int size) : data(new int[size]) {}
    Resource(Resource&& other) noexcept : data(other.data) { other.data = nullptr; }
    Resource& operator=(Resource&& other) noexcept {
    delete[] data;
    data = other.data;
    other.data = nullptr;
    return *this;
    }
    ~Resource() { delete[] data; }
    };

    总结:移动语义通过右值引用和移动构造函数/赋值运算符,高效转移资源,提高性能。

    编译的过程

    1. 预处理(Preprocessing)
      • 处理源代码文件中的预处理指令,如#include#define等。
      • 生成预处理后的文件(通常是.i.ii文件)。
    2. 编译(Compilation)
      • 将预处理后的文件转换为汇编语言代码。
      • 生成汇编文件(通常是.s文件)。
    3. 汇编(Assembly)
      • 将汇编语言代码转换为机器码。
      • 生成目标文件(通常是.o文件)。
    4. 链接(Linking)
      • 将多个目标文件和库文件合并为一个可执行文件。
      • 解决符号引用,生成最终的可执行文件(通常是.exe或无扩展名的文件)。

    最熟悉什么语言

    C和C++是我最熟悉的语言。我有丰富的嵌入式系统开发经验,C++在性能和资源管理方面表现出色,非常适合这类场景。

    数组和链表区别?

    数组和链表的区别

    1. 存储方式
      • 数组:连续存储,内存分配固定。
      • 链表:非连续存储,通过指针连接。
    2. 访问速度
      • 数组:随机访问,速度快。
      • 链表:顺序访问,速度慢。
    3. 内存分配
      • 数组:静态分配,大小固定。
      • 链表:动态分配,大小可变。
    4. 插入和删除
      • 数组:插入和删除需要移动元素,效率低。
      • 链表:插入和删除直接操作指针,效率高。
    5. 内存使用
      • 数组:连续内存,浪费空间。
      • 链表:非连续内存,节省空间。

    7 愿意做bios吗

    愿意。BIOS(Basic Input/Output System,基本输入输出系统)开发是一个很有挑战性和成就感的领域,它涉及到硬件初始化、系统启动等底层技术,对提升我的嵌入式系统开发能力非常有帮助。我期待能在这个领域深入学习和实践。

得C++11和之前的有什么区别(auto、智能指针、右值引用等)

  1. auto 关键字

    • C++11 之前:需要显式声明变量类型。

    • C++11 之后auto 关键字让编译器自动推断变量类型,简化代码。

    • 示例

      1
      2
      auto x = 10; // x 的类型为 int
      auto y = 3.14; // y 的类型为 double
  2. 智能指针

    • C++11 之前:手动管理动态内存,容易导致内存泄漏。

    • C++11 之后:引入智能指针(如 std::unique_ptrstd::shared_ptr),自动管理内存,减少内存泄漏风险。

    • 示例

      cpp

      复制

      1
      2
      std::unique_ptr<int> ptr1(new int(10)); // 自动释放内存
      std::shared_ptr<int> ptr2(new int(20)); // 引用计数管理内存
  3. 右值引用

    • C++11 之前:只有左值引用,无法直接操作临时对象。

    • C++11 之后:引入右值引用(&&),支持移动语义,提高性能。

    • 示例

      cpp

      复制

      1
      int&& rvalueRef = 10; // 绑定到临时对象
  4. 移动语义

    • C++11 之前:只有拷贝语义,复制对象时会创建新的副本。

    • C++11 之后:支持移动语义,允许将资源从一个对象转移到另一个对象,避免不必要的拷贝。

    • 示例

      1
      2
      std::vector<int> v1 = {1, 2, 3};
      std::vector<int> v2 = std::move(v1); // v1 的内容被移动到 v2
  5. 初始化列表

    • C++11 之前:初始化数组或集合需要逐个赋值。

    • C++11 之后:支持初始化列表,简化初始化过程。

    • 示例

      1
      std::vector<int> v = {1, 2, 3, 4, 5};
  6. Lambda 表达式

    • C++11 之前:需要定义函数或函数对象。

    • C++11 之后:支持 Lambda 表达式,方便定义匿名函数。

    • 示例

      1
      2
      auto lambda = [](int x, int y) { return x + y; };
      int result = lambda(5, 3); // result = 8
  7. 并发支持

    • C++11 之前:没有标准的并发支持。

    • C++11 之后:引入了线程库(std::thread),支持多线程编程。

    • 示例

      1
      2
      std::thread t([]() { std::cout << "Hello from thread!" << std::endl; });
      t.join();

总结

C++11 引入了 auto、智能指针、右值引用、移动语义、初始化列表、Lambda 表达式和并发支持等特性,显著提升了语言的表达能力和效率,减少了内存泄漏风险,简化了代码编写。

8、你说你曾经用过云服务器,我们这边也是云服务器开发这一块的,你了解服务器里面都是些什么吗?

1. CPU(中央处理器)

  • 功能:负责执行服务器上的所有计算任务,包括运行操作系统、应用程序和处理用户请求。
  • 特点:云服务器通常会分配虚拟CPU(vCPU),这些vCPU是物理CPU核心的虚拟化实例。

2. 内存(RAM)

  • 功能:用于临时存储操作系统、应用程序和当前运行的数据,提供快速读写能力。
  • 特点:云服务器的内存是物理服务器内存的虚拟化分配,支持动态扩展和收缩。

3. 存储(磁盘)

  • 功能:用于持久化存储数据,如操作系统文件、应用程序数据和用户数据。
  • 类型
    • 本地存储:直接连接到物理服务器的硬盘(如SSD或HDD)。
    • 网络存储:通过网络连接的存储资源,如云存储服务(如AWS S3、阿里云OSS)。
  • 特点:支持弹性扩展,用户可以根据需求动态调整存储容量。

4. 网络接口

  • 功能:负责云服务器与其他设备(如其他云服务器、客户端、外部网络)的通信。
  • 特点:通过虚拟网络接口连接到虚拟网络,支持多种网络协议(如TCP/IP)。

5. 操作系统

  • 功能:管理服务器的硬件资源,提供用户与硬件之间的交互界面。
  • 常见类型:Linux(如Ubuntu、CentOS)、Windows Server等。

6. 虚拟化层(Hypervisor)

  • 功能:将物理服务器的资源虚拟化,分配给多个云服务器实例。
  • 特点:确保每个云服务器实例之间的隔离性,提高资源利用率。

7. 管理工具和服务

  • 功能:用于监控、管理和维护云服务器的运行状态。
  • 常见工具
    • 监控工具:如Prometheus、Grafana,用于监控资源使用情况和性能指标。
    • 配置管理工具:如Ansible、Puppet,用于自动化配置和部署。
    • 日志管理工具:如ELK(Elasticsearch、Logstash、Kibana),用于收集和分析日志。

8. 安全机制

  • 功能:保护云服务器免受攻击,确保数据安全。
  • 常见机制
    • 防火墙:控制进出服务器的网络流量。
    • 身份认证:如SSH密钥、多因素认证。
    • 数据加密:存储和传输中的数据加密。

9. 备份和恢复机制

  • 功能:确保数据的完整性和可用性,防止数据丢失。
  • 特点:支持定期备份和快速恢复。

10. 负载均衡

  • 功能:在多个云服务器之间分配用户请求,提高系统的可用性和性能。
  • 特点:支持自动扩展和故障转移。

11、那你对TCP的协议了解吗,TCP的协议发送流程是怎么样的,数据格式是怎么样的?

TCP 发送流程

  1. 建立连接(三次握手)
    • 客户端发送一个SYN(同步)包到服务器。
    • 服务器回应一个SYN+ACK(同步+确认)包。
    • 客户端发送一个ACK(确认)包,完成连接建立。
  2. 数据传输
    • 数据被分割成多个TCP段(Segment),每个段包含TCP头部和数据部分。
    • 每个TCP段通过IP层发送,TCP头部包含源端口、目的端口、序列号、确认号、窗口大小等信息。
    • 接收方通过序列号确认数据完整性,发送ACK确认收到的段。
  3. 关闭连接(四次挥手)
    • 发送方发送一个FIN(结束)包,表示数据发送完毕。
    • 接收方回应一个ACK确认收到FIN。
    • 接收方发送自己的FIN包。
    • 发送方回应ACK,完成连接关闭。

TCP 数据格式

  • TCP头部
    • 源端口和目的端口:标识发送和接收端的应用程序。
    • 序列号:用于数据段的顺序确认。
    • 确认号:接收方期望收到的下一个字节的序列号。
    • 标志位(如SYN、ACK、FIN):控制连接的建立和关闭。
    • 窗口大小:接收方的接收缓冲区大小,用于流量控制。
    • 校验和:确保数据的完整性。

12、你知道发送中有哪些检测错误的协议类型吗?说出任意一个都可以

当然!TCP协议中使用了多种机制来检测和纠正错误,其中一个关键机制是校验和(Checksum)

TCP 校验和

  • 作用:用于检测数据在传输过程中是否发生错误。
  • 原理:TCP校验和是一个简单的16位一的补码和,覆盖了TCP头部和数据部分。
  • 计算方法
    1. 将TCP头部和数据部分按16位分组。
    2. 对每个16位的段进行一的补码加法。
    3. 将最终的和取反,得到校验和。
  • 发送方:在发送TCP段之前,计算校验和并将其放入TCP头部。
  • 接收方:收到TCP段后,重新计算校验和。如果计算结果为全0,说明数据没有错误;否则,数据可能在传输过程中被篡改。

其他错误检测机制

除了校验和,TCP还通过以下机制确保数据的可靠性:

  • 序列号和确认号:确保数据按顺序接收,并通过ACK确认机制检测丢失或重复的段。
  • 超时重传:如果发送方在超时时间内没有收到ACK,会重新发送数据段。
  • 流量控制:通过窗口机制控制发送速率,避免接收方缓冲区溢出。

13、那你解释解释CRC校验是怎么回事,怎么的一个流程。

CRC校验流程

  1. 选择生成多项式:选择一个预定义的多项式(如CRC-16的0x8005)。
  2. 数据预处理:在数据后面附加若干个零(零的数量等于校验码的位数)。
  3. 多项式除法:用生成多项式对预处理后的数据进行除法,得到余数。
  4. 生成校验码:将余数作为校验码附加到数据末尾。
  5. 接收方校验:接收方收到数据后,用相同生成多项式对数据进行除法,若余数为0,则数据正确。

特点

  • 高效:能检测出大多数常见错误,如单比特错误和突发错误。
  • 可靠:基于数学运算,抗干扰能力强。
  • 易于实现:硬件和软件实现都简单。

13.针对竞赛:如何沟通 如何安排任务(我详细答了我的电赛 强调4天3夜时间想要获奖对于配合沟通非常重要)

在参加电子设计竞赛(电赛)时,我们团队面临着4天3夜的紧张赛程,时间非常紧迫。为了在这种高压环境下取得优异成绩,我们非常注重团队的沟通和任务安排。

1. 沟通方式

  • 明确分工:在竞赛开始前,我们团队根据每个人的专长和兴趣,明确了各自的分工。例如,我主要负责硬件设计和调试,另一位队员负责软件编程,还有一位队员负责撰写文档和测试。明确分工后,我们通过定期的团队会议来同步进度和解决问题。
  • 实时沟通:在整个竞赛过程中,我们保持实时沟通。遇到技术难题或进度延误时,我们会立即召开小组讨论,共同寻找解决方案。我们还通过微信群和项目管理工具(如Trello)来记录任务进展和关键问题,确保每个成员都能随时了解项目状态。
  • 面对面交流:尽管有线上工具,但我们更倾向于面对面交流。在竞赛期间,我们每天都会安排固定的时间进行面对面的讨论,这不仅提高了沟通效率,还增强了团队凝聚力。

2. 任务安排

  • 制定详细计划:在竞赛开始前,我们制定了详细的项目计划,将整个竞赛过程分解为多个小任务,并为每个任务分配了明确的时间节点。例如,第一天完成需求分析和初步设计,第二天进行硬件搭建和软件框架搭建,第三天进行系统集成和调试,最后一天进行测试和文档撰写。
  • 灵活调整:尽管我们制定了详细的计划,但在实际操作中,难免会遇到意外情况。我们团队非常注重灵活性,一旦发现某个任务的进度滞后,我们会立即重新分配任务,确保整体进度不受影响。例如,在硬件调试阶段,我们发现一个问题需要额外的时间来解决,于是软件团队提前介入,帮助进行部分测试工作,确保整体进度不受影响。
  • 优先级管理:在任务安排中,我们特别注重优先级管理。对于关键任务,我们会集中资源优先完成,确保项目的核心功能能够正常运行。例如,在竞赛中,我们优先完成了核心功能的硬件和软件设计,然后再逐步完善其他辅助功能。

3. 团队协作

  • 信任与支持:在整个竞赛过程中,团队成员之间建立了深厚的信任。每个成员都清楚自己的职责,同时也愿意在需要时为其他成员提供支持。这种信任和团队精神是我们能够在4天3夜内完成任务并获得优异成绩的关键。
  • 共同目标:我们始终牢记竞赛的最终目标,即在规定时间内完成高质量的作品。这种共同的目标意识激励着我们每个人在面对困难时保持积极态度,共同努力克服挑战。

14.觉得自己在团队中是担任一个什么角色(分派任务 执行任务 监督管理)

在团队中,我通常会根据项目的具体需求和团队成员的专长来灵活调整自己的角色。不过,总体来说,我更倾向于担任一个“协调者”和“执行者”的角色。

1. 协调者角色

  • 任务分配与沟通:在项目初期,我会积极参与任务的分配和计划的制定。我会根据每个成员的技能和兴趣,合理分配任务,确保每个人都能发挥自己的优势。同时,我会负责团队内部的沟通协调,确保信息的透明和流畅。
  • 解决冲突:在团队合作过程中,难免会出现意见分歧。我会主动倾听各方观点,帮助团队达成共识,确保项目顺利推进。
  • 进度跟踪:我会定期检查项目的进度,及时发现潜在的问题,并调整计划以确保项目按时完成。例如,在电子设计竞赛中,我负责每天总结团队的进展,并根据实际情况灵活调整任务分配。

2. 执行者角色

  • 高效执行:除了协调工作外,我也会积极参与具体的任务执行。我会确保自己负责的任务高质量完成,同时也会主动协助其他成员解决技术难题。
  • 技术专长:在技术方面,我具备扎实的编程和硬件设计能力,能够独立完成复杂的任务。例如,在智能家居项目中,我负责了核心硬件的开发和调试工作,确保了系统的稳定运行。
  • 质量把控:在执行任务时,我会严格把控质量,确保每个环节都符合项目要求。我会主动进行测试和验证,确保交付的成果无误。

15.入职时间以及入职时长

16.对家庭/发展/城市/岗位/行业/职位/薪酬进行排序

  1. 家庭
    • 理由:家庭是生活的基础,是我在工作中保持动力和平衡的重要支撑。无论工作多忙,家庭的幸福和健康始终是最重要的。
  2. 发展
    • 理由:职业发展是我选择工作的重要考量。我希望在一个能够提供成长机会和职业晋升空间的环境中工作,这样我不仅能实现个人价值,也能为家庭带来更好的生活保障。
  3. 行业
    • 理由:选择一个有前景的行业对于长期职业发展至关重要。嵌入式软件行业目前正处于快速发展阶段,技术更新换代快,市场需求大,这为我提供了广阔的发展空间。
  4. 岗位
    • 理由:岗位的具体职责和工作内容直接影响到我的工作满意度和职业成就感。我希望在一个能够充分发挥自己专业技能和兴趣的岗位上工作,这样可以提高工作效率和质量。
  5. 城市
    • 理由:城市的选择也非常重要,它不仅影响生活质量,还会影响职业机会。我更倾向于选择一个经济发展良好、生活成本合理、文化氛围浓厚的城市,这样可以更好地平衡工作和生活。
  6. 职位
    • 理由:职位的高低虽然重要,但并不是我最看重的因素。我更关注职位是否能够让我在团队中发挥重要作用,是否能够为我提供学习和成长的机会。
  7. 薪酬
    • 理由:薪酬是工作的重要组成部分,但它并不是我选择工作的首要因素。合理的薪酬可以保障生活质量,但职业发展和个人成长对我来说更为重要。我相信,随着职业的发展,薪酬自然会得到提升。

17.你觉得你自己是一个什么样的人

我是一个有责任心、学习能力强且注重团队合作的人。 细心且有耐心 积极主动

18.家庭情况,家庭成员…

我的家庭非常温馨和支持我。我来自一个普通的家庭,父母都非常重视教育,他们一直鼓励我追求自己的梦想,并在学业和职业上给予我很大的支持。我有一个弟弟。我的家庭氛围很融洽,这让我能够在一个充满爱和支持的环境中成长,也培养了我积极向上的人生态度和责任感。

19.职业规划以及生活规划(生活规划暂时还没考虑那么远)

在未来1-3年的短期职业规划中,我期望能够顺利入职贵公司并快速适应工作环境,熟悉公司的业务流程和技术栈。在入职的第一年,我计划通过参与实际项目,重点提升自己在嵌入式软件开发方面的技能,尤其是在Linux驱动开发和硬件调试领域。接下来的1-2年里,我希望能够参与更多具有挑战性的项目,积累丰富的项目经验,提升自己在团队中的贡献度,并进一步深化对嵌入式系统的理解和掌握。

目前,我的生活规划还没有考虑得特别长远,但总体上,我希望能够在工作和生活之间找到一个良好的平衡。我计划在工作稳定后,逐步实现一些个人的生活目标

20.了解公司在哪里吗

广东省东莞市东莞市;江苏省无锡市市辖区;江西省南昌市;上海市市辖区;陕西省西安市

21.一个月可以接受加班时间

50个小时? 只要给加班费就好了

22.怎么看待加班

我认为工作和生活的平衡非常重要,但我也理解在某些情况下,项目可能需要额外的时间投入。如果项目确实需要,我愿意在必要时加班以确保任务的完成。然而,我也相信通过高效的管理和合理的工作安排,可以在正常工作时间内完成大部分任务,从而减少不必要的加班。如果每月需要加班50小时,我会尽力配合,但同时也会与团队和管理层沟通,寻找更高效的工作方式,以确保长期的工作效率和团队的可持续发展。

23.自己进入公司有什么优势(答了活力和效益)

首先,我充满活力和热情。我对嵌入式系统开发和物联网技术充满兴趣,这种热情让我始终保持积极主动的工作态度。我相信这种活力能够为团队带来新的想法和动力,推动项目的顺利进行。

其次,我注重效益和效率。我深知在快节奏的科技行业,时间和资源都非常宝贵。因此,我始终致力于通过优化代码、合理规划项目进度以及高效解决问题,提升工作效率和项目质量。我相信这种对效益的关注能够为公司创造更大的价值。

此外,我还具备扎实的技术基础和快速学习能力。我在嵌入式Linux开发、驱动程序编写以及硬件调试方面积累了丰富的经验,并且能够迅速掌握新的技术和工具。这使我能够快速适应公司的技术栈和业务需求,为团队贡献实际力量。

最后,我具备良好的团队合作精神和沟通能力。我深知团队合作的重要性,能够与团队成员有效协作,共同解决问题。同时,我也能够清晰地表达自己的想法和建议,确保信息的高效传递。

1.为什么选择读目前的专业

我选择电子信息工程专业,主要是基于以下几个原因:

  1. 个人兴趣
    我从小就对电子设备和技术充满了浓厚的兴趣。喜欢拆解和组装各种电子设备,对电路、芯片和编程有着天生的好奇心。这种兴趣促使我选择了电子信息工程专业,希望能够系统地学习相关知识。
  2. 职业前景
    电子信息工程是一个快速发展的领域,涵盖了嵌入式系统、物联网、通信技术等多个热门方向。我看到了这个专业的广阔职业前景,尤其是在嵌入式软件开发方面,市场需求非常大。我希望通过学习这个专业,能够在未来的职业生涯中找到一个有挑战性和发展前景的工作。
  3. 实践与创新
    电子信息工程专业注重实践和创新,课程设置中包含了大量的实验和项目。这让我有机会将理论知识应用到实际项目中,培养了我的动手能力和解决问题的能力。例如,在大学期间,我参与了多个项目,如基于AI技术的智能语音台灯和Linux智能家居系统,这些项目不仅锻炼了我的技术能力,也让我对专业有了更深入的理解。
  4. 技术基础
    这个专业为我提供了坚实的理论基础和技术技能,包括C语言编程、单片机原理、嵌入式系统设计等。这些知识和技能为我未来的职业发展打下了坚实的基础,使我能够更好地适应快速变化的技术环境。

2.为什么想做嵌入式的工作

  1. 个人兴趣
    我对电子设备和底层硬件的交互非常感兴趣。从小就喜欢拆解和组装各种电子设备,对电路、芯片和编程有着浓厚的兴趣。嵌入式开发让我能够将这些兴趣结合起来,直接与硬件设备进行交互,实现各种功能。
  2. 职业规划
    我希望在技术领域深耕,成为一名专业的嵌入式软件工程师。嵌入式系统在现代科技中无处不在,从智能家居到工业自动化,从医疗设备到汽车电子,嵌入式技术的应用非常广泛。我希望通过从事嵌入式工作,积累丰富的项目经验,提升自己的技术能力,为未来的职业发展打下坚实的基础。
  3. 行业前景
    嵌入式行业目前正处于快速发展阶段,随着物联网、人工智能和5G技术的普及,嵌入式系统的需求不断增加。这为嵌入式工程师提供了广阔的职业发展空间和丰富的就业机会。我相信在这个领域工作,能够接触到最新的技术和创新项目,保持职业的竞争力。
  4. 专业背景
    我在大学期间系统地学习了电子信息工程专业,掌握了C语言编程、单片机原理、嵌入式系统设计等核心课程。通过参与多个项目,如基于AI技术的智能语音台灯和Linux智能家居系统,我积累了丰富的实践经验,这些都让我对嵌入式开发有了更深入的理解和兴趣。
  5. 技术挑战
    嵌入式开发涉及到硬件和软件的紧密结合,需要解决各种技术难题,如硬件资源管理、实时性要求、低功耗设计等。这些挑战让我感到兴奋,也让我有机会不断提升自己的技术水平和解决问题的能力。

3.怎么找到兴趣的

  1. 尝试不同的活动
    在高中和大学期间,我尝试了各种不同的活动,包括参加电子制作社团、编程比赛、机器人竞赛等。这些活动让我接触到了不同的领域,逐渐发现自己对电子技术和编程的浓厚兴趣。
  2. 参与项目实践
    在大学期间,我积极参与了多个项目,比如基于AI技术的智能语音台灯和Linux智能家居系统。通过这些项目,我不仅学到了很多专业知识,还发现自己在解决实际问题时的成就感,这进一步激发了我对嵌入式开发的兴趣。
  3. 深入学习
    我通过阅读专业书籍、参加在线课程和学习最新的技术文章,不断深入了解嵌入式领域的知识。在这个过程中,我发现自己对硬件和软件的结合、系统优化等方面特别感兴趣。
  4. 与他人交流
    我经常与同学、老师和行业专家交流,分享彼此的经验和见解。这些交流不仅拓宽了我的视野,还帮助我更清晰地认识到自己的兴趣所在。例如,在参加技术研讨会和行业论坛时,我了解到嵌入式技术在智能家居、工业自动化等领域的广泛应用,这让我更加坚定了自己的兴趣方向。
  5. 反思和调整
    在探索兴趣的过程中,我不断反思自己的经历,思考哪些活动让我感到兴奋和满足,哪些活动则让我感到无聊或疲惫。通过这种反思,我逐渐明确了自己真正感兴趣的领域,并调整了自己的学习和实践方向。

4.如果在本专业没有找到兴趣那你会怎么做

  1. 深入自我反思
    首先,我会花时间深入反思自己的兴趣和优势所在。通过与导师、职业规划师的交流,以及进行职业兴趣测试,更全面地了解自己的兴趣点和适合的方向。
  2. 探索相关领域
    如果在本专业没有找到兴趣,我会尝试探索与本专业相关的其他领域。例如,电子信息工程与计算机科学、自动化、人工智能等领域有很多交叉点。通过选修相关课程或参与跨学科项目,可能会发现新的兴趣点。
  3. 实践与尝试
    我会积极参与实习和项目实践,尝试不同的工作内容和角色。通过实际工作经验,了解不同领域的工作性质和要求,找到自己真正感兴趣的方向。
  4. 继续教育
    如果发现本专业与我的兴趣不符,我可能会考虑继续深造,攻读相关领域的研究生学位。这不仅可以拓宽我的知识面,还能为未来的职业发展提供更多选择。
  5. 职业规划与调整
    最重要的是,我会根据自己的兴趣和市场需求,制定灵活的职业规划。如果发现某个领域更适合自己,我会毫不犹豫地调整职业方向,确保自己的工作能够带来成就感和满足感。

5.怎么定义兴趣/喜欢

  1. 内在的兴奋感
    当我对某件事情感兴趣时,我会感到一种内在的兴奋和愉悦。这种感觉会让我主动去了解更多的相关信息,并且在思考和讨论这些内容时感到快乐。
  2. 主动投入时间
    兴趣会让我愿意主动投入时间和精力去学习和实践。例如,如果我对某个技术感兴趣,我会在课余时间阅读相关书籍、参加在线课程,甚至自己动手做一些小项目来加深理解。
  3. 持续的动力
    兴趣会给我带来持续的动力,即使遇到困难和挑战,我也会坚持下去。这种动力让我在面对复杂问题时不会轻易放弃,而是会努力寻找解决方案。
  4. 积极的反馈
    当我对某件事情感兴趣时,我通常会收到积极的反馈。这种反馈可能来自自己的成就感,也可能来自他人的认可。例如,在参与项目时,如果我对某个模块特别感兴趣,我通常能够更高效地完成任务,并且得到团队成员的认可。
  5. 长期的追求
    兴趣不仅仅是一时的喜好,而是一种长期的追求。它会让我在一段时间内持续关注某个领域,并且愿意不断学习和进步。例如,我对嵌入式开发的兴趣让我在大学期间参与了多个相关项目,并且在毕业后仍然希望在这个领域继续发展。

6.为什么不去别的公司

  1. 公司的行业地位和影响力
    贵公司在嵌入式系统和物联网领域具有很高的行业地位和广泛的影响力。我非常钦佩公司在技术创新和产品开发方面的成就,特别是在智能家居、智能安防等领域的应用。我希望能够在这样一个行业领先的企业中工作,学习先进的技术和管理经验。
  2. 公司文化和价值观
    我了解到贵公司非常注重团队合作、创新和员工发展。这种积极向上的公司文化与我的个人价值观非常契合。我相信在这样的环境中,我能够更好地发挥自己的能力,同时也能够不断成长和进步。
  3. 职业发展机会
    贵公司为员工提供了丰富的职业发展机会,包括内部培训、项目实践和晋升通道。我看到了自己在贵公司未来的职业发展路径,这让我非常期待能够加入贵公司,实现自己的职业目标。
  4. 项目和团队
    在了解贵公司的项目和团队时,我被团队的专业能力和项目的创新性所吸引。例如,贵公司在智能家居系统开发方面的项目,不仅技术先进,而且具有很强的市场竞争力。我希望能够加入这样的团队,贡献自己的力量,并与团队成员共同成长。
  5. 个人兴趣和职业规划
    我对嵌入式开发和物联网技术有着浓厚的兴趣,而贵公司在这些领域有着深厚的技术积累和丰富的项目经验。我相信在贵公司工作,能够让我更好地实现自己的职业规划,同时也能够为公司的项目贡献自己的专业知识和技能。

7.家庭情况如何

我的家庭非常温馨和支持我。我来自一个普通的家庭,父母都非常重视教育,他们一直鼓励我追求自己的梦想,并在学业和职业上给予我很大的支持。我有一个弟弟。我的家庭氛围很融洽,这让我能够在一个充满爱和支持的环境中成长,也培养了我积极向上的人生态度和责任感。

10.什么时候可以入职

非常感谢您对我的认可!如果顺利通过面试,我可以在**[具体日期]**入职。目前我已经完成了手头的所有事务,没有任何其他工作安排,可以全身心投入到新的工作中。我非常期待能够尽快加入贵公司,开始新的职业旅程。

11.你的学校是985还是211(双非仔落泪了)

我的学校是西北民族大学,它是一所非常注重实践和创新的高校。虽然它不是985或211院校,但我在这里接受了系统的专业教育,并且通过参与多个项目和竞赛,积累了丰富的实践经验。例如,我曾独立完成基于AI技术的智能语音台灯项目,并在Linux智能家居系统项目中负责驱动开发和应用开发。这些经历不仅锻炼了我的技术能力,也培养了我的团队合作和解决问题的能力。我相信,这些经验和能力能够让我在贵公司的工作中发挥重要作用。

12.期望薪资

我对薪资的期望是根据市场行情和我的专业背景来设定的。根据我目前的了解,嵌入式软件工程师的市场薪资范围在**[具体范围]。考虑到我的专业技能、项目经验以及对贵公司的热情,我期望的薪资范围是1w-1w2**。当然,我也理解薪资会根据公司的具体情况和市场变化有所调整,我愿意与公司进行进一步的沟通和协商。

平时项目怎么分配任务

1. 沟通方式

  • 明确分工:在竞赛开始前,我们团队根据每个人的专长和兴趣,明确了各自的分工。例如,我主要负责硬件设计和调试,另一位队员负责软件编程,还有一位队员负责撰写文档和测试。明确分工后,我们通过定期的团队会议来同步进度和解决问题。
  • 实时沟通:在整个竞赛过程中,我们保持实时沟通。遇到技术难题或进度延误时,我们会立即召开小组讨论,共同寻找解决方案。我们还通过微信群和项目管理工具(如Trello)来记录任务进展和关键问题,确保每个成员都能随时了解项目状态。
  • 面对面交流:尽管有线上工具,但我们更倾向于面对面交流。在竞赛期间,我们每天都会安排固定的时间进行面对面的讨论,这不仅提高了沟通效率,还增强了团队凝聚力。

2. 任务安排

  • 制定详细计划:在竞赛开始前,我们制定了详细的项目计划,将整个竞赛过程分解为多个小任务,并为每个任务分配了明确的时间节点。例如,第一天完成需求分析和初步设计,第二天进行硬件搭建和软件框架搭建,第三天进行系统集成和调试,最后一天进行测试和文档撰写。
  • 灵活调整:尽管我们制定了详细的计划,但在实际操作中,难免会遇到意外情况。我们团队非常注重灵活性,一旦发现某个任务的进度滞后,我们会立即重新分配任务,确保整体进度不受影响。例如,在硬件调试阶段,我们发现一个问题需要额外的时间来解决,于是软件团队提前介入,帮助进行部分测试工作,确保整体进度不受影响。
  • 优先级管理:在任务安排中,我们特别注重优先级管理。对于关键任务,我们会集中资源优先完成,确保项目的核心功能能够正常运行。例如,在竞赛中,我们优先完成了核心功能的硬件和软件设计,然后再逐步完善其他辅助功能。

3. 团队协作

  • 信任与支持:在整个竞赛过程中,团队成员之间建立了深厚的信任。每个成员都清楚自己的职责,同时也愿意在需要时为其他成员提供支持。这种信任和团队精神是我们能够在4天3夜内完成任务并获得优异成绩的关键。
  • 共同目标:我们始终牢记竞赛的最终目标,即在规定时间内完成高质量的作品。这种共同的目标意识激励着我们每个人在面对困难时保持积极态度,共同努力克服挑战。

为什么投华勤

1. 行业地位与业务布局

华勤技术是全球知名的智能硬件ODM(原始设计制造商)企业,连续多年在全球智能手机ODM/IDH厂商中市占率名列前茅。其“3+N+3”战略(手机、笔电、服务器 + N个新兴场景 + 3大技术中台)正在加速落地,业务涵盖智能终端、高性能计算、汽车电子、AIoT等多个领域,显示出强大的市场竞争力和多元化的业务布局。

2. 技术创新与研发实力

华勤技术在技术研发方面投入巨大,建立了多个研发中心,汇聚了全球顶尖技术人才。公司在5G、AI、物联网等前沿技术领域取得了显著成果,例如在AI笔电、服务器等产品上实现了技术创新。此外,华勤还通过并购豪成智能科技有限公司,快速切入机器人市场,并启动人形机器人研发,展现了强大的技术储备和前瞻性布局。

3. 市场前景与增长潜力

华勤技术2024年实现营收首破千亿大关,同比增长28.76%。随着AI技术的发展,华勤在AI服务器、智能座舱及机器人业务等新兴领域的持续放量,有望进一步推动公司增长。公司还通过“China + VMI”全球化制造布局和垂直整合增强供应链韧性,进一步提升市场竞争力。

4. 职业发展与个人成长

华勤技术作为行业内的龙头企业,提供了广阔的职业发展空间和丰富的学习机会。加入华勤,不仅能接触到前沿的技术和项目,还能与全球顶尖的技术人才合作,提升个人的技术水平和职业素养。

加班怎么看

我理解加班是工作中不可避免的一部分,尤其是在项目紧急或任务繁重时。我认为,加班本身并不是目的,而是为了确保项目能够按时交付、质量达标的一种手段。如果加班能够帮助团队完成重要任务,我会毫不犹豫地参与其中。

不过,我也相信通过合理的时间管理和高效的工作方式,可以在一定程度上减少不必要的加班。例如,提前规划工作流程、优化任务分配、提高工作效率等,都能帮助我们在正常工作时间内完成更多任务。

总的来说,我愿意在必要时加班,但同时也会努力提高工作效率,尽量减少加班的频率,以保持良好的工作与生活平衡。

首先是想通过自己的努力获得丰厚回报,能力中等偏上,但是又距离大神还有差距,抗压能力强,想在大城市稳住脚跟。

关于加班,华勤这几年顶着这么大的行业压力依然杀到了ODM的榜首,绝对不是随随便便能实现的。强度也分部门,市场研发应该是强度最大的,当然也是公司地位决定的。真到了项目dl,该上得上啊,不过日常项目不急,也是正常上下班。

对公司的了解

公司背景: 华勤技术股份有限公司(简称“华勤”)是一家全球领先的智能硬件平台型企业,成立于2005年,总部位于中国上海。华勤专注于智能硬件产品的研发设计、生产制造和运营服务,业务覆盖智能手机、平板电脑、笔记本电脑、智能穿戴设备、AIoT设备等多个领域。

行业地位: 华勤在全球智能硬件ODM(原始设计制造商)市场中占据重要地位,连续多年在全球智能手机ODM/IDH厂商中市占率名列前茅。根据市场研究机构的数据,华勤在2024年实现营收首破千亿大关,同比增长28.76%,显示出强大的市场竞争力和增长潜力。

业务布局: 华勤的业务布局广泛,涵盖了“3+N+3”战略,即:

  • 3大核心业务:智能手机、笔记本电脑、服务器。
  • N个新兴场景:如智能穿戴、智能汽车、智能家居等。
  • 3大技术中台:包括研发、供应链和制造技术中台,为业务发展提供坚实的技术支持。

技术创新: 华勤在技术创新方面投入巨大,建立了多个研发中心,汇聚了全球顶尖的技术人才。公司在5G、AI、物联网等前沿技术领域取得了显著成果。例如,华勤在AI笔电、服务器等产品上实现了技术创新,并通过并购豪成智能科技有限公司,快速切入机器人市场,启动人形机器人研发,展现了强大的技术储备和前瞻性布局。

全球化布局: 华勤在全球范围内建立了广泛的制造和运营网络,通过“China + VMI”全球化制造布局和垂直整合增强供应链韧性,进一步提升市场竞争力。公司在多个国家和地区设有研发中心和生产基地,能够快速响应全球客户的需求。

企业文化: 华勤注重企业文化建设,倡导“客户至上、奋斗为本、创新为魂、合作共赢”的价值观。公司为员工提供了广阔的职业发展空间和丰富的学习机会,致力于打造一个充满活力和创新精神的工作环境。

同时拥有几个offer怎么选择

  1. 职业发展与个人兴趣
    • 我会首先考虑每个Offer的职位内容和发展机会,确保工作内容符合我的职业兴趣和长期规划。例如,如果某个职位能够让我接触到前沿技术,或者为我提供清晰的职业晋升路径,这会是一个重要的加分项。
  2. 公司背景与行业地位
    • 我会研究每家公司的背景,包括行业地位、市场前景和企业文化。选择一个在行业内有良好声誉和稳定发展的公司,可以为我的职业发展提供更坚实的基础。
  3. 薪资与福利
    • 虽然薪资不是唯一考虑因素,但它确实很重要。我会比较每个Offer的薪资水平、奖金结构以及福利待遇,如健康保险、退休金计划、带薪休假等。
  4. 工作环境与文化
    • 公司的工作环境和文化对我的工作满意度和幸福感有很大影响。我会尽量了解每家公司的文化,包括团队合作方式、工作氛围和领导风格。如果可能,我会参观公司,与未来的同事和领导交流,以更好地感受公司的工作环境。
  5. 个人因素
    • 我也会考虑一些个人因素,比如工作地点是否方便,是否需要搬家或长途通勤。此外,工作与生活的平衡也很重要,我会选择一个能够支持我实现工作与生活平衡的公司。
  6. 长期目标
    • 最后,我会考虑每个Offer如何与我的长期职业目标相契合。选择一个能够帮助我实现长期目标的公司,对我来说是最重要的。

面试官可能的追问及回答

追问 1:你最看重的因素是什么?

回答: 我最看重的是职业发展机会和个人兴趣。我认为,如果工作内容是我感兴趣的,并且能够为我提供成长和晋升的机会,我会更有动力和热情。当然,薪资和福利也很重要,但它们更多是锦上添花,而不是决定性因素。

追问 2:如果两个Offer在职业发展方面都很有吸引力,你会怎么选择?

回答: 如果两个Offer在职业发展方面都很有吸引力,我会进一步比较公司的文化和工作环境。我会选择一个让我感到舒适、能够与团队成员和领导良好合作的公司。此外,我也会考虑工作与生活的平衡,因为这对我个人的幸福感和长期职业发展同样重要。

追问 3:你有没有遇到过类似的情况?你是怎么做的?

回答: 是的,我曾经遇到过类似的情况。当时,我收到了两个Offer,一个来自一家大型公司,薪资较高但工作压力大;另一个来自一家初创公司,薪资略低但工作环境灵活,有更多学习和成长的机会。经过仔细考虑,我选择了初创公司,因为它的文化和工作环境更符合我的价值观,而且我能感受到公司对员工的重视和支持。事实证明,这个选择让我在工作中感到更加充实和满足。

找工作的侧重点

我在找工作时最注重的是职业发展机会和学习成长的空间。我希望加入一个能够提供清晰职业晋升路径的公司,同时也能让我接触到前沿技术和行业动态。例如,如果公司有完善的培训体系和导师制度,这将是一个很大的加分项。我相信,通过不断学习和提升自己的技能,我能够更好地实现个人职业目标,同时也为公司创造更大的价值。

3 场景题,一个项目需要4天完成,现在需要你2天完成,你会怎么做

  1. 紧急评估与任务分解
    • 评估任务:首先,我会对项目的整体任务进行快速评估,了解每个任务的优先级和所需时间。这有助于我确定哪些任务是关键路径上的任务,哪些任务可以并行处理。
    • 任务分解:将项目分解为更小的子任务,并列出每个子任务的详细步骤和所需时间。这有助于我更清晰地了解任务的复杂性和优先级。
  2. 优先级排序与资源分配
    • 优先级排序:根据任务的重要性和紧急性,对子任务进行优先级排序。将关键任务放在优先位置,确保这些任务能够按时完成。
    • 资源分配:评估我是否有足够的资源来完成任务。如果需要,我会请求额外的资源支持,例如团队成员的帮助或工具支持。
  3. 优化工作流程
    • 提高效率:寻找可以优化的工作流程,例如通过自动化工具减少重复性工作,或者通过更高效的方法来完成任务。
    • 减少不必要的工作:检查是否有可以省略或简化的任务,确保只专注于核心任务。
  4. 沟通与协调
    • 与团队沟通:如果项目需要团队合作,我会立即与团队成员沟通,明确每个人的职责和任务,确保团队成员能够高效协作。
    • 与上级沟通:及时向上级汇报项目进度和可能遇到的问题,确保他们了解情况并能够提供必要的支持。
  5. 时间管理与监控
    • 制定详细计划:根据任务分解和优先级排序,制定一个详细的两天工作计划,明确每个任务的开始和结束时间。
    • 监控进度:在执行过程中,持续监控任务进度,确保每个任务都能按时完成。如果发现某个任务可能会延迟,我会立即调整计划,寻找解决方案。
  6. 应对突发问题
    • 预留缓冲时间:在计划中预留一定的缓冲时间,以应对可能出现的突发问题或意外情况。
    • 灵活调整:如果遇到突发问题,我会迅速评估影响并调整计划,确保项目整体进度不受太大影响。
  7. 质量保证
    • 确保质量:尽管时间紧迫,但我会确保每个任务的质量符合要求。在必要时,我会进行快速测试和验证,确保交付的成果是可靠的。
    • 持续改进:在项目完成后,我会总结经验教训,找出可以改进的地方,以便在未来的项目中更好地应对类似情况。

4 场景题,接3,接到项目,你会最先考虑什么?如果项目中,有一个团队成员摆烂,不想加班,不想做项目,你会怎么做?

接到项目,你会最先考虑什么?

回答: 接到项目后,我会首先进行以下几件事情:

  1. 项目目标与需求分析
    • 明确目标:我会与项目负责人或客户沟通,确保我完全理解项目的目标、期望的成果以及交付的时间节点。
    • 需求分析:详细分析项目需求,了解项目的具体要求和关键点,确保没有遗漏任何重要细节。
  2. 任务分解与优先级排序
    • 任务分解:将项目分解为更小的子任务,列出每个子任务的具体步骤和所需时间。这有助于我更清晰地了解项目的复杂性和工作量。
    • 优先级排序:根据任务的重要性和紧急性,对子任务进行优先级排序,确保关键任务能够优先处理。
  3. 资源评估与分配
    • 评估资源:评估完成项目所需的资源,包括人力、工具、技术等。如果发现资源不足,我会及时提出解决方案,例如请求额外的资源支持或调整项目范围。
    • 分配任务:根据团队成员的能力和时间安排,合理分配任务,确保每个成员都能承担合适的任务。
  4. 制定详细计划
    • 时间规划:制定一个详细的项目计划,明确每个任务的开始和结束时间,确保项目能够按时完成。
    • 监控机制:建立项目监控机制,定期检查项目进度,及时发现和解决问题。
  5. 沟通与协调
    • 团队沟通:与团队成员进行沟通,确保每个人都清楚自己的职责和任务,了解项目的目标和重要性。
    • 客户沟通:与客户保持密切沟通,及时汇报项目进展,确保客户对项目进展感到满意。

问题 2:如果项目中有一个团队成员摆烂,不想加班,不想做项目,你会怎么做?

回答: 如果项目中有一个团队成员摆烂,不想加班,也不想积极参与项目,我会采取以下步骤来解决问题:

  1. 私下沟通

    • 了解原因:首先,我会私下与该团队成员进行沟通,了解他/她不愿意参与项目的原因。可能是因为个人问题、工作压力过大、对项目不感兴趣或其他原因。
    • 表达关心:表达我对他的关心和理解,让他/她感受到团队的支持和关心。
  2. 明确期望

    • 重申项目重要性:向该团队成员重申项目的重要性和紧迫性,让他/她明白项目对团队和公司的重要性。
    • 明确职责:明确他/她在项目中的职责和任务,确保他/她清楚自己的工作内容和期望。
  3. 提供支持

    • 帮助解决问题:如果他/她遇到困难或问题,我会提供必要的支持和帮助,例如调整任务难度、提供培训或资源支持。
    • 激励措施:如果可能,我会提出一些激励措施,例如额外的奖励或认可,以提高他/她的积极性。
  4. 调整任务分配

    • 重新分配任务:如果该团队成员确实无法在短时间内完成任务,我会考虑重新分配任务,将一些任务分配给其他团队成员,确保项目能够按时完成。
    • 优化工作流程:优化工作流程,减少不必要的工作量,确保每个任务都能高效完成。
  5. 持续监控与反馈

    • 定期检查:定期检查该团队成员的工作进展,及时发现问题并提供反馈。
    • 正面激励:对于他/她的积极表现,及时给予正面激励,增强他/她的自信心和积极性。
  6. 向上级汇报

    • 及时沟通:如果问题无法解决,我会及时向上级汇报情况,寻求更多的支持和建议。
    • 制定解决方案:与上级共同制定解决方案,确保项目能够顺利进行。

    面试官可能的追问及回答

    追问 1:如果团队成员摆烂的原因是个人问题,你会怎么做?

    回答: 如果团队成员摆烂的原因是个人问题,我会采取以下措施:

    • 表达关心:首先,我会表达我对他的关心和理解,让他感受到团队的支持和关心。
    • 提供帮助:询问他是否需要帮助,例如调整工作时间、提供心理支持等。如果问题严重,我会建议他寻求专业的帮助。
    • 灵活调整:根据他的情况,灵活调整任务分配,确保项目能够顺利进行,同时不影响他的个人问题解决。
    • 持续关注:持续关注他的情况,定期与他沟通,确保他能够尽快恢复状态。

5 问了家庭基本情况,是否愿意接受加班,能否在无锡定居?

1. 家庭基本情况

回答: 我的家庭非常支持我的职业发展。我的父母和伴侣都非常理解我的工作性质,知道有时候工作可能会比较忙碌。他们总是鼓励我追求自己的职业目标,并且愿意在需要的时候给予我支持。我的家庭环境很和谐,这让我能够全身心地投入到工作中。

2. 是否愿意接受加班

回答: 我理解加班是工作中不可避免的一部分,尤其是在项目紧急或任务繁重时。我认为加班本身并不是目的,而是为了确保项目能够按时交付、质量达标的一种手段。如果加班能够帮助团队完成重要任务,我会毫不犹豫地参与其中。

不过,我也相信通过合理的时间管理和高效的工作方式,可以在一定程度上减少不必要的加班。例如,提前规划工作流程、优化任务分配、提高工作效率等,都能帮助我们在正常工作时间内完成更多任务。

总的来说,我愿意在必要时加班,但同时也会努力提高工作效率,尽量减少加班的频率,以保持良好的工作与生活平衡。

3. 能否在无锡定居

回答: 我非常愿意在无锡定居。无锡是一个充满活力和发展机会的城市,我很看好这里的职业前景和生活环境。我已经开始了解无锡的住房市场,并且正在考虑合适的居住地点。我相信,通过努力工作和合理规划,我能够在无锡建立一个稳定的生活和职业基础。

理想中工作的样子

我希望工作内容能激发我的热情,让我专注于自己感兴趣的领域,比如嵌入式系统开发,同时有机会接触前沿技术,保持多样化任务,避免重复枯燥。在职业发展上,公司能提供清晰的晋升路径、丰富的培训资源和导师指导,让我能参与重要项目,实现自我价值。

工作环境舒适,配备先进设备,注重员工健康,这是基础保障。团队合作方面,我期待与优秀、有责任心的同事共事,大家相互支持、沟通顺畅,公司倡导合作文化,领导信任员工,给予自主空间。

工作与生活平衡也很重要,合理的工作时间、灵活的工作安排、完善的假期福利,能让我保持身心健康。公司文化要积极向上,鼓励创新,对失败宽容,同时注重社会责任,内部信息透明,决策公平公正。

薪酬待遇要合理,有绩效奖金和年终奖,最好还有股权激励,让我能分享公司成长。最重要的是,我的工作要有意义,能得到认可和奖励,让我感受到自己的价值。

自己的优缺点

我的优点

  • 学习能力强:能够快速掌握新技术和知识。例如,我曾自学并成功移植了一个新的嵌入式驱动程序。
  • 责任心强:对工作认真负责,确保任务高质量完成。曾加班加点解决项目中的技术难题,确保按时交付。
  • 团队合作好:善于与不同背景的同事沟通协作,乐于分享经验,共同推动项目进展。
  • 问题解决能力强:面对困难时,能冷静分析并迅速找到解决方案,多次成功解决开发中的复杂问题。

我的缺点

  • 追求完美:有时会因过度追求完美而花费过多时间优化细节,影响项目进度。我正在学习在质量与效率之间找到平衡。
  • 沟通不够主动:在团队讨论中,我有时不够主动表达自己的想法,更倾向于先倾听他人意见。我正在努力提升自己的沟通主动性。
  • 时间管理能力有待提高:有时会因专注于某项任务而忽略其他任务的进度,正在通过使用时间管理工具来改进。

抗压能力

我的抗压能力

  • 能够承受压力:我能够很好地应对工作中的压力,保持冷静和专注。例如,在之前的一个紧急项目中,我们面临紧迫的交付期限和复杂的技术挑战,但我通过合理安排时间和高效解决问题,成功按时完成了任务。

  • 善于调整心态:面对压力时,我会积极调整心态,将压力转化为动力,保持乐观和积极的态度。

  • 有效的时间管理:我会通过合理规划任务和优先级,确保在压力下也能高效完成工作。

13.有对华勤有了解吗?
华勤是一家规模很大的上市公司。主要接受品牌方的委托,生产,研发,设计笔记本、手机等。有点狼性文化。
14.对于加班怎么看?
如果给的多,我爱加班。
15.期望毕业的薪资
12k/月
反问
1.实习生待遇
大概本科160元/天,硕士200元/天,具体开会讨论过后,会有人事联系你。

image-20250603204902571

二面(综合)

自我介绍,询问了项目的一些基本问题(项目负责哪部分,遇到什么问题,怎么解决的)。就业选择公司看重哪些点?如果别人给你批评建议你会如何对待?平常玩游戏吗(玩cs)?你觉得怎么才能赢得游戏(团队协作)?本科期间c语言考试多少分?c++掌握程度怎么样,如何学习的?你觉得c和c++有什么区别?你的职业规划有哪些?堆和栈有什么区别?你觉得自己有什么优缺点?平常有什么爱好?

面试官人很好,特别温和的一种感觉,然后说是做平板开发(安卓开发,说是比较难,也还是C语言的)

问家庭情况,问是否愿意去无锡

华勤一面就是八股,进线程,驱动问的多,会问到uboot和系统移植等相关问题,最后加一个简单的手撕代码,二面的话项目上深问一下

反问:

24.驱动开发主要针对哪些方面

  1. 硬件设备的初始化和配置
    驱动程序负责初始化硬件设备,设置其工作模式和参数。例如,在我参与的智能家居项目中,我为DHT11温湿度传感器和SG90伺服电机控制器等外设编写了驱动程序,确保它们能够在系统启动时正确初始化并进入工作状态。
  2. 硬件设备的通信接口
    驱动程序需要管理硬件设备的通信接口,如GPIO、I2C、SPI、UART等。这些接口用于设备之间的数据传输和控制信号传递。在Linux智能家居系统项目中,我成功移植并实现了这些接口的驱动程序,确保了硬件设备与系统之间的稳定通信。
  3. 硬件设备的中断处理
    驱动程序需要处理硬件设备产生的中断信号。中断处理是确保设备能够及时响应外部事件的关键。例如,在智能家居系统中,我实现了高效的中断处理机制,确保设备能够实时响应用户的操作和环境变化。
  4. 硬件设备的状态管理
    驱动程序需要监控和管理硬件设备的状态,包括设备的开启、关闭、故障检测等。在项目中,我通过设备树(Device Tree)配置和Pinctrl子系统,动态管理硬件设备的引脚功能,提高了系统的灵活性和可靠性。
  5. 与操作系统的集成
    驱动程序需要与操作系统紧密集成,提供设备的抽象接口,使得应用程序能够通过标准的系统调用访问硬件设备。在Linux环境下,我熟悉设备树配置和内核模块的开发,能够确保驱动程序与Linux内核的无缝集成。
  6. 性能优化
    驱动程序的性能直接影响到整个系统的响应速度和效率。在开发过程中,我通过代码优化和硬件资源的合理配置,确保驱动程序的高效运行。例如,在智能家居项目中,我优化了驱动程序的代码,减少了CPU的占用率,提高了系统的整体性能。

总结

驱动开发主要针对硬件设备的初始化、通信接口管理、中断处理、状态管理、与操作系统的集成以及性能优化。通过这些工作,驱动程序能够确保硬件设备在系统中的稳定运行,并为应用程序提供高效、可靠的访问接口。

25.对我面试表现评价如何给出建议(要对基础知识进一步加深 因为我有几个答得不是很好)

26.公司加班一般时间是多久

1.贵公司的培养机制

反问:食宿补贴(应届生第一年免费住宿 明天15交通费+餐补)

试用期时长及待遇(三个月 比正式少500)

2.对我的评价

6 反问: 面试结果反馈多久,华勤加班情况,跟我具体聊了华勤真实的加班情况

实习生培养模式(说的有点长,忘了,反正就是说有人带)

业务是什么(bios开发,他这边主要是固件一块)