本文档是在备战秋招、笔试和面试之后复盘整理的一些嵌入式软件常见题,包含C/C++、Linux、操作系统、算法、硬件总线和一些琐碎的知识点。该资源适合有笔试、面试需求的人进行使用,资源提供目录,可以先查看自己感兴趣或者不太清楚的题目,还便于进行题目定位和查看。一些题目不仅仅只有文字解释,还有代码和图片进行解析,做到知其所以然,更加方便进行理解和学习。该合集非常适合在面试、笔试前进行查缺补漏,希望这份资源可以帮助你解决一些问题。 ### 嵌入式软件面试知识点详解 #### 进程和线程间通信方式 进程间的通信(IPC)包括管道(pipe)、消息队列(message queue)、共享内存(shared memory)、信号量(semaphore)、套接字(socket)等方式。线程间的通信则主要依赖于共享内存,并通过信号量或互斥锁(mutex)机制来同步访问。 - **管道(Pipe)**:用于具有亲缘关系的进程间通信,如父进程和子进程。 - **消息队列(Message Queue)**:允许多个无亲缘关系的进程之间发送消息。 - **共享内存(Shared Memory)**:允许多个进程共享一段物理内存,是最高效的IPC方式之一。 - **信号量(Semaphore)**:用于控制多个进程对共享资源的访问,防止资源冲突。 - **套接字(Socket)**:不仅用于不同主机间通信,也可以用于同一主机上不同进程间的通信。 #### 上下文切换 上下文切换是指处理器从执行某个任务转到执行另一个任务时发生的处理步骤。它涉及保存当前任务的状态(即上下文),恢复下一个任务的状态,并将CPU控制权交给下一个任务。上下文切换是操作系统调度任务的基本操作之一,频繁的上下文切换会影响系统的性能。 #### new和malloc的区别 - **定义**: - `malloc` 是 C 语言中的库函数,用于动态分配内存,需要包含 `<stdlib.h>` 头文件。 - `new` 是 C++ 中的一个关键字,用于动态内存分配,无需显式包含头文件,由编译器支持。 - **用法**: - `malloc` 分配内存时需要明确指定分配的内存大小。 - `new` 分配内存时通常根据类型自动确定内存大小,无需显式指定大小。 - **返回类型**: - `malloc` 成功后返回 `void *` 类型的指针,需显式转换为所需类型。 - `new` 成功后返回对应类型的对象指针。 - **异常处理**: - `malloc` 分配内存失败返回 `NULL`。 - `new` 分配内存失败抛出 `std::bad_alloc` 异常。 #### 1G内存的计算机能否分配出 malloc(1.2G),为什么?(虚拟内存) 在大多数现代操作系统中,物理内存和虚拟内存是分开管理的。即使物理内存只有1GB,操作系统仍能通过虚拟内存技术分配更多的内存。当调用 `malloc(1.2G)` 时,如果物理内存不足,操作系统会将部分数据移到磁盘上的交换文件(swap file)中,从而腾出物理内存空间供新分配的内存使用。因此,在大多数情况下,即使物理内存不足1.2GB,系统也能通过虚拟内存技术完成分配。 #### 虚拟存储技术 虚拟存储技术是一种内存管理策略,使得程序可以使用比实际物理内存更大的地址空间。它通过将部分不常用的内存页面移动到磁盘上来实现。这种方式可以提高内存的利用率,使得系统能够运行更多的程序。 #### extern C的作用 在C++中,使用 `extern "C"` 来声明函数或变量时,会告诉编译器这些函数或变量按照C语言的方式进行链接,而不是C++的名称修饰(name mangling)。这通常用于C++程序调用C库或在C++代码中包含C库头文件时。 #### static关键字的用法 - **局部变量**:使局部变量的生存期扩展到整个程序生命周期。 - **全局变量**:限制变量的作用域仅在当前文件内可见。 - **函数**:限制函数的作用域仅在当前文件内可见。 #### volatile关键字的用法 `volatile` 关键字用来标记那些可能被外部因素(如其他线程或硬件设备)改变的变量。它告诉编译器不要对这些变量进行优化,确保每次访问都是从内存中读取最新值。 #### const、define关键字的用法 - **const**:用于声明只读变量,可以指定类型。 - **#define**:宏定义,用于定义常量或简单的表达式替换,没有类型检查。 #### __attribute__的使用和结构体字节对齐 `__attribute__((packed))` 用于关闭结构体成员之间的填充,避免不必要的对齐导致的额外内存消耗。 #### 交换分区 交换分区是硬盘上的一块区域,用于存储临时溢出的数据。当物理内存不足时,操作系统会将一部分内存数据移动到交换分区,以释放物理内存供其他程序使用。 #### shell中$0、$?、$!、$$、$*、$#、$@ - `$0`:表示当前脚本的文件名。 - `$?`:表示最后执行命令的退出状态。 - `$!`:表示最后后台启动的进程的PID。 - `$$`:表示当前进程的PID。 - `$*`:表示所有参数组成的字符串。 - `$#`:表示参数的个数。 - `$@`:表示所有参数列表。 #### Linux中系统进程类型 Linux中的进程可以分为用户进程和系统进程。系统进程包括内核线程、守护进程等,它们通常是系统运行所必需的。 #### /etc/hosts文件中包含ip地址和主机名的映射 `/etc/hosts` 文件用于映射IP地址到主机名,主要用于局域网内的主机名称解析。 #### Vim的一些考点 Vim是一款功能强大的文本编辑器,考试中可能会涉及到基本命令(如插入模式、命令模式的切换)、文本搜索、分割窗口等。 #### 标准C库和系统调用之间的区别 - **标准C库**:提供了高级抽象,易于使用,但可能不如直接系统调用高效。 - **系统调用**:直接与操作系统交互,效率高,但编写较为复杂。 #### Linux开机流程 Linux开机流程包括BIOS初始化、加载内核、初始化系统服务等步骤。 #### objcopy和objdump - `objcopy`:用于复制或转换目标文件格式。 - `objdump`:用于反汇编和查看目标文件信息。 #### 计算一个数中1的个数和判断一个数是不是2的幂 - **计算1的个数**:可以通过位运算来逐位检查。 - **判断是否为2的幂**:利用 `num & (num - 1)` 的结果是否为0来判断。 #### 几个查找指令(type、whereis、whatis、which、locate、find) - `type`:显示命令的类型。 - `whereis`:查找命令的二进制文件、源码文件等位置。 - `whatis`:显示命令的简短描述。 - `which`:查找命令的确切路径。 - `locate`:快速查找文件位置。 - `find`:按条件查找文件。 #### C++中的template模板 模板是C++中用于创建泛型函数或类的一种机制,可以提高代码的重用性和灵活性。 #### Makefile默认寻找次序 Makefile的默认搜索路径包括当前目录和父目录中的Makefile文件。 #### inline函数 `inline` 关键字用于提示编译器尝试将函数内联,以减少函数调用开销,但不一定总是内联。 #### 程序在内存中的分区 程序在内存中通常分为代码段、数据段、堆、栈等多个区域。 #### 判断一个机子是小端模式还是大端模式 可以利用指针访问结构体中的整数来判断字节顺序。 #### 算法时间复杂度 时间复杂度是用来评估算法执行效率的重要指标,常用O记号表示,如O(1)、O(n)、O(log n)等。 #### 空间复杂度 空间复杂度是指算法在运行过程中临时占用存储空间大小的量度。 #### 查找 查找算法包括顺序查找、折半查找、二分查找等,适用于不同类型的数据结构。 #### 排序 排序算法如冒泡排序、快速排序、插入排序等,用于将数据序列按照一定规则进行排列。 #### socket编程基础 socket编程用于实现网络通信,包括创建套接字、绑定地址、监听连接等步骤。 #### C语言头文件为什么要加 #ifndef#define#endif 这是为了防止头文件被重复包含,导致编译错误。 #### const与指针 - `const` 可以修饰指针所指向的数据。 - `const` 也可以修饰指针本身。 #### 几个复制函数 strcpy,strncpy,memcpy,copy_to_user,copy_from_user - `strcpy`:用于复制字符串。 - `strncpy`:用于安全地复制字符串,可以指定复制的最大字符数。 - `memcpy`:用于复制任意类型的数据。 - `copy_to_user` 和 `copy_from_user`:用于用户空间和内核空间之间的数据复制。 #### 使用数组指针来访问一维数组最后一个元素 数组指针可以指向数组的首地址,通过偏移量访问数组中的任一元素。 #### 死锁的四个必要条件 - **互斥条件**:资源不能同时被多个进程使用。 - **请求和保持条件**:进程已经保持至少一个资源,但又请求其他资源。 - **不剥夺条件**:进程不能强制剥夺其他进程已获得的资源。 - **循环等待条件**:存在一个进程等待链,每个进程都在等待链中下一个进程所占有的资源。 #### GCC编译过程、GDB的使用和库的制作 - **GCC编译过程**:预处理、编译、汇编、链接。 - **GDB**:GNU调试器,用于调试C/C++程序。 - **库的制作**:静态库和动态库的生成方法。 #### 读写文本文件(fgets、fputs)和二进制文件(fread、fwrite) - `fgets` 和 `fputs`:用于文本文件的读写。 - `fread` 和 `fwrite`:用于二进制文件的读写。 #### 硬链接、软链接、CP三者之间的区别 - **硬链接**:指向文件的索引节点,删除硬链接不会影响原文件。 - **软链接(符号链接)**:类似于Windows下的快捷方式,删除软链接不影响原文件。 - **cp**:复制文件或目录。 #### 虚拟文件系统和Linux常见的文件系统 - **虚拟文件系统(VFS)**:Linux中文件系统的抽象层。 - **常见文件系统**:EXT4、XFS、Btrfs等。 #### 一个进程打开文件的过程 打开文件通常涉及查找文件、权限检查、分配文件描述符等步骤。 #### 队列在嵌入式中的应用 队列常用于缓冲区管理、任务调度等场景。 #### 如何判断浮点数是否相等 由于浮点数的精度问题,通常通过比较两个数的差值是否小于某个阈值来判断。 #### GPIO模拟串口TX和RX、C语言中的可变参数函数 - **GPIO模拟串口**:利用通用输入输出接口模拟串行通信。 - **可变参数函数**:使用 `va_list`、`va_start`、`va_end` 等宏来处理可变数量的参数。 #### 中断 中断是处理器对外部事件的响应机制,可以用于实现硬件同步、定时等功能。 #### IIC和SPI的比较 - **IIC(Inter-Integrated Circuit)**:两线制串行总线,支持主从模式。 - **SPI(Serial Peripheral Interface)**:四线制串行总线,支持全双工通信。 #### 进程PID和网络端口号的区别 - **PID**:进程标识符,唯一标识一个进程。 - **端口号**:用于标识网络通信中的应用程序。 #### FTP、SFTP和SSH - **FTP**:文件传输协议,不加密。 - **SFTP**:基于SSH协议的文件传输,加密传输。 - **SSH**:安全外壳协议,用于远程登录和管理。 #### 栈区和全局区变量的初值 - **栈区变量**:通常未初始化时值不确定。 - **全局区变量**:默认初始化为0或空字符串。 #### GPIO的几种工作模式 GPIO可以配置为输入模式、输出模式、上拉/下拉等模式。 #### input子系统上报事件的流程 Linux内核中的input子系统负责处理来自键盘、鼠标等输入设备的事件。 #### printf、scanf的底层原理(va_list和vfprintf) - `printf` 和 `scanf` 实现了格式化输入输出。 - 底层通过 `va_list` 和 `vfprintf` 来处理可变参数列表。 #### Shell脚本中 #!/bin/bash 的作用 `#!/bin/bash` 指定了脚本的解释器为bash shell。 #### C语言中 malloc、free 函数底层实现原理 - `malloc`:分配内存。 - `free`:释放之前分配的内存。 - 底层实现通常涉及内存池管理和碎片处理。 #### C语言中数组和指针的区别 - **数组**:固定长度的元素集合。 - **指针**:存储地址的变量,可用于动态内存分配。 #### Linux中 fork 函数在创建子进程的时候具体做了哪些事,与 vfork 的区别、clone 函数 - `fork` 创建一个与父进程几乎完全相同的子进程。 - `vfork` 创建子进程时共享父进程的内存,直到子进程执行 `exec` 或退出。 - `clone` 是更通用的进程创建函数,可以指定不同的选项来控制子进程的行为。 #### exec系列函数和 system 函数 - `exec` 系列函数用于替换当前进程的图像。 - `system` 函数用于执行外部命令,并等待其结束。 #### C++中静态类型转换和动态类型转换(dynamic_cast和static_cast) - `static_cast`:用于基本类型的转换。 - `dynamic_cast`:用于派生类向基类的转换,并进行类型检查。 #### Linux多线程中可重入函数和不可重入函数 - **可重入函数**:可以被多个线程同时安全调用。 - **不可重入函数**:包含静态变量或全局变量,可能导致数据竞争。 #### 进程阻塞和进程挂起的区别 - **进程阻塞**:进程主动放弃CPU,等待某种条件满足后重新执行。 - **进程挂起**:进程被暂时挂起,通常由系统或父进程操作。 #### 常见外设配置项 - **GPIO**:配置输入输出方向。 - **UART**:设置波特率、数据位等。 - **I2C/SPI**:配置时钟速度等。 以上是嵌入式软件领域常见的面试知识点概述,掌握这些内容对于面试准备和职业发展都十分有益。
- 粉丝: 273
- 资源: 2
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助