嵌入式面试核心:从C语言底层到系统设计的工程思维解析

java完整实现各种类型的文件上传和下载 此项目为web项目,需要部署在Tomcat6.0中。此项目用fileupload实现了文件上传,实现了遍历磁盘目录下及其子目录中的内容,并提供下载。 一、文件上传部分 1.访问地址为 http://localhost/UploadAndDownload/index.jsp 2.点击页面上的加一个会增加一个上传按钮,实现同时上传多个文件。 3.如果是eclipse开发工具,上传之后的文件保存在路径D:\develop\resource\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\UploadAndDownload\WEB-INF\upload 4.其中D:\develop\resource为项目所在的路径。 5.读者可以通过在这条代码前面通过断点来查看eclipse运行环境下的文件上传之后保存的路径。String path = this.getServletContext().getRealPath("/WEB-INF/upload"); 二、文件下载部分 1.访问地址一 http://localhost/UploadAndDownload/download.jsp 该地址实现的是通过超链接下载。 2.访问地址二 http://localhost/UploadAndDownload/downloadlist.jsp 该地址实现的是通过后台代码实现下载。 3.在访问地址二时,会遍历本地电脑中的一个文件夹,改文件夹在我自己电脑上的位置是D://music(该地址是在downloadlist.jsp中设置的),读者需要根据自身情况来设置文件夹的路径。 立即下载

1. 项目概述:为什么嵌入式面试题值得深挖?

干了十几年嵌入式,从单片机玩到Linux,也面过不少人,也被人面过。我发现一个挺有意思的现象:很多朋友,尤其是刚入行或者准备转行的,一提到“嵌入式面试题”,第一反应就是去网上搜罗一堆“八股文”,然后开始死记硬背。什么“进程和线程的区别”、“I2C和SPI的时序”、“大小端模式”……背得滚瓜烂熟,但一遇到实际项目里的坑,或者面试官稍微换个角度问深一点,立马就露怯了。

这其实是个误区。嵌入式面试,尤其是针对有经验的工程师,考察的绝不仅仅是知识点的记忆。它更像是一次“技术体检”,面试官通过一系列问题,试图摸清你的技术底子、解决问题的思路、项目经验的含金量,甚至是你面对压力时的反应。那些题目本身,只是引子,背后串联的是整个嵌入式开发的知识体系和工程实践能力。

所以,今天我们不搞简单的题库罗列。我想结合我这些年面试别人和被面试的经验,以及带新人的体会,来一次深度的“面试题解构”。我们会围绕几个核心的、高频出现的面试主题,不仅告诉你“标准答案”是什么,更要拆解面试官“为什么这么问”,以及在实际工作中“这个问题对应着怎样的场景和挑战”。无论是你正在准备面试,还是想系统梳理自己的嵌入式知识体系,相信这篇长文都能给你带来实实在在的启发。咱们的目标不是背题,而是建立一种“见题拆题”的思维模式,让你能从任何一个问题出发,展现出你真正的技术实力。

2. 核心主题深度拆解:从八股文到工程思维

嵌入式面试题覆盖面极广,从C语言基础到硬件原理,从操作系统内核到网络协议,再到具体的驱动、应用开发。但万变不离其宗,我们可以将其归纳为几个核心的考察维度。理解这些维度,你就能以不变应万变。

2.1 维度一:C语言与底层理解——嵌入式的地基

这是嵌入式开发的立身之本。面试官在这里挖的坑,往往不是为了考语法,而是看你是否理解计算机如何工作。

