嵌入式面试笔试刷题(day8)


前言

一、uart spi ii2的区别

1.通信方式:

UART:UART使用异步通信方式,即数据以字节为单位逐个传输,不带时钟信号。
SPI:SPI使用同步通信方式,数据以字节为单位通过一个时钟线(SCK)同步传输。
I2C:I2C也使用同步通信方式,数据以字节为单位通过两个线路(时钟线SCL和数据线SDA)同步传输。

2.线路数量:

UART:UART使用一对单向线路(发送线和接收线)来传输数据。
SPI:SPI使用四根线路:SCK(时钟信号)、MOSI(主机输出从机输入)、MISO(主机输入从机输出)和SS(片选信号)。
I2C:I2C使用两根线路:SCL(时钟信号)和SDA(数据信号)。

3.工作模式:

UART:UART工作在全双工或半双工模式。它可以同时发送和接收数据,或者在特定时刻只发送或只接收数据。
SPI:SPI工作在全双工模式,即在传输数据时可以同时发送和接收。
I2C:I2C工作在半双工模式,即在同一时刻只能进行发送或接收操作。

4.设备数量:

UART:UART通常用于点对点通信,即一对一的通信,例如串口输入/输出。
SPI:SPI支持多主设备和多从设备的通信,主设备可以与多个从设备进行通信。
I2C:I2C也支持多主设备和多从设备的通信。它使用7位或10位地址编码来选择不同的设备作为通信目标。

5.数据传输速率:

UART:UART的速率是可变的,常见的波特率为9600、115200等。
SPI:SPI的速率可以在一定范围内配置,具有较高的传输速度,通常可达数百Mbps。
I2C:I2C的速率可配置为标准模式(100 kbps)、快速模式(400 kbps)、高速模式(3.4 Mbps)或超高速模式(5 Mbps)。

二、造成TCP粘包原因和解决方法

1.原因

1.TCP缓冲区机制:发送方向接收方发送数据时,操作系统内部的TCP缓冲区会对数据进行合并,以提高传输效率。接收方从缓冲区读取数据,可能一次读取到多个数据包。

2.传输速率不匹配:发送方的数据发送速率和接收方的数据接收速率不匹配时,可能会导致数据粘包。发送方快速发送多个数据包,而接收方较慢地接收数据,从而导致多个数据包粘在一起。

2.解决方法

1.消息边界标识符(Message Boundary Marker):在数据包中添加特定的标识符作为消息的边界标志。接收方根据这个标志来切分接收到的数据,将其分解为单独的消息。例如,在发送端每个数据包末尾添加换行符(\n),接收端根据换行符来切分数据。

2.消息长度字段(Message Length Field):在每个数据包开头添加表示数据长度的字段。接收方首先读取这个字段,根据字段值确定待接收数据的长度,然后按照长度读取数据。这样接收方可以精确地切分每个数据包。常见的长度字段包括固定长度的整数或使用特定字节数编码的变长字段。

三、什么是内存泄漏

内存泄漏(Memory Leak)指的是在程序运行时,动态分配的内存空间无法被正确释放或回收,从而导致该内存空间无法再被程序所访问或利用,但仍然占用着系统的内存资源。

四、大量频繁的申请堆空间会发生什么

1.内存耗尽:堆内存是有限的资源,如果频繁申请而没有释放,会导致堆内存逐渐耗尽。当堆内存不足以满足新的内存分配请求时,可能会引发内存分配失败或内存分配异常。

2.内存泄漏:如果申请的堆内存没有在合适的时候进行释放,就会造成内存泄漏。内存泄漏会导致已经无法访问的内存仍然被占用,从而浪费了宝贵的内存资源。

3.性能下降:过多的堆内存使用会导致系统频繁进行内存分配和释放操作,增加了内存管理的开销。这可能会影响程序的性能,导致响应时间变长、CPU 占用率增加等问题。

