# 面试总结
面的希奥端这家公司是一个从华为出来的初创公司,做芯片研发的,整体面下来感觉问的知识点非常的底层,个人觉得是有一些难的,针对每一个知识点会由浅入深,然后深挖细问,最后还问了一个场景题,没答上来,比较难。
# 希奥端软件开发一面面经
1. 在c++中static在什么地方用,讲讲你对他的理解,举个例子讲述一下
答:我的理解是,static 的核心思想是 “控制生命周期和链接性”。
1). 对于局部变量:普通的局部变量在函数调用时创建,函数返回时销毁。
而static局部变量在第一次执行到其声明时初始化,并在程序整个生命周期中存在,后续调用函数时不会再初始化,而是保持上次的值,这实现了 “在函数调用间持久化数据” 的功能。
2). 对于全局变量和函数:在多个源文件的项目中,普通的全局变量和函数是“全局可见”的,可能会在其他文件中被意外使用或发生命名冲突。
使用static修饰后,它们就变成了 “文件作用域” 的,相当于对外隐藏了实现细节,是封装性的一种体现。
3). 对于类成员:普通的类成员属于每个对象,而static成员属于类本身,它在所有对象被创建之前就已经存在。
这非常适合用来存储 “类级别” 的共享信息,比如对象的计数、公共配置等,静态成员函数也因此不能访问需要对象实例才能确定的非静态成员。
2. 一个项目在编译的时候是怎么编出来的?在你的横向项目中编好了代码,烧录到单片机板子中时,是怎么烧录的?烧录的时候这些代码经历什么到达你的板子中的?
答: 预处理:处理以#开头的指令,如#include(展开头文件)、#define(宏替换)、#ifdef(条件编译)等,生成一个纯粹的.i文件。
编译:将预处理后的C/C++代码进行 词法分析、语法分析、语义分析、优化,最终翻译成汇编代码,生成.s文件。
汇编:使用汇编器将汇编代码翻译成 机器指令,生成 目标文件。这些文件是二进制的,但还不能直接执行,因为可能缺少外部函数的地址。在Linux下是.o文件,在Windows**下是.obj文件。
链接:链接器将一个或多个目标文件以及所需的库文件合并在一起。
它的主要工作是 地址和空间分配、符号解析和重定位,它会解析一个目标文件中调用另一个目标文件中函数的地址,最终生成一个完整的、可以被操作系统或单片机硬件加载执行的可执行文件。
3. 你对.o文件的理解是什么?从.c文件到.o文件是怎么转换过来的?代码经历了什么?
答:
.o文件是一个 可重定位 的二进制文件。可以把.o文件看作一个 零件,而链接器是 组装工人。
从.c到.o的转换过程就是 编译和汇编。
代码经历了:
翻译:将高级的C/C++代码逐句翻译成处理器能看懂的、由0和1组成的机器指令。
符号生成:编译器会为文件中的函数和全局变量生成 符号。例如,定义了一个函数void foo(),那么在目标文件中就会有一个叫foo的符号。
符号引用:如果你的代码调用了另一个文件中的函数,或者使用了库函数,编译器此时并不知道这个函数在哪。
它会在目标文件中生成一个 “未解析的符号引用”,相当于记下“这里需要函数printf的地址,但我现在不知道,链接的时候你帮我找到并填上”。
节区划分:目标文件内部会分成不同的 “节”,常见的有:
.text:存放编译后的 机器指令。
.data:存放已初始化的 全局变量和静态变量。
.bss:存放 未初始化 的全局变量和静态变量(实际上不占文件空间,只是预留位置)。
链接器的工作就是收集所有这些“零件”,把各个.o文件中的相同节区合并,然后最重要的一步——重定位:解析所有未解决的符号引用,找到其定义(在哪个.o文件或库中),然后计算出它们在最终内存空间中的 绝对地址,并把之前“留空”的地方全部填上正确的地址。
4. 计算机由哪几个模块组成?各个模块是什么?
现代计算机主要由五大模块组成:
运算器:负责算术运算和逻辑运算。
控制器:指挥整个系统协调工作,是计算机的“指挥中心”。
存储器:存放程序和数据,分为内存和外存。
输入设备:将外部信息输入计算机,如键盘、鼠标。
输出设备:将计算机处理结果输出,如显示器、打印机。
通常,运算器和控制器合称为中央处理器。
5. 讲一下计算机的冯·诺依曼体系结构和哈弗体系结构
答:冯·诺依曼结构是早期计算机的设计基础,其“存储程序”的概念是革命性的,但它的主要瓶颈在于,指令和数据共享同一总线,在高速CPU面前,内存的吞吐量成了系统性能的瓶颈。
哈佛结构通过分离指令和数据通道,解决了这个瓶颈,例如,DSP和ARM9等处理器就采用了这种结构,可以实现单时钟周期内同时完成一条指令的取指和另一条指令的数据操作。
现代PC为了兼容性和成本,CPU内部(如缓存)普遍采用哈佛结构(L1指令缓存和数据缓存是分开的),而外部内存控制器仍是冯·诺依曼结构。
6. 计算机的内存结构为什么越往里面,越小访问速度越快?外面的反之。
答: 这是由 存储器层次结构 和 局部性原理 共同决定的。
速度与成本的矛盾:速度越快的存储器,单位容量的制造成本越高。
局部性原理:程序在90%的时间里,只访问10%的数据。包括:时间局部性:刚被访问的数据,很快又会被再次访问;空间局部性:刚被访问的数据,其相邻的数据很快也会被访问。
解决方案:采用金字塔式的层次结构。用 少量、昂贵、高速 的存储器作为缓存,放在靠近CPU的地方,存放最常用的数据;用 大量、廉价、低**** 的存储器作为主存和硬盘,存放全部数据。
7. 计算机体系结构里面的组成成分是什么?他们之间是怎么协作的?
答: 组成成分:
中央处理器:包含运算器、控制器和寄存器组。
存储器:主存储器。
输入/输出系统:各种I/O设备及它们的控制器。
系统总线:连接以上所有部件的通信干线,包括:
数据总线:双向传输数据。
地址总线:单向,由CPU发出,指定要访问的内存单元或I/O端口。
控制总线:传输控制信号,如读/写、中断、时钟等。
协作流程(以执行一个程序为例):
取指令:控制器将 程序计数器 中的地址送到地址总线,通过控制总线发出“读”信号。内存将该地址对应的指令通过数据总线送回CPU,存入 指令寄存器。
指令译码:控制器分析指令寄存器中的指令,明白要做什么操作(如加法),操作数在哪。
执行指令:
如果需要数据,控制器会再次通过总线去内存中取数据。
运算器根据指令对数据进行计算。
写回结果:将运算结果写入寄存器或通过总线写回内存。
然后,程序计数器自动加1或跳转,开始下一个指令周期。
整个过程在时钟信号的同步下有条不紊地进行。
8. 场景题:当键盘输入字母a,word中能够显示指定的字母a,这个过程中计算机底层各个部分都执行了哪些任务,做了什么事?你敲a为什么显示器能显示a?写完以后保存,它保存到哪里?
答: 这是一个跨硬件、驱动、操作系统和应用的复杂协作过程。
底层硬件与中断阶段:
1).当按下‘a’键,键盘内的微控制器会检测到电路导通,生成一个唯一的扫描码。
2).键盘通过USB线将包含扫描码的数据包发送给电脑的USB主机控制器。
3).USB控制器接收到数据后,通过一根中断请求线向CPU发出一个 硬件中断信号。
操作系统内核阶段:
4). CPU收到中断,立即保存当前现场,根据 中断向量表 跳转到 键盘驱动程序 中的中断服务程序。
5). 该程序从USB控制器的寄存器中读取扫描码,然后查询 键盘映射表,将扫描码转换成对应的ASCII码 ‘a’(或宽字符)。
6). 操作系统将这个按键事件封装成一个标准的结构(如在Windows中是WM_KEYDOWN消息),并将其投递到系统消息队列。
应用程序阶段:
7). Word进程 一直在运行它的 消息循环,从它的 应用程序消息队列 中**获取到这个“按键a”**的消息。
8). Word的消息处理函数开始工作,它知道当前光标位置,于是将字符‘a’插入到文档的内存模型中。
9). 同时,Word调用InvalidateRect等API,通知系统其窗口需要重绘。
10). 在重绘过程中,Word调用GDI/DirectWrite等图形接口,计算‘a’的字体、大小、颜色,并将其光栅化为一堆像素点,写入 帧缓冲区。
显示输出阶段:
11). 显卡会定期从帧缓冲区中读取数据,将其转换为显示器能识别的 VGA/HDMI/DP 等视频信号。
12). 显示器根据接收到的信号,点亮屏幕上相应的像素,我们便看到了‘a’。
保存阶段:
13). 当按下Ctrl+S,Word接收到命令。
14). Word将文档在内存中的数据结构(文本、格式、图片等)序列化成 .docx 格式的二进制流。
15). Word调用操作系统的 文件系统API,将这个二进制流写入硬盘。
16). 文件系统决定将这个文件存储在硬盘的哪些 扇区,并更新其 文件分配表 或 inode 等元数据,记录文件的位置信息。
17). 硬盘驱动器将二进制数据通过磁头转换为磁盘盘片上的磁畴方向变化,完成物理存储。
9. 对于CPU而言,中断是怎么工作的?当有更紧急的任务时,CPU停下当前的任务,去处理更紧急的任务,处理完怎么找到之前的任务,继续执行之间的任务?
答: 中断机制让CPU不用轮询设备状态,极大地提高了效率。
详细工作流程:
中断请求:
设备需要CPU处理时,通过中断请求线发出信号。
中断响应:
CPU在执行完 当前指令 后,检查是否有中断请求。如果有,且 中断未被屏蔽,则响应中断。
CPU通过中断应答信号通知设备,并获取一个中断类型码。
现场保护:
这是能 “找回之前任务” 的关键,CPU自动将当前的 程序计数器、程序状态字 等关键寄存器压入 系统堆栈,这样它就记住了“从哪里中断的”和“当时的状态”。
中断处理:
CPU利用中断类型码作为索引,去查询内存中预先设置好的 中断向量表,从中找到对应的 中断服务程序 的入口地址。
CPU跳转到ISR开始执行,ISR通常也会在开头手动保存通用寄存器的值。
中断返回:
ISR执行完毕后,会执行一条 中断返回指令。
该指令会从堆栈中 弹出 之前保存的程序计数器和程序状态字。
CPU根据恢复的程序计数器,回到被中断的指令流中继续执行,所有的寄存器状态也都恢复了,就好像什么都没发生过一样。
评论
验证登录状态...