经典问题1: volatile 关键字有什么用?在什么场景下必须使用?

  • 表面考点 :一个C语言关键字。
  • 深度考察点 :你对内存访问、编译器优化、以及硬件交互的理解。
  • 标准答案速记 volatile 告诉编译器,这个变量的值可能会被程序之外的代理改变(如硬件寄存器、中断服务程序、多线程共享变量),因此编译器不应对其进行优化(如缓存到寄存器、省略“冗余”读取),每次使用都必须从内存中重新读取。
  • 工程场景与“为什么”
    1. 内存映射的硬件寄存器 :这是最典型的场景。比如你定义了一个指针指向GPIO的数据寄存器 uint32_t *pReg = (uint32_t*)0x40020000; 。你通过 *pReg = 1; 来点亮一个LED。如果没有 volatile ,聪明的编译器可能会认为“既然程序里紧接着没有再次修改 *pReg 的代码,那么我第二次读取 *pReg 的值肯定还是1”,于是它可能优化掉第二次实际的读内存操作,直接从缓存或寄存器里给你返回1。但问题是,这个寄存器的值可能被外部硬件(比如按下了按钮)改变了!你必须用 volatile uint32_t *pReg 来确保每次 *pReg 都是真的去那个物理地址读。
    2. 多线程/中断共享的全局变量 :一个在中断服务程序(ISR)里修改的全局标志位 flag ,在主循环里判断。如果 flag 不是 volatile ,编译器可能把主循环中的 while(!flag); 优化成 if(!flag) while(1); ,因为编译器认为循环内 flag 没被修改,这会导致死锁。
    3. 空循环延时 :有些简陋的延时函数会写 for(i=0; i<10000; i++); 。如果循环变量 i 不是 volatile ,编译器可能发现这个循环没有副作用,直接把它整个优化掉,延时效果就没了。

实操心得 :不要滥用 volatile 。它会影响编译器优化,可能降低性能。只在确有必要(变量可能被外部改变)时才使用。另外, volatile 不能保证原子性,在多核或复杂并发场景下,还需要结合内存屏障( barrier )或原子操作来保证数据一致性。

经典问题2:解释一下“大小端”(Endianness)。如何用C代码检测当前系统的大小端?

  • 表面考点 :一个计算机基础概念。
  • 深度考察点 :你对数据在内存中存储格式的理解,以及编写可移植代码的意识。
  • 标准答案速记 :大端模式(Big-endian)将数据的高位字节存储在低地址,小端模式(Little-endian)将数据的低位字节存储在低地址。网络字节序通常是大端。
  • 工程场景与“为什么”
    1. 处理器差异 :ARM架构通常是小端(可配置),PowerPC是大端,x86是小端。当你进行跨平台开发(比如在x86 PC上调试ARM目标板的代码)时,必须注意。
    2. 协议解析 :很多网络协议(如TCP/IP头)规定使用大端字节序。当你从网络接收一个 uint32_t 的数据包长度字段时,必须用 ntohl() 函数将其从网络字节序(大端)转换成本机字节序才能正确使用。
    3. 硬件寄存器与数据手册 :阅读芯片数据手册时,经常会看到寄存器位域的描述。理解大小端有助于你正确设置和读取这些寄存器,特别是当寄存器宽度大于8位时。
  • 检测代码与原理
    #include <stdio.h>
    int main() {
        union {
            int i;
            char c;
        } u;
        u.i = 1;
        if (u.c == 1) {
            printf("Little Endian\n"); // 低地址存的是低位字节(1)
        } else {
            printf("Big Endian\n"); // 低地址存的是高位字节(0)
        }
        return 0;
    }
    
    原理 :联合体( union )的所有成员共享同一块内存。我们让一个 int (假设4字节) 和一个 char 共享内存。将 int 赋值为1(二进制 0x00000001 )。在小端机器上,低位字节 0x01 存放在最低地址,所以 char c 读到的是1。在大端机器上,高位字节 0x00 存放在最低地址,所以 c 读到的是0。

2.2 维度二:操作系统核心概念——嵌入式系统的大脑

无论是裸机轮询、RTOS还是Linux,操作系统的概念都是面试的重中之重。这里考察的是你如何管理复杂的系统资源。

