50道 C/C+++Linux+嵌入式+网络+内核高频面试题
一、C/C++ 基础(1–12)
1、static 作用
1. 修饰局部变量:改变变量生命周期,延长至整个程序运行结束,仅初始化一次,默认值为 0。
2. 修饰全局变量:限定作用域,仅当前.c文件内可见,禁止外部文件引用。
3. 修饰普通函数:函数仅当前文件可调用,避免多文件函数名冲突。
4. C++类中static:
-
静态成员变量:属于类而非对象,所有对象共享,必须在类外初始化。
-
静态成员函数:无this指针,只能访问静态成员,不可调用非静态成员。
2、什么是宏定义;宏定义中的 # 和 ##
宏定义:#define 是预处理指令,仅做纯文本替换,无类型检查、不分配内存。
#:字符串化,将宏参数转为字符串。
#define STR(x) #x
STR(123) → "123"
##:符号拼接,将两个标识符合并为一个。
#define CAT(a,b) a##b
CAT(te,st) → test
3、函数指针与指针函数区别
指针函数:本质是函数,返回值为指针
int *func(int a);
函数指针:本质是指针,指向一个函数
int (*pfunc)(int);
快速区分:*带括号是函数指针,不带括号是指针函数。
4、对指针的理解
1. 指针是存储内存地址的变量,32位系统占4字节,64位系统占8字节。
2. 核心操作:&取地址、*解引用。
3. 可指向:普通变量、数组、函数、结构体、堆内存。
4. 常见风险:野指针、空指针、内存越界、内存泄漏。
5、const、volatile
const(只读修饰)
1. 修饰普通变量:变量不可修改。
2. 修饰指针:
-
const int *p:指针指向内容不可改,指针可改
-
int *const p:指针本身不可改,内容可改
-
const int *const p:指针和内容均不可改
3. 修饰函数参数/返回值:防止参数被意外修改。
volatile(防止编译器优化)
1. 告知编译器:变量可能被硬件/中断/多线程随时修改,禁止寄存器缓存,每次必须从内存读取。
2. 适用场景:硬件寄存器、中断共享变量、多线程全局变量。
6、C 与 C++ 的区别
1. C是面向过程,C++是面向对象,支持封装、继承、多态。
2. C++新增:引用、函数重载、运算符重载、模板、异常、STL。
3. C使用malloc/free,C++使用new/delete(自动调用构造/析构)。
4. C结构体不能包含函数,C++结构体可包含成员函数。
5. C++类型检查更严格,支持命名空间避免命名冲突。
7、C 指针与 C++ 引用区别
1. 指针是独立变量;引用是变量别名,不占用内存。
2. 指针可空;引用必须初始化,不能为空。
3. 指针可改变指向;引用绑定后不可更换对象。
4. 支持多级指针;无多级引用。
5. 指针需解引用*;引用直接使用,更安全。
8、C++ 多态性,如何实现多态
多态:同一接口,不同对象实现不同行为。
分类:
-
编译期多态:函数重载、运算符重载、模板
-
运行期多态:虚函数
实现方式:基类定义virtual虚函数,派生类重写,通过基类指针/引用调用,自动匹配子类实现。
底层原理:虚函数表 + 虚函数指针。
9、C/C++ 内存分布;内存分配方式
内存分布(地址由低到高)
-
1. 代码段.text:程序执行二进制指令
-
2. 数据段.data:已初始化全局/静态变量
-
3. BSS段:未初始化全局/静态变量,默认初始化为0
-
4. 堆heap:向上生长,动态内存
-
5. 栈stack:向下生长,局部变量、函数参数
内存分配方式
-
1. 栈:编译器自动分配释放
-
2. 全局/静态区:程序全程存在
-
3. 堆:malloc/free、new/delete手动管理
10、C++ static 使用
1. 静态全局变量/函数:仅当前文件可见。
2. 静态局部变量:延长生命周期,仅初始化一次。
3. 静态成员变量:类所有对象共享,类外初始化。
4. 静态成员函数:无this指针,只能访问静态成员。
11、C++ 异常处理方式
- try:包裹可能抛出异常的代码
- throw:主动抛出异常
- catch:捕获并处理对应类型异常
工程常用RAII思想,配合智能指针实现异常安全的资源管理。
12、实时操作系统与 Linux 区别
1. RTOS实时系统:调度确定性强,中断延迟微秒级,体积小,适合嵌入式实时场景。
2. Linux通用系统:分时调度,非硬实时,功能丰富、生态完善,稳定性高。
3. 核心差异:调度算法、抢占机制、中断响应时间、任务执行确定性。
二、Linux 系统基础(13–24)
13、对 Linux 系统的认识
开源免费、多用户多任务、稳定安全、一切皆文件;内核模块化可裁剪,广泛用于服务器、嵌入式、物联网、移动端。
14、Linux 系统框架
1. 用户层:应用程序、Shell、第三方库
2. 系统调用层:用户态进入内核态的统一接口
3. 内核层:进程管理、内存管理、文件系统、设备驱动、网络协议栈
4. 硬件层:CPU、内存、外设硬件
15、Linux 用户密码相关文件
- /etc/passwd:用户基本信息(用户名、UID、家目录)
- /etc/shadow:加密后的用户密码,安全存储
- /etc/group:用户组信息
16、/etc 目录作用
存放系统所有配置文件,包括网络、用户权限、服务配置、启动脚本、环境变量等。
17、相对、绝对路径
- 绝对路径:从根目录/开始的完整路径
- 相对路径:从当前工作目录开始,不包含/
18、常见 Linux 系统
Ubuntu、CentOS、Debian、RedHat、Fedora、OpenWrt、Android(Linux内核)
19、Linux 系统作用
服务器部署、嵌入式设备、网络设备、云计算、物联网终端、移动端内核。
20、Linux 中 shell 作用
命令解释器,用户与内核的交互桥梁;支持命令执行、脚本编程、管道、重定向。
21、Linux 文件类型
- :普通文件
- d:目录文件
- c:字符设备文件
- b:块设备文件
- p:管道文件
- s:套接字文件
- l:软链接文件
22、软链接和硬链接区别
1. 硬链接:与原文件共用同一个inode;不可跨分区、不可链接目录;删除原文件链接仍有效。
2. 软链接:独立文件,类似Windows快捷方式;可跨分区、可链接目录;原文件删除则链接失效。
23、Linux 下接口分类
1. 系统调用接口(内核原生接口)
2. 库函数接口(glibc封装)
3. 设备驱动接口(设备文件)
4. 网络接口(Socket)
24、Linux 下接口分类(重复)
同上。
三、Linux 进程、通信、同步(25–27)
25、Linux 进程通信方式(IPC)
1. 匿名管道 pipe
2. 命名管道 FIFO
3. 信号 signal
4. 消息队列
5. 共享内存(速度最快)
6. 信号量
7. Socket套接字(支持跨主机通信)
26、pipe 与 FIFO 的区别
- 匿名管道pipe:仅亲缘进程使用,无文件实体。
- 命名管道FIFO:任意无亲缘关系进程通信,存在磁盘文件。
27、Linux 下实现同步机制方式
信号量、互斥锁mutex、自旋锁、条件变量、读写锁、文件锁。
四、计算机网络(28–34)
28、TCP 与 UDP 区别
1. TCP:面向连接、可靠传输、有序、支持重传/拥塞控制,速度慢。
2. UDP:无连接、不可靠、数据报传输,实时性强、速度快。
29、OSI 七层模型
应用层 → 表示层 → 会话层 → 传输层 → 网络层 → 数据链路层 → 物理层
30、IP 地址组成
网络位 + 主机位;IPv4为32位,IPv6为128位;分为A/B/C/D/E五类地址。
31、物理地址与 IP 地址转换协议
- ARP:IP地址解析为MAC物理地址
- RARP:MAC地址反向解析为IP地址
32、数据链路层作用
帧封装与解封装、物理寻址、差错检测、流量控制、介质访问控制。
33、三次握手?为什么是三次而不是2次、4次
三次握手流程
1. 客户端→服务端:SYN同步报文
2. 服务端→客户端:SYN+ACK确认报文
3. 客户端→服务端:ACK确认报文,连接建立
为什么三次
1. 避免失效旧连接报文导致服务器资源浪费。
2. 确保双方收发能力均正常,两次握手无法确认客户端接收服务端报文的能力。
3. 四次握手冗余,无实际意义。
34、什么是数据库?与文件有什么区别?什么是关系型数据库?什么是SQL?
1. 数据库:结构化存储、支持事务、并发控制、快速查询、安全可靠。
2. 文件:无结构、无索引、无事务,数据管理困难。
3. 关系型数据库:以二维表格存储数据,如MySQL、SQLite。
4. SQL:结构化查询语言,用于增删改查、管理数据库。
五、Linux IO、启动、内核&嵌入式驱动(35–50)
35、五大 IO 模型
阻塞IO、非阻塞IO、IO多路复用(select/poll/epoll)、信号驱动IO、异步IO。
36、Linux 启动过程
BIOS/UEFI硬件自检 → Bootloader(U‑Boot/GRUB) → 加载内核镜像 → 内核初始化 → 启动init/systemd → 启动系统服务 → 进入Shell登录。
37、Linux 系统组成部分
Linux内核 + Shell解析器 + 文件系统 + 系统库 + 应用程序。
38、u-boot如何向内核传参?启动模式?如何设置环境变量?
1. 传参:通过Tag标签列表或设备树DTB向内核传递启动参数。
2. 启动模式:SD/EMMC启动、Flash启动、网络TFTP启动。
3. 环境变量:setenv设置、saveenv保存、printenv查看。
39、kconfig作用?如何向内核菜单添加选项
1. Kconfig:生成内核配置菜单,用于裁剪内核,最终生成.config配置文件。
2. 添加方式:在对应目录Kconfig添加config配置项,关联Makefile编译规则。
40、内核模块编程的优势
可动态加载/卸载,无需重启内核;减小内核体积;驱动调试方便、灵活。
41、字符设备核心数据结构
struct cdev、struct file_operations、struct file、struct inode。
42、如何确定唯一设备
通过主设备号+次设备号唯一标识;或设备树唯一节点路径。
43、内核模式与用户模式的区别
1. 用户态:权限受限,不可直接操作硬件、访问内核资源。
2. 内核态:最高权限,可操作全部硬件、寄存器、内存。
3. 切换方式:系统调用、硬件中断、异常。
44、用户态malloc开辟空间的范围
在进程堆空间;底层通过brk()或mmap()系统调用实现。
45、如何加载模块到内核
- insmod xxx.ko:加载内核模块
- rmmod xxx:卸载模块
- lsmod:查看已加载模块
- modprobe:自动解决模块依赖
46、float运算是内核实现还是用户层实现
浮点运算由硬件FPU完成;Linux内核默认禁用浮点运算,浮点运算均在用户态执行。
47、内核中开辟大内存空间的方式
1. __get_free_pages:按页连续分配
2. vmalloc:虚拟地址连续,物理地址不连续,适合大内存分配
48、设备总线组成
总线(bus)、设备(device)、驱动(driver);通过设备ID或设备树完成匹配。
49、内核中锁机制都有哪些
自旋锁spinlock、互斥锁mutex、信号量semaphore、读写锁rwlock、顺序锁seqlock、RCU。
50、如何使用(操作)LCD屏,为什么要采用映射
操作步骤
1. 打开LCD设备文件
2. mmap将显存物理地址映射到用户虚拟地址
3. 直接向映射地址写入像素数据
4. 刷新显示
映射原因
用户态无法直接访问硬件物理地址;mmap映射后,用户态直接读写显存,省去内核拷贝,速度极快。
更多推荐

所有评论(0)