4.程序崩溃:当堆内存耗尽或无法满足程序的内存需求时,可能会导致程序异常终止、崩溃或发生段错误等严重问题。

五、SPI有几根线,可以去除哪根线

SPI(Serial Peripheral Interface)通信的数据线一般包括以下四根:

1.SCLK(Serial Clock):时钟线,用于同步数据传输的时序控制。

2.MOSI(Master Output Slave Input):主设备输出、从设备输入线,用于主设备向从设备发送数据。

3.MISO(Master Input Slave Output):主设备输入、从设备输出线,用于从设备向主设备返回数据。

4.SS(Slave Select):从设备选择线,用于选择与主设备进行通信的从设备。在多个从设备的情况下,每个从设备通常都有一个独立的 SS 线。

如果要去除一根数据线,那么要根据具体的情况来判断可以去除哪一根数据线。这取决于所需的通信功能和设备的工作方式。以下是一些可能的情况:

1.不需要双向通信:如果通信场景中只需要单向数据传输(例如,仅从主设备向从设备发送数据),则可以考虑去除 MISO 线。

2.不需要主设备输出数据:如果从设备无需返回数据给主设备,可以考虑去除 MISO 线。

3.单个从设备:如果只与一个从设备通信,并且没有其他设备需要通过 SS 信号进行选择,则可以考虑去除 SS 线。

六、C语言中的static和C++中的static的区别

1.变量的作用范围:

C语言中,函数内部使用static关键字声明的变量具有块作用域,仅在声明其所在函数内部可见。
C++中,类内部使用static关键字声明的变量或者函数会成为类的静态成员(静态数据成员或静态成员函数),它们在整个类的范围内可见。

2.变量的生命周期:

C语言中,函数内部使用static关键字声明的变量具有静态存储期,它们在程序的整个执行过程中都存在,并且只会被初始化一次。
C++中,类的静态成员在程序开始时被初始化,并且一直存在,直到程序结束。它们的生命周期与类的生命周期相同。

3.全局变量和函数的可见性:

C语言中,全局变量或函数使用static关键字声明后具有内部链接(internal linkage),只在声明它们的源文件内部可见。
C++中,全局变量或函数使用static关键字声明后默认具有外部链接(external linkage),也可以显式指定为内部链接。外部链接意味着它们可以在其他文件中访问。

七、回调函数概念

回调函数是一种常见的编程概念,它指的是通过将一个函数作为参数传递给另一个函数,以在特定事件发生或特定条件满足时被调用的函数。

回调函数通常用于异步编程或事件驱动的程序设计中,其中我们需要在某些特定事件发生后执行一些特定的操作。通过使用回调函数,我们可以将这些操作的逻辑封装到一个函数中,并将其作为参数传递给其他函数或系统,以便在事件发生时调用执行。

#include <stdio.h>
#include <stdlib.h>

// 定义回调函数类型
typedef void (*CallbackFunc)(void);

// 回调函数,处理按下 Enter 键的事件
void enterPressedCallback(void) {
    
    
    printf("Enter 键被按下了!\n");
    // 其他处理逻辑...
}

// 模拟用户输入事件的处理函数
void processInput(CallbackFunc callback) {
    
    
    // 模拟等待用户输入事件
    // 当用户按下 Enter 键时调用回调函数
    if (getchar() == '\n') {
    
    
        callback(); // 调用回调函数
    }
}

int main() {
    
    
    // 调用 processInput 函数,传递回调函数作为参数
    processInput(enterPressedCallback);

    return 0;
}

八、怎么设置程序的可执行权限

在Linux上,可以使用chmod命令设置文件的可执行权限。以下是示例命令:

chmod +x 文件名

九、什么是内联函数

内联函数是一种编译器提供的优化手段,通过将函数体插入到调用处减少了函数调用的开销,并提高程序的执行效率。

总结

本篇文章就讲解到这里,下次见。

猜你喜欢

转载自blog.csdn.net/m0_49476241/article/details/132259545
今日推荐