经典问题3:请详细说明进程和线程的区别与联系。

  • 表面考点 :操作系统基础概念。
  • 深度考察点 :你对程序并发执行单元的理解,资源开销、通信、安全性的权衡。
  • 标准答案速记 :进程是资源分配的最小单位,拥有独立的地址空间;线程是CPU调度的最小单位,共享进程的资源。
  • 工程场景与“为什么”
    特性 进程 线程 嵌入式场景下的考量
    资源 独立地址空间,代码、数据、堆栈独立,资源消耗大(MB级)。 共享进程的地址空间和资源(打开的文件、全局变量等),资源消耗小(KB级)。 在内存紧张的MCU上,创建多个进程几乎不可能,常用多线程或任务。在Linux嵌入式设备上,对于需要强隔离的模块(如一个视频解码服务和一个网络服务),用进程更安全。
    通信 通信复杂,需要IPC机制:管道、消息队列、共享内存、信号量、Socket等。 通信简单,直接读写共享的全局变量即可(但需同步机制保护)。 线程间通信效率高,但bug难以排查(一个线程写坏内存,所有线程遭殃)。进程间通信有内核介入,开销大但隔离性好。
    崩溃影响 一个进程崩溃一般不会影响其他进程。 一个线程崩溃(如段错误)会导致整个进程崩溃,所有线程终止。 在可靠性要求高的嵌入式系统中,需要谨慎设计线程,或使用一些保护机制(如看门狗监控关键线程)。
    创建/切换开销 开销大,涉及资源分配和内存管理。 开销小,主要涉及寄存器上下文切换。 在实时性要求高的场合(如RTOS),任务(线程)切换速度是关键指标。
    • 联系 :线程是进程内部的执行流。一个进程至少有一个线程(主线程)。

注意事项 :在嵌入式Linux中,使用多线程( pthread )时要特别注意线程安全。对共享资源的访问必须加锁(互斥锁 mutex )。我曾遇到一个Bug,一个线程在遍历链表时,另一个线程删除了某个节点,导致遍历指针失效,程序崩溃。这就是典型的同步问题。

经典问题4:什么是内存泄漏?在嵌入式C程序中,常见的泄漏点有哪些?如何检测和避免?

  • 表面考点 :编程常见问题。
  • 深度考察点 :你的资源管理意识、调试能力和对系统长期稳定运行的理解。
  • 标准答案速记 :程序动态申请的内存( malloc , calloc , new 等)在使用完毕后没有释放,导致可用内存逐渐减少,最终可能耗尽。
  • 工程场景与“为什么” : 嵌入式设备,特别是那些需要7x24小时长期运行的设备(如网关、监控设备),内存泄漏是致命的。它不像PC程序,重启一下就行。设备可能部署在野外,重启意味着服务中断。
    • 常见泄漏点
      1. malloc/free 不成对出现 :这是最直接的。在复杂的条件分支或错误处理路径中,容易忘记释放。
      2. 文件/资源句柄未关闭 fopen 后没有 fclose open 后没有 close 。在Linux中,这也会消耗内核资源。
      3. 使用第三方库 :某些库的API要求调用者负责释放内存,如果没仔细看文档,就会漏掉。
      4. 数据结构设计缺陷 :例如,一个动态增长的链表,在删除节点时只修改了指针,没有 free 节点本身的内存。
    • 检测方法
      • 代码审查 :养成好习惯,看到 malloc 就立刻找对应的 free
      • 工具
        • Valgrind (Linux) :神器。 valgrind --leak-check=full ./your_program 可以精确定位泄漏点和大小。
        • mtrace (glibc) :在代码中插入 mtrace() / muntrace() ,设置 MALLOC_TRACE 环境变量,可以生成日志分析。
        • 嵌入式平台 :可能没有Valgrind。可以重写 malloc/free 函数,加入计数和日志功能,或者在链接时使用 -wrap 选项包装这些函数。
    • 避免策略
      1. 谁申请,谁释放 :这是一个基本原则,最好在同一个函数或同一个模块层次内完成。
      2. 使用RAII思想 :C++中利用构造函数/析构函数自动管理。C语言可以模拟,比如定义一个 ScopedMalloc 结构体,在离开作用域时自动释放。
      3. 静态分析工具 :如 Coverity , Cppcheck ,可以在编码阶段发现一些潜在泄漏。
      4. 压力测试 :让程序长时间、高负荷运行,监控内存使用量(如通过 /proc/meminfo ps 命令),观察是否持续增长。

