前言
本篇文章继续讲解嵌入式面试笔试刷题。
一、线程同步方式
1.互斥锁(Mutex)
2.信号量(Condition Variable)
3.读写锁(Read-Write Lock)
4.条件变量(Semaphore)
5.屏障(Barrier)
二、tcp和udp区别与应用场景
1.可靠性:TCP 提供可靠的数据传输,通过使用序列号、确认机制、重传机制和流量控制等机制来确保数据的完整性和顺序性。UDP 则是无连接的协议,不提供数据可靠性,数据包可能会丢失或乱序。
2.通信方式:TCP 是面向连接的协议,使用三次握手建立连接,以及四次挥手来终止连接。UDP 是无连接的协议,每个数据包都是独立的,没有连接建立和断开的过程。
3.数据传输效率:由于 TCP 提供的可靠性机制较多,传输过程中会有更多的开销,例如确认机制和重传机制等,因此相对于 UDP,它的传输效率较低。
4.传输特点:TCP 提供流式传输,保证数据的顺序和完整性,适用于要求确保数据完整性和顺序性的应用场景,如文件传输、电子邮件、Web 浏览等。UDP 则以数据报的形式传输数据,适用于实时性要求较高的应用场景,如实时音视频传输、在线游戏等。
三、物理内存和虚拟内存他们之前的关系
物理内存是计算机系统中实际存在的内存硬件,由RAM (Random Access Memory,随机访问内存)组成。物理内存是计算机用于存储和访问数据的物理位置,它提供了直接的数据读写能力。程序和操作系统需要将数据加载到物理内存中,以便 CPU 可以直接对其进行访问。
虚拟内存是一种抽象的内存概念,对程序而言,它看起来是一块连续的、私有的地址空间。虚拟内存的大小通常比实际的物理内存大得多。虚拟内存由操作系统管理,它将程序的虚拟地址映射到物理内存上的物理地址。
关系:
虚拟内存通过页表将程序的虚拟地址映射到物理内存的物理地址,提供了更大的地址空间和便捷的内存管理功能。
四、malloc分配的内存空间不初始化带来的问题
1.不可预测的值:未初始化的内存空间中的值是不确定的,其内容可能是之前使用过的数据残留值,也可能是随机垃圾值。这使得在使用该内存空间时,这些值的行为是不可预测的,可能导致程序的不确定性和不稳定性。
2.安全隐患:在未初始化的内存空间中,如果存在敏感信息(例如密码、密钥或其他敏感数据),这些信息可能仍然存在于内存中,容易被恶意访问或泄露。这可能引发安全问题和漏洞。
3.不一致的结果:如果未初始化的内存空间作为数据结构的存储区域,其初始值可能会导致数据结构的不一致和错误的计算结果。例如,如果使用未初始化的数组进行操作,结果可能会产生不正确的值、越界访问或数组异常。
为了避免未初始化内存带来的潜在问题,推荐在使用malloc分配的内存空间后,使用适当的方法对其进行初始化。可以使用memset、循环赋值或其他合适的方式将初始值分配给内存空间,确保所使用的内存空间处于已定义和一致状态。
五、嵌入式Linux中的调试方式
1.GDB(GNU调试器):是一个功能强大的命令行调试器,可用于调试嵌入式Linux应用程序、内核模块和驱动程序等。它提供了一组命令和功能,以便在运行时查看和修改变量、设置断点、单步调试代码、回溯函数调用栈等。
使用GDB调试应用程序时,首先需要编译并链接目标代码时包含调试信息(通常使用-g选项)。然后,通过在终端中执行gdb <可执行文件>命令来启动GDB调试器。在调试器中,可以使用各种GDB命令来控制程序的执行和观察变量的值。
GDB还支持通过远程调试和调试器脚本等功能,使得在嵌入式系统上进行远程调试更加便捷和灵活。
2.printf调试:是一种基本的调试技术,通过在代码中插入打印语句来输出变量的值、程序执行的状态以及其他调试信息。这些输出将显示在终端或系统日志中,供开发人员检查和分析。
在嵌入式Linux开发中,开发人员可以在关键位置插入printf语句,输出关注的变量的值和调试信息。通过比较输出结果,可以验证代码的正确性、追踪程序的执行路径以及观察状态变化等。
需要注意的是,在生产环境中大量使用printf会影响性能并增加资源消耗,因此,调试完成后通常需要从代码中删除或禁用这些调试语句。
3.syslog:syslog是Linux系统中的一个日志机制,可以用来记录系统运行时的各种信息,包括调试信息。嵌入式Linux系统可以使用syslog库将自定义的调试信息输出到系统日志中,通过查看系统日志文件可以进行调试。
4.printk:printk是Linux内核中的一个函数,类似于printf函数,可以将打印信息输出到系统控制台或日志文件。在嵌入式Linux开发中,可以在内核模块或驱动程序中使用printk函数来输出调试信息,方便进行调试和故障排查。
5.Trace工具:Linux内核提供了一些trace工具,如ftrace和trace-cmd,用于跟踪和分析系统的运行情况。这些工具可以记录系统中各个软件和硬件事件的发生顺序和时间戳,帮助定位问题。
6.硬件调试器:某些嵌入式平台可能提供支持硬件调试的功能,如JTAG或SWD接口。通过与硬件调试器连接,可以在嵌入式系统中设置断点、查看和修改寄存器、跟踪代码执行等,实现底层的硬件级调试。
7.运行时分析工具:嵌入式Linux系统上可以使用一些运行时分析工具,如strace和ltrace,来跟踪和分析进程的系统调用和库函数调用情况。这些工具可以帮助定位系统调用错误或库函数使用不当的问题。
六、互斥锁简单介绍
互斥锁(Mutex Lock)是一种常见的同步机制,用于实现互斥访问共享资源的多线程或多进程编程中。它提供了一种保护共享资源的机制,确保在任意时刻只有一个线程或进程可以持有该锁,从而避免竞争条件和数据不一致性。
七、QT中的信号与槽
信号与槽(Signals and Slots)是Qt框架中的一种机制,用于实现对象之间的通信和交互。它是一种基于事件的编程模式,使得对象能够以一种分离的方式相互响应和交互。
八、标准输入输出
在Linux中,标准输入(stdin)、标准输出(stdout)和标准错误(stderr)通常是通过特定的文件描述符来表示。对应的文件描述符的宏定义可以在 <unistd.h> 头文件中找到:
STDIN_FILENO:标准输入的文件描述符,通常为 0。
STDOUT_FILENO:标准输出的文件描述符,通常为 1。
STDERR_FILENO:标准错误的文件描述符,通常为 2。
这些宏定义在编写程序时可以用于明确指定和使用标准输入输出的文件描述符,例如在进行文件描述符的操作时或使用底层系统调用时。
#include <stdio.h> #include <unistd.h> int main(void) { char buf[1024]; int len = 0; len = read(STDIN_FILENO, buf, 1024); write(STDOUT_FILENO, buf, len); return 0; }
总结
本篇文章就讲解到这里。