2.3 维度三:外设通信与总线协议——嵌入式与世界的桥梁

这是嵌入式独有的领域,直接和硬件打交道。面试官想确认你不是只会写软件,也懂硬件如何协同。

经典问题5:对比I2C、SPI和UART这三种常见串行通信协议。

  • 表面考点 :三种协议的区别。
  • 深度考察点 :你如何根据项目需求(速度、距离、引脚数、复杂度)选择合适的通信方式。
  • 标准答案与工程选型
    特性 I2C SPI UART
    全称 Inter-Integrated Circuit Serial Peripheral Interface Universal Asynchronous Receiver/Transmitter
    通信方式 同步、半双工 同步、全双工 异步、全双工
    信号线 2根 :SCL(时钟)、SDA(数据)。支持多主多从。 至少3根 :SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)。 片选CS每从机一根 2根 :TX(发送)、RX(接收)。点对点。
    速度 标准模式100kbps,快速模式400kbps,高速模式3.4Mbps。速度较慢。 速度高,可达几十Mbps甚至更高,取决于控制器和布线。 常见波特率从9600到几Mbps,速度适中。
    寻址方式 7位或10位从机地址,通过SDA广播,节省引脚。 硬件片选(CS),通过单独的线选通从机,引脚占用多。 无寻址,物理连接决定通信对象。
    复杂度 协议复杂,有时序要求(起始、停止、应答位),需要上拉电阻。软件模拟相对复杂。 协议简单,基本上是时钟沿同步移位数据。软件模拟容易。 协议简单,固定格式(起始位、数据位、校验位、停止位)。
    典型应用 连接低速片上外设:EEPROM、传感器(温湿度)、RTC、IO扩展芯片等。 连接高速外设:Flash存储器、SD卡、显示屏、ADC/DAC芯片、无线模块等。 调试串口(Console)、连接GPS/蓝牙模块、与PC通信、旧式设备互联。
    • 工程选型思考
      • 需要连接很多同类型传感器,且MCU引脚紧张? I2C ,因为它地址寻址,只需要两根线串联所有设备。但要小心地址冲突和总线拉低问题。
      • 需要高速传输大量数据,比如读写Flash或刷新屏幕? SPI ,它速度最快,且是全双工。缺点是每个从机需要独占一个片选引脚。
      • 只是简单的双向数据透传,或者用于调试打印? UART ,它最简单,最通用,接线方便。缺点是缺乏时钟同步,长距离或高波特率时对时钟精度要求高。

经典问题6:I2C协议中,为什么需要上拉电阻?阻值如何选择?

  • 表面考点 :一个硬件细节。
  • 深度考察点 :你对开漏输出(Open-Drain)电路原理的理解,以及理论联系实际(计算)的能力。
  • 标准答案速记 :I2C总线采用开漏输出,本身无法输出高电平,需要上拉电阻将总线拉至高电平,以实现“线与”功能。
  • 原理详解 : I2C的SDA和SCL线路上,主设备和所有从设备的对应引脚都配置为 开漏输出 模式。开漏输出就像一个接地的开关:当输出0时,内部MOS管导通,将线路拉低到GND;当输出1时,内部MOS管关闭,引脚处于高阻态(悬空), 无法主动输出高电平 。 这时,如果总线上没有上拉电阻,当所有设备都输出1(即释放总线)时,总线就处于浮空状态,电平不确定,极易受到干扰。因此,必须在电源VCC和SDA/SCL线之间各接一个上拉电阻(Rp)。当设备释放总线(输出1)时,上拉电阻将总线电压拉至高电平(VCC)。 “线与”功能:因为任何设备都可以拉低总线(输出0),而拉高是靠电阻,所以总线电平是“所有设备输出的逻辑与”。只要有一个设备输出0,总线就是0;所有设备都输出1,总线才是1。这是实现多主仲裁的基础。
  • 阻值计算与选择 : 这是一个经典的权衡问题。电阻值不能随便选。
    1. 下限(最小值) :由最大允许电流决定。当总线被拉低时,电流从VCC通过上拉电阻流到地。电流 I = VCC / Rp 。这个电流不能超过IO引脚的最大灌电流(sink current,通常几个mA到20mA)。例如,VCC=3.3V,引脚最大灌电流为20mA,则 Rp_min = 3.3V / 0.02A = 165Ω 。通常我们会留有余量。
    2. 上限(最大值) :由总线电容和上升时间决定。总线不是理想的,它有寄生电容(Cb),来自导线、设备引脚等。当设备释放总线(从0变1)时,上拉电阻需要给这个电容充电,电压从低到高有一个上升时间。上升时间 Tr ≈ 0.35 / (Rp * Cb) (简化RC充电模型)。I2C规范对上升时间有要求(例如,标准模式要求Tr < 1000ns)。如果Rp太大,充电太慢,上升时间过长,会导致在高速模式下采样出错。
    • 经验值 :对于3.3V系统,总线电容不大(<100pF)的情况下, 4.7kΩ 是一个非常常用且安全的值。在5V系统或总线较长、设备较多(电容大)时,可以考虑 2.2kΩ 1kΩ 。在超低功耗设备中,为了降低静态电流(总线为高时的电流 I = VCC/Rp ),可能会用到 10kΩ ,但要确保上升时间满足要求。

踩坑实录 :有一次调试一个I2C设备老是失败,逻辑分析仪看波形发现上升沿非常缓。查了半天,发现PCB布局上I2C总线走了很长一段线,且靠近其他高频信号线,导致寄生电容很大。而设计时用了10kΩ的上拉电阻,充电太慢。换成2.2kΩ后问题立刻解决。所以,上拉电阻不是照抄原理图就行,要根据实际板级情况调整。

3. 实战模拟:如何应对系统设计类问题

这类问题没有标准答案,最能体现工程师的综合能力。面试官会给你一个模糊的需求,看你怎么拆解、设计和权衡。

经典问题7:设计一个简单的温湿度监控系统,传感器通过I2C连接,要求每分钟采集一次数据,并通过4G模块上报到云端。如果网络异常,数据需要本地缓存。请描述你的软件架构设计思路。

  • 问题剖析 :这不是问你怎么写I2C驱动,而是考察 多任务管理、状态机设计、数据流处理、错误处理 等系统级能力。

  • 回答思路与分层设计

    1. 硬件抽象层(HAL)
      • 封装I2C底层操作,提供 sensor_read_temp_humidity() 这样的函数。内部处理可能的I2C通信错误,返回统一格式的数据或错误码。
      • 封装4G模块的AT指令操作,提供 network_send_data() network_check_status() 等函数。将复杂的AT指令交互隐藏起来。
    2. 数据采集任务
      • 创建一个独立的线程或RTOS任务,命名为 Task_Sensor
      • 内部使用一个1分钟的定时器(如 sleep(60) vTaskDelay(60000) )来周期性触发。
      • 每次触发时,调用HAL层的传感器读取函数。
      • 将读取到的数据(加上时间戳)放入一个 线程安全的队列 (如FreeRTOS的Queue,或自己用环形缓冲区+互斥锁实现)中。这个队列是连接采集任务和上传任务的桥梁。
      • 错误处理 :如果连续几次读取失败,应记录错误日志,并可能尝试复位传感器(如果硬件支持)。
    3. 数据上传与缓存任务
      • 创建另一个线程 Task_Upload
      • 它的主循环不断尝试从队列中取出数据。
      • 网络正常时 :取出数据,调用 network_send_data() 发送。发送成功后,确认数据已处理(从队列中移除或标记为已发送)。
      • 网络异常时 :这是关键。不能丢弃数据。
        • 本地缓存设计 :可以使用一个 非易失性存储器 (如SPI Flash的一块区域,或SD卡上的一个文件)作为缓存池。当发送失败时,将数据(包括时间戳)追加写入这个缓存池,并记录当前写入位置。
        • 缓存管理 :需要设计简单的格式,比如每条记录定长,或添加帧头帧尾。需要考虑缓存满的情况(循环覆盖或停止采集?取决于业务重要性)。
      • 网络恢复处理 Task_Upload 需要定期(例如每5秒)检查网络状态 network_check_status() 。当检测到网络恢复时, 优先发送缓存中的数据 。从缓存池中按顺序读取未发送的数据,尝试发送,发送成功后标记该数据为已发送(或删除),直到缓存清空,再恢复正常的数据采集-上传流程。
    4. 系统监控与看门狗
      • 考虑增加一个硬件看门狗,防止程序跑飞。
      • 可以在 Task_Sensor Task_Upload 中定期“喂狗”。如果某个任务卡死,看门狗超时复位系统。
      • 还可以增加一个低优先级的心跳任务,通过串口或LED输出系统状态,便于调试。
  • 可能被追问的细节

    • 队列怎么实现? 可以用数组实现环形缓冲区,用互斥锁保护读写指针。要处理好满和空的状态判断。
    • 缓存存在Flash里,频繁写会不会损坏Flash? 会。需要做 写均衡 (Wear Leveling)。可以设计将缓存区模拟成多个块(block),轮流写入;或者使用专为频繁写设计的文件系统(如LittleFS)。
    • 如果上传任务正在发送缓存数据,此时新的采集数据来了怎么办? 队列仍然可以接收新数据。上传任务发送完一条缓存数据后,可以检查队列是否有新数据,优先发送新数据(保证实时性),再继续发送旧缓存。或者设计两个优先级不同的队列。
    • 如何保证时间戳准确? 如果设备有RTC(实时时钟),最好用RTC时间。如果没有,可以在上电时从网络获取一次时间(NTP),然后用MCU的定时器进行软件计时。但软件计时会累积误差。

4. 独家避坑指南与面试技巧

除了技术本身,面试中的软技能和策略同样重要。这里分享一些我作为面试官和面试者的心得。

4.1 技术问题回答的“STAR”法则变形

对于项目经验类问题(“讲一个你最熟悉的项目”、“遇到的最大挑战是什么”),不要平铺直叙。用“背景-任务-行动-结果”的结构来组织语言。

  • S(情境) :项目是做什么的?你的角色是什么?(例如:“我负责一个基于STM32的智能家居网关的嵌入式软件部分”)
  • T(任务) :你接到什么具体任务?要解决什么问题?(例如:“需要实现一个OTA升级功能,要求升级过程不掉电、可回滚”)
  • A(行动) 这是重点! 你具体做了什么?用了什么技术方案?为什么这么选?(例如:“我设计了A/B双分区机制。分区A运行当前固件,分区B用于下载和验证新固件。我选用了SHA-256进行固件完整性校验,因为比MD5更安全。下载使用HTTP断点续传,以应对不稳定的网络。最关键的是,我在Flash中设计了一个状态标志位,用来标识升级的各个阶段…”)这里要突出你的技术决策和动手过程。
  • R(结果) :最终效果如何?有什么量化指标吗?(例如:“最终功能稳定上线,升级成功率达到99.9%以上。我还写了一个模拟掉电的测试脚本,验证了回滚机制的有效性。”)

4.2 遇到不会的问题怎么办?

这是常态,处理好了是加分项。切忌不懂装懂,胡说八道。

  1. 坦诚承认 :“抱歉,这个问题我之前没有深入研究过。” 诚实比欺骗好一万倍。
  2. 展示思考过程 :“不过根据我的理解,这个问题可能和XX领域相关。如果是我的话,我可能会从A和B两个角度去尝试解决…” 即使方向不完全对,也能展示你的逻辑思维和学习能力。
  3. 转化为学习机会 :“您提的这个问题很有意思,能告诉我一些关键词或者方向吗?我面试结束后一定会去好好学习一下。” 表现出积极好学的态度。

4.3 提问环节的艺术

面试最后,面试官通常会问“你有什么问题想问我们?”。这是一个双向选择的机会,也能体现你的思考深度。

  • 避免问 :薪水福利(后续谈)、加班多不多(负面暗示)。
  • 可以问
    • 关于团队和技术 :“咱们这个团队目前主要的技术栈是什么?接下来半年重点要攻克的技术挑战是什么?”(显示你对工作的兴趣和规划)
    • 关于项目 :“如果我加入,可能会参与哪个产品线或项目?这个项目目前处于哪个阶段?”(显示你的投入意愿)
    • 关于成长 :“公司对于工程师的技术成长有哪些支持?比如内部技术分享、外部培训的机会?”(显示你积极上进)
    • 关于面试反馈 :“针对我刚才的表现,您觉得我在哪些方面还需要加强?”(非常积极的信号,表明你渴望进步)

4.4 知识体系自查清单

在面试前,可以按这个清单快速过一遍自己的知识储备:

  • C语言 :指针(多级指针、函数指针)、内存布局(栈、堆、静态区)、 const / static / volatile / extern 关键字、位操作、结构体对齐、预处理器。
  • 数据结构 :链表(单/双)、队列、栈、哈希表(在嵌入式中的应用场景)。
  • 单片机/ARM :中断流程(压栈、跳转、返回)、时钟树、功耗管理、看门狗、DMA原理。
  • RTOS :任务调度(优先级、抢占、时间片)、任务间通信(信号量、互斥量、消息队列、事件标志)、内存管理(堆、池)、中断管理与任务同步。
  • Linux驱动 :字符设备驱动框架( file_operations )、设备树(DTS)概念、平台设备驱动、中断处理(顶半部/底半部)、内核同步机制(自旋锁、信号量)、设备模型。
  • 网络 :TCP/IP协议栈基础(三次握手、滑动窗口)、Socket编程、常用网络工具( ping , ifconfig , netstat )。
  • 调试 :日志系统设计、GDB调试基础(断点、查看内存、回溯)、 strace / ltrace 工具、内存检测工具。
  • 硬件基础 :看懂原理图(寻找芯片、电源、复位、晶振、外设接口)、使用万用表、示波器、逻辑分析仪。

面试就像一场开卷考试,题目无穷无尽,但考点是有限的。这篇长文试图为你勾勒出这些核心考点和背后的逻辑。真正的准备,不在于背下这里所有的文字,而在于通过这些问题,去反查自己知识体系中的薄弱环节,去思考“如果是我,我会怎么做”。带着这种“工程师思维”去面试,无论遇到什么问题,你都能从容应对,展现出你真正的价值。最后,保持自信,保持沟通的热情,技术之路,终将眷顾那些持续思考和动手的人。

FormData实现文件上传(前端+后端) 文件上传,包括前端和后端的核心代码,IE8无法获取文件真实路径,可以通过该方法来实现文件上传,使用的是FormData传递文件数据。 立即下载

相关推荐

javaweb简单实现文件上传与下载源代码

javaweb简单实现文件上传与下载源代码,仅供参考

Web文件下载总结

web文件下载是业务常见的需求场景

曹定栓的博客 2016

ollama服务暴露公网?三步搞定Nginx反向代理配置(避坑指南)

本文详细介绍了如何通过Nginx反向代理安全地将Ollama服务暴露到公网,避免直接修改OLLAMA_HOST带来的安全隐患。文章提供了从SSL证书部署到高级安全加固的全流程实战指南,包括IP白名单、基础认证、速率限制等企业级安全措施,帮助用户实现安全可靠的外部访问。

wood5的博客 160

java后端上传文件到服务器,下载服务器文件到本地

java后端上传文件到服务器,下载服务器文件到本地

weixin_41592847的博客 722

后端文件上传及下载

文件上传下载

qq_45524787的博客 413

文件上传下载 Upload&Download

文件的上传下载 Upload&Download (一)文件的上传 文件的上传即将本地文件上传到远程服务器端 文件上传的流也需要放到一个表单中 2、文件上传的表单的要求 文件上传的表单需要设置的请求方式是POST请求 文件上传的表单项的type属性需要指定为:file<input type="file" name="photo">给form表单添加一个enctype属性 该属性的默认值是:applic

xiongfeng 4243

Vue项目-后端接口文件上传下载

【代码】Vue下载文件。

StupidlyGrass的博客 2435

File Upload Download For iOS

本文内容来自于王志刚 《软件创富密码:iPhone应用程序开发攻略之深入浅出Objective-C 2.0》一书,修改了部分内容。 截图如下: Download: 代码如下: // // AppController.h // File Upload Download // // Created by longx-app on 13-9-15. // Copyright

ALDRIDGE1的专栏 2043

Upload and Download File using Java

1.Upload Control ①Apache的Commons FileUpload ②JavaZoom的UploadBean ③JspSmartUpload 2.DownloadFileUploadCommons Control Official Website:http://commons.apache.org/fileupload/ ...

weixin_30867015的博客 169

golang gin download and upload file

func main() { router := gin.Default() router.GET("/api/v1/attachments/:file",DownloadAttachmentHandler) router.POST("/api/v1/attachment/files", UploadAttachmentFileHandler) // Listen and serve on 0.0.0.0:8080 r.Run(":8080") } // Uplo.

ezreal_pan的博客 3626

Flask:web中添加 upload file and download file 功能

在form表单中添加file; <form action={{url_for('download')}} method='POST' enctype="multipart/form-data"> <input type="file" name='file'> <br> <button type="submit">Submit</button>

BLUEsang的博客 443

file-upload-download

使用 try-with-resources。

wsd_ontheroad的博客 462

Upload a file for download

Upload a file for downloadUpload a file for downloadUpload a file for download

feihensq的专栏 259

ABAP-Download/Upload text element into local file

Some times we want to download/upload the text symbol of text element into/from local file, we can use below report, Its very useful. **********************************************************r

Jason Zhao's Blog 711

推荐文章:使用Go构建的HTTP文件上传下载利器——golang-http-file-upload-download

推荐文章:使用Go构建的HTTP文件上传下载利器——golang-http-file-upload-download 1. 项目介绍 在互联网应用中,文件上传和下载功能是不可或缺的部分。golang-http-file-upload-download 是一个简单的Go语言实现的HTTP文件上传和下载示例项目,它提供了清晰易懂的代码结构,帮助开发者快速理解和实现相关功能。 2. 项目技术分析 该项目...

gitblog_00910的博客 968

Java_ftp_file upload and download

import java.io.File;  import java.io.FileInputStream;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream;  import org.apac...

ALL TECHNOLOGIES ARE CLOUDS 137

Work with a file upload and download controls

Table of Contents 1 Restrict the size of uploaded files2 Known Bugs for upload control3 Workaround for known bug in download control Restrict the size of uploaded filesSet in Application Prope...

ama7449的博客 128

探索Go语言的轻量级文件上传与下载:golang-http-file-upload-download项目深度剖析

探索Go语言的轻量级文件上传与下载:golang-http-file-upload-download项目深度剖析 在日常开发中,文件上传与下载功能是构建Web应用不可或缺的一环。今天,我们将探索一个简洁而高效的开源项目——golang-http-file-upload-download,它为Go(Golang)开发者提供了一个直观的HTTP文件上传和下载示例。对于那些寻求快速集成这一基本但关键功能...

gitblog_00020的博客 736
上一篇: 基于TLD 5191的LED驱动开发板实战:从PWM调光到RGB色彩混合
下一篇: YAMLET:工程化工具集解决YAML配置管理痛点,提升DevOps效率
weixin_30776545
博客等级 码龄11年 104粉丝 1357原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值