面试真题 | 诺瓦科技[20240812]

到现在为止,我依旧认为诺瓦科技是我面试公司中问的最全面的一家公司

笔试和其他公司笔试比较相同了,嵌入式选择题(C,C++,linux,嵌入式基础),可以在牛客网上刷一下,原题挺多,一道编程:链表,结构体相关的操作,两道问答题。

@[toc]

面试(52min)

(1)自我介绍:我是xxx,就读于xxx,…

当然,以下是一个针对嵌入式系统面试的自我介绍模板框架,您可以根据自己的实际经历和技能进行调整和补充:

面试官您好,

我是[您的姓名],非常荣幸有机会参加今天的面试,向您展示我在嵌入式系统领域的热情和专业知识。我毕业于[毕业院校],主修[专业名称],自[毕业年份]以来,我一直致力于将理论知识应用于实践,特别是在嵌入式系统设计与开发方面积累了丰富的经验。

专业技能方面

  • 嵌入式编程语言:我熟练掌握C/C++编程语言,熟悉其内存管理、指针操作及优化技巧,在多个项目中成功实现了高效的嵌入式软件设计。同时,我也对Python有一定的了解,用于辅助嵌入式系统的数据分析与脚本编写。

  • 微控制器与处理器:我熟悉多种微控制器架构,如ARM Cortex-M系列、AVR、PIC等,以及高性能嵌入式处理器如ARM Cortex-A系列。我能够根据项目需求选择合适的硬件平台,并进行相应的软件开发与调试。

  • 硬件接口与通信协议:我精通多种硬件接口技术,包括SPI、I2C、UART、CAN等,能够设计并实现复杂的设备间通信。同时,我也对以太网、Wi-Fi、蓝牙等无线通信协议有所研究,并在项目中成功应用。

  • 嵌入式操作系统:我熟悉RTOS(实时操作系统)如FreeRTOS、RT-Thread,以及Linux在嵌入式领域的应用。我能够理解并优化操作系统的任务调度、中断管理、同步机制等,以满足项目对实时性和可靠性的要求。

  • 开发工具与调试:我熟练使用Keil MDK、IAR EWARM、Eclipse CDT等IDE进行嵌入式软件开发,同时也精通JTAG、SWD等调试技术,能够快速定位并解决软件问题。

项目经验

(这里简要介绍一两个与嵌入式系统相关的项目,突出您的技术贡献和解决问题的能力。例如:)

  • 在[项目名称]中,我负责了嵌入式系统的核心控制软件开发,实现了对多传感器数据的实时采集与处理,并通过CAN总线与上位机进行高效通信。通过优化算法和代码结构,我成功将系统响应时间缩短了30%,并提高了数据处理的准确性。

  • 在另一个项目中,我参与了基于ARM Cortex-A处理器的智能设备开发,负责Linux系统下的驱动程序编写和应用程序开发。通过深入理解Linux内核机制,我成功解决了设备驱动与上层应用之间的兼容性问题,提升了产品的整体性能。

个人品质与职业规划

我具备良好的团队合作精神和独立解决问题的能力,能够快速适应新环境并承担压力。对于嵌入式系统领域,我始终保持高度的热情和好奇心,不断学习新技术、新知识以提升自己的专业能力。未来,我希望能在嵌入式系统的高级开发、架构设计或项目管理等方面有更深入的发展,为公司的技术创新和产品升级贡献自己的力量。

再次感谢您给我这次面试的机会,期待能有机会加入贵公司,共同创造更加辉煌的业绩。

请根据您的实际情况调整上述模板中的具体内容,使其更加贴合您的个人经历和求职意向。缩减一下内容。

(2)通信协议了解过吗(SPI,I2C,UART)?

一、SPI(Serial Peripheral Interface)

1. 时序说明: SPI是一种高速的、全双工、同步的通信总线,通过四根线(SS/CS、SCK、SDI/MOSI、SDO/MISO)实现数据交换。其时序通常包括在SCK(时钟信号)的控制下,SDI和SDO分别在时钟的上升沿或下降沿进行数据的发送和接收。SPI支持四种工作模式(SP0, SP1, SP2, SP3),通过CPOL(时钟极性)和CPHA(时钟相位)的设置来确定数据的采样和发送时刻。

2. 实现方式: SPI的实现通常涉及配置主机或从机的SPI接口参数(如时钟频率、工作模式等),然后通过编程控制SCK信号,以及在合适的时钟沿发送和接收数据。在实现过程中,需要注意数据的发送和接收顺序,以及SPI总线上的设备选择(通过SS/CS信号)。

二、I2C(Inter-Integrated Circuit)

1. 时序说明: I2C是一种两线制(SDA数据线和SCL时钟线)的串行通信协议,支持多个主设备和多个从设备之间的通信。I2C通信通过起始信号、停止信号、地址帧、数据帧和应答信号等实现。其中,起始信号和停止信号用于表示通信的开始和结束,地址帧用于指定从设备地址,数据帧用于传输数据,应答信号用于确认数据是否接收成功。

2. 实现方式: I2C的实现涉及配置主设备或从设备的I2C接口参数(如地址、通信速率等),然后通过编程发送起始信号、地址帧、数据帧,并接收应答信号。在实现过程中,需要注意时钟信号的生成和数据的同步发送与接收,以及如何处理通信过程中的各种异常情况(如仲裁失败、超时等)。

三、UART(Universal Asynchronous Receiver/Transmitter)

1. 时序说明: UART是一种异步串行通信协议,通过两根线(TXD发送线和RXD接收线)实现数据交换。UART通信不需要统一的时钟信号,而是通过波特率(数据传输速率)来同步数据的发送和接收。UART数据帧包括起始位、数据位、可选的奇偶校验位和停止位。

2. 实现方式: UART的实现涉及配置串口参数(如波特率、数据位、停止位、奇偶校验等),然后通过编程发送和接收数据帧。在实现过程中,需要注意波特率的设置与接收方一致,以及正确处理数据帧的起始位、数据位、校验位和停止位。

总结

以上是对SPI、I2C、UART三种通信协议的时序说明和实现方式的简要介绍。在嵌入式面试中,了解这些通信协议的基本原理和实现方式是非常重要的,因为它们是嵌入式系统与其他设备或模块进行通信的基础。同时,根据具体的硬件平台和项目需求,还需要深入了解这些协议的具体实现细节和注意事项。

(3)I2C协议你是用到哪里的,代码怎么实现的?

I2C协议的使用场景

I2C(Inter-Integrated Circuit)协议是一种广泛使用的串行通信协议,它采用两根线(SDA串行数据线、SCL串行时钟线)实现设备之间的通信,具有连接简单、支持多设备连接、占用引脚少等优点。在嵌入式系统中,I2C协议常用于连接各种传感器、EEPROM、ADC、DAC、I/O扩展器等外设。

具体来说,I2C协议可用于以下场景:

  • 传感器通信:如温度传感器、加速度传感器等,通过I2C接口与主控制器通信,传输测量数据。
  • 存储器件通信:如EEPROM存储器,用于存储配置信息或数据,通过I2C接口进行读写操作。
  • 模拟/数字转换器(ADC/DAC)通信:通过I2C接口控制ADC/DAC的转换过程,并读取转换结果。
  • I/O扩展器通信:当主控制器的I/O口不足时,可以通过I2C接口连接I/O扩展器,以扩展更多的I/O口。

代码实现

I2C协议的代码实现通常涉及以下几个关键步骤:

  1. 初始化I2C接口:配置GPIO引脚为I2C模式,设置波特率(时钟频率)、主从模式等参数。

  2. 发送起始条件:当SCL为高电平时,拉低SDA,然后拉低SCL,表示通信开始。

  3. 发送从机地址和读写命令:发送7位从机地址和1位读写控制位(0表示写操作,1表示读操作)。

  4. 发送数据或接收数据

    • 写操作:发送寄存器地址,然后发送数据到指定的寄存器。每发送一个字节数据后,等待从机的应答信号(ACK)。
    • 读操作:发送寄存器地址后,重新启动总线并发送从机地址和读命令,然后从从机读取数据。每读取一个字节数据后,根据需要发送应答信号(ACK)或停止信号(NACK)。
  5. 发送停止条件:当数据传输完成时,发送停止条件,即先拉高SDA,然后拉高SCL,表示通信结束。

以下是一个简化的I2C写操作代码示例(以STM32为例,使用HAL库):

#include "stm32f4xx_hal.h"

I2C_HandleTypeDef hi2c1;

// 初始化I2C接口
void MX_I2C1_Init(void)
{
    // 配置GPIO引脚为I2C模式
    // ...

    // 初始化I2C句柄
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 100000; // 设置波特率为100kHz
    HAL_I2C_Init(&hi2c1);
}

// 发送I2C数据
void I2C_WriteData(uint8_t DevAddress, uint8_t RegAddress, uint8_t *pData, uint16_t Size)
{
    HAL_StatusTypeDef status;

    // 发送起始条件和从机地址+写命令
    status = HAL_I2C_Mem_Write(&hi2c1, DevAddress << 1, RegAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 1000);

    if (status != HAL_OK)
    {
        // 处理错误
        Error_Handler();
    }
}

// 错误处理函数
void Error_Handler(void)
{
    // 具体的错误处理逻辑
}

请注意,上述代码是一个简化的示例,实际项目中可能需要根据具体的硬件平台和开发环境进行调整。

在面试中,除了介绍I2C协议的使用场景和代码实现外,还可以进一步讨论I2C通信中的注意事项、错误处理机制、性能优化等方面的问题,以展示对I2C协议的深入理解。

(4)Linux下I2C驱动编程:I2C核心层、I2C总线层、I2C驱动层

1. I2C核心层与I2C总线层的交互

  • 注册与注销:I2C总线层中的每个I2C适配器都需要通过I2C核心层进行注册。注册过程中,I2C核心层会验证适配器的信息,并将其加入到内核的I2C适配器列表中。同样,当适配器不再需要时,也会通过I2C核心层进行注销。
  • 通信方法:I2C核心层提供了一套通信方法(如i2c_transfer()),这些方法允许I2C设备驱动层通过I2C总线层与I2C设备进行通信。当I2C设备驱动层需要发送或接收数据时,它会调用这些通信方法,并由I2C核心层将请求转发给相应的I2C适配器。
  • 错误处理:在通信过程中,如果发生错误(如总线冲突、设备无响应等),I2C适配器会通过I2C总线层向I2C核心层报告错误。I2C核心层会处理这些错误,并根据需要向上层(如I2C设备驱动层)报告。

2. I2C核心层与I2C设备驱动层的交互

  • 设备发现与匹配:当I2C设备连接到I2C总线上时,I2C核心层会探测总线上的设备,并尝试与它们进行通信。通过读取设备的地址和标识符,I2C核心层可以确定设备的类型,并将其与相应的I2C设备驱动程序进行匹配。
  • 数据传输:一旦设备被正确匹配并初始化,I2C设备驱动层就可以通过I2C核心层提供的通信方法与设备进行数据传输。这些传输请求由I2C设备驱动层发起,经过I2C核心层处理后,由I2C总线层转发给相应的I2C适配器。
  • 设备控制:I2C设备驱动层还负责控制设备的行为,如设置设备的配置参数、启动或停止设备的工作等。这些控制命令同样通过I2C核心层进行传输,并由I2C总线层转发给I2C适配器,最终由适配器控制I2C设备进行相应的操作。

3. I2C总线层与I2C设备驱动层的间接交互

  • 间接性:虽然I2C总线层并不直接与I2C设备驱动层进行交互,但它通过I2C核心层作为中介来实现与I2C设备驱动层的通信。这种间接交互确保了I2C设备驱动层无需关心具体的硬件细节,只需按照I2C核心层提供的接口进行操作即可。
  • 数据转发:在数据传输过程中,I2C总线层负责将I2C设备驱动层发送的数据转发给I2C适配器,并将从I2C适配器接收到的数据转发给I2C设备驱动层。这种数据转发机制确保了数据的正确传输和同步。

综上所述,I2C核心层、I2C总线层和I2C设备驱动层之间的交互是通过一系列的函数调用、回调机制和错误处理来实现的。这种分层架构使得Linux系统能够高效地管理I2C设备,并确保它们之间的正确通信。

(5)platform 与 设备树的区别

在嵌入式系统中,Platform(平台总线)与设备树(Device Tree)是两个重要的概念,它们在Linux内核中扮演着不同的角色,用于管理和配置硬件设备。以下是它们之间的详细区别:

Platform(平台总线)

定义与作用

  • Platform总线是内核注册好的一种用于管理设备及驱动的模式。它提供了一种机制,使得设备和驱动能够在内核中进行注册和匹配,从而实现设备的识别和驱动程序的加载。
  • Platform总线通过struct bus_type结构体进行实现,内核已经实现了这一总线的匹配规则,并对设备和驱动的类型进行了抽象。

特点

  • 驱动分离:Platform总线的一个主要优势是实现了驱动与具体硬件信息的分离。驱动开发者只需要关注驱动逻辑的实现,而不需要关心硬件的具体信息。
  • 自动匹配:Platform总线采用自动匹配的方法,通过设备树(如果有的话)或其他机制来匹配设备和驱动,无需手动搜索和配置。
  • 简化开发:Platform总线简化了驱动的开发过程,开发者只需要关注驱动逻辑的实现,而不需要处理复杂的设备发现和匹配过程。

设备树(Device Tree)

定义与作用

  • 设备树是一种用于描述计算机硬件信息的数据结构,它以树状结构的形式存在,包含了CPU、内存、总线和其他外设的详细信息。
  • 设备树的主要作用是为操作系统的内核提供硬件的详细信息,以便内核能够正确地识别、配置和使用这些硬件。

特点

  • 硬件抽象:设备树通过对硬件信息的抽象,实现了硬件信息与驱动代码的分离。这样,当硬件发生变化时,只需要修改设备树文件,而无需修改驱动代码。
  • 灵活配置:设备树提供了灵活的硬件配置方式,可以支持多种不同的硬件平台和配置选项。
  • 标准化:随着设备树规范的不断发展和完善,它已经成为了一种标准化的硬件配置方式,被广泛应用于各种嵌入式系统和Linux内核中。

Platform与设备树的区别

Platform 设备树
定义 内核注册好的用于管理设备及驱动的模式 描述计算机硬件信息的数据结构
作用 提供设备和驱动的注册、匹配机制 为内核提供硬件的详细信息,支持硬件的识别和配置
特点 - 驱动分离
- 自动匹配
- 简化开发
- 硬件抽象
- 灵活配置
- 标准化
关系 Platform总线可能依赖于设备树来匹配设备和驱动(如果设备树可用) 设备树为Platform总线提供硬件信息,使其能够正确地匹配设备和驱动

总结来说,Platform总线是一种管理设备和驱动的机制,而设备树则是一种描述硬件信息的数据结构。它们在Linux内核中协同工作,共同实现了硬件的识别和配置。Platform总线通过设备树(或其他机制)获取硬件信息,并据此匹配和加载相应的驱动程序。

(6)linux 下怎么获取到设备树中硬件(板级)的信息

在Linux下获取设备树(Device Tree)中硬件(板级)的信息,主要涉及到设备树的解析、遍历以及节点信息的读取。以下是一个详细的步骤说明:

一、设备树的基本概念

设备树(Device Tree)是一种硬件描述机制,用于在嵌入式系统和操作系统中描述硬件设备的特性、连接关系和配置信息。它采用一种结构化的方式来描述硬件平台,包括CPU、内存、外设、总线等资源,使得驱动程序和内核代码能够更容易地适应不同的硬件平台。

二、设备树的组成

设备树主要由DTS(Device Tree Source)文件描述,这些文件采用类似于文本的语法来描述硬件设备的结构、属性和连接关系。DTS文件被编译成DTB(Device Tree Blob)文件,即设备树的二进制表示形式,由操作系统加载和解析。

三、获取设备树中硬件信息的步骤

  1. 加载和解析设备树文件(.dtb)

    • 在系统启动阶段,通常由引导加载程序(如U-Boot)或内核自身加载并解析设备树文件。
    • 解析过程将二进制格式的设备树文件转换成内存中的数据结构,便于后续访问。
  2. 遍历设备树

    • 通过特定的API或数据结构遍历整个设备树。这通常涉及访问根节点,并递归地访问其子节点。
  3. 查找特定节点

    • 在遍历过程中,根据节点的名称、路径或其他属性查找特定的节点。这些节点通常代表系统中的硬件设备。
  4. 读取节点信息

    • 找到特定节点后,读取其属性、配置参数和其他相关信息。这些信息对于正确配置和使用该设备至关重要。

四、Linux内核中的设备树API

Linux内核提供了丰富的设备树API,允许开发者在代码中访问和操作设备树节点。以下是一些常用的API函数:

  • of_find_node_by_name:根据节点名称查找特定节点。
  • of_find_node_by_path:根据节点路径查找特定节点。
  • of_get_property:读取节点的属性信息。
  • of_property_read_u32of_property_read_string等:读取特定类型的属性信息。

五、示例代码

以下是一个简单的示例代码片段,展示了如何使用Linux内核提供的设备树API获取特定节点的信息:

#include <linux/of.h>

// 假设我们要查找名为"my_device"的节点
struct device_node *np;
np = of_find_node_by_name(NULL, "my_device");
if (!np) {
    // 节点未找到处理逻辑...
}

// 读取节点的某个属性(例如"reg")
const __be32 *reg_prop;
int len_p;
reg_prop = of_get_property(np, "reg", &len_p);
if (!reg_prop || len_p < sizeof(*reg_prop)) {
    // 属性读取失败处理逻辑...
}

// 使用属性信息(例如配置设备寄存器)...

// 使用完毕后, 释放对节点的引用(如果API要求这样做的话)
of_node_put(np);

六、实际使用中的问题及解决方案

在实际使用中,获取设备树节点信息可能会遇到以下问题:

  1. 节点不存在或路径错误

    • 解决方案:仔细检查设备树文件和代码中的路径指定,确保它们与实际的硬件配置一致。
  2. 属性读取失败

    • 解决方案:核对属性名称并确保它们与设备树文件中的定义一致。
  3. 内存分配失败

    • 解决方案:优化内存使用、减少不必要的节点或属性,并确保系统具有足够的可用内存。
  4. 版本兼容性问题

    • 解决方案:确保使用的内核版本与设备树文件的格式和语法兼容。

通过遵循以上步骤和注意事项,可以在Linux下有效地获取设备树中硬件(板级)的信息。

(7)TCP,UDP的不同之处,socket套接字编程了解吗,TCP服务器端的编程步骤,UDP和TCP socket编程哪里不同

一、TCP与UDP的区别

TCP(传输控制协议)和UDP(用户数据报协议)是两种常用的网络传输层协议,它们之间存在显著的差异:

  1. 连接性

    • TCP是面向连接的协议,在数据传输之前需要建立连接,类似于打电话前的拨号过程。
    • UDP是无连接的协议,发送数据之前不需要建立连接,直接发送数据包。
  2. 可靠性

    • TCP提供可靠的服务,确保数据无差错、不丢失、不重复,且按序到达。
    • UDP则尽最大努力交付,但不保证可靠交付,可能会出现数据丢失、乱序等问题。
  3. 数据传输方式

    • TCP是面向字节流的协议,将数据视为无结构的字节流。
    • UDP是面向报文的协议,每个UDP报文都包含完整的数据信息,并且UDP没有拥塞控制机制。
  4. 效率与开销

    • TCP由于需要建立连接和确保可靠性,其效率相对较低,且首部开销较大(通常为20字节)。
    • UDP则具有较高的传输效率,且首部开销较小(通常为8字节),适用于对实时性要求较高的应用场景。
  5. 通信模式

    • TCP支持一对一的通信模式。
    • UDP则支持一对一、一对多、多对一和多对多的通信模式。
  6. 应用场景

    • TCP适用于需要可靠传输的应用场景,如文件传输、Web浏览等。
    • UDP适用于对实时性要求较高且对可靠性要求不高的应用场景,如视频直播、在线游戏等。

二、Socket套接字编程的了解

Socket套接字是计算机网络中提供的一种通信机制,它允许应用程序在不同的主机之间进行数据交换。在嵌入式系统中,Socket编程是实现设备间通信的关键技术之一。Socket编程基于TCP/IP协议族,通过创建Socket套接字、绑定IP地址和端口号、监听连接(对于服务器端)、接受连接(对于服务器端)、发送和接收数据等步骤实现网络通信。

三、TCP服务器端的编程步骤

TCP服务器端的编程步骤通常包括以下几个步骤:

  1. 创建Socket套接字:使用socket()函数创建一个新的Socket套接字。
  2. 绑定IP地址和端口号:使用bind()函数将Socket套接字绑定到一个特定的IP地址和端口号上。
  3. 开启监听:使用listen()函数开始监听传入的连接请求。
  4. 接受连接:使用accept()函数接受客户端的连接请求,并返回一个新的Socket套接字用于与客户端通信。
  5. 收发数据:使用send()recv()函数(或write()read()函数)进行数据的发送和接收。
  6. 关闭连接:使用close()函数关闭Socket套接字连接。

四、UDP与TCP在Socket编程中的不同之处

在Socket编程中,UDP与TCP的主要不同之处体现在以下几个方面:

  1. 创建Socket类型

    • TCP使用流式套接字(SOCK_STREAM)。
    • UDP使用数据报套接字(SOCK_DGRAM)。
  2. 连接与无连接

    • TCP在发送数据前需要建立连接。
    • UDP则直接发送数据,无需建立连接。
  3. 数据发送与接收

    • TCP使用send()recv()函数(或write()read()函数)进行数据的发送和接收,且保证数据的可靠性和顺序性。
    • UDP使用sendto()recvfrom()函数进行数据的发送和接收,不保证数据的可靠性和顺序性。
  4. 端口号的使用

    • TCP和UDP都可以使用相同的端口号,但它们分别属于不同的协议族(TCP/IP协议族中的TCP协议和UDP协议)。
  5. 应用场景

    • TCP适用于需要可靠传输的应用场景。
    • UDP适用于对实时性要求较高且对可靠性要求不高的应用场景。

综上所述,TCP和UDP在Socket编程中各有特点和应用场景,开发者应根据实际需求选择合适的协议进行网络通信。

(8)I/O复用,select、epoll,poll的区别

在嵌入式面试中,面试官询问I/O复用技术,特别是select、epoll、poll的区别时,可以从以下几个方面进行回答:

一、概述

I/O复用(I/O Multiplexing)是一种高效的I/O模型,允许单个线程或进程同时处理多个I/O操作,通过监听多个文件描述符(如Socket、文件等)的状态,并在某个文件描述符就绪时通知程序进行相应的读写操作。select、poll、epoll是Linux环境下常见的三种I/O复用机制。

二、主要区别

1. 跨平台性

  • select:几乎在所有主流的操作系统上都支持,包括Windows、Linux、macOS等,具有良好的可移植性。
  • poll:也可以在多数平台上使用,如Linux、macOS等,但不支持Windows。
  • epoll:是Linux特有的I/O复用技术,仅适用于Linux系统。

2. 文件描述符数量限制

  • select:受文件描述符数量限制,一般默认在32位系统上限制为1024个,64位系统上限制为2048个。虽然可以通过修改内核参数来增加,但性能可能会受影响。
  • poll:理论上没有最大连接数的限制,因为它基于链表来存储文件描述符。
  • epoll:没有文件描述符数量限制,理论上可以支持非常大的并发连接数,适用于处理大规模并发连接的场景。

3. 工作机制

  • select:使用轮询模型,每次调用时都需要遍历所有注册的文件描述符集合,检查它们的状态。这种方式在文件描述符数量较多时效率较低。
  • poll:与select类似,也是轮询模型,但它将用户传入的数组拷贝到内核空间,然后查询每个文件描述符对应的设备状态。
  • epoll:基于事件驱动模型,通过回调函数只处理活跃的文件描述符。当文件描述符状态发生变化时,内核会主动通知用户空间的应用程序,从而避免了轮询,提高了效率。

4. 触发模式

  • select 和 poll:都使用水平触发模式(Level-Triggered),即当文件描述符状态就绪时,会一直通知应用程序进行处理,直到应用程序处理完所有数据后才返回阻塞状态。
  • epoll:支持边缘触发模式(Edge-Triggered, ET)和水平触发模式(Level-Triggered, LT)。在边缘触发模式下,只有当文件描述符状态发生变化时才会通知应用程序进行处理,如果应用程序没有处理完所有数据,则会返回阻塞状态。这种模式可以减少不必要的系统调用,提高性能。

5. 数据拷贝开销

  • select 和 poll:在内核空间和用户空间之间传递消息时,需要进行数据拷贝,增加了开销。
  • epoll:通过内核和用户空间共享一块内存(使用mmap)来实现消息的传递,减少了数据拷贝的开销。

三、总结

在选择I/O复用机制时,应根据具体的使用需求和场景来决定。对于需要处理大量并发连接的高性能场景,epoll是更好的选择。而对于跨平台性要求较高或文件描述符数量较少的应用场景,select或poll可能更合适。

(9)linux字符设备驱动程序的设计流程,file_operations 中read write,应用

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

ARM/Linux嵌入式真题 文章被收录于专栏

让实战与真题助你offer满天飞!!! 每周更新!!! 励志做最全ARM/Linux嵌入式面试必考必会的题库。 励志讲清每一个知识点,找到每个问题最好的答案。 让你学懂,掌握,融会贯通。 因为技术知识工作中也会用到,所以踏实学习哦!!!

全部评论
1 回复 分享
发布于 2024-08-31 11:25 北京
🐮🐮🐮🐮
1 回复 分享
发布于 2024-08-13 15:22 北京

相关推荐

2025-12-28 16:32
重庆邮电大学 Java
程序员花海:1.技能放最后,来面试默认你都会,技能没啥用 2.实习写的看起来没啥含金量,多读读部门文档,包装下 接LLM这个没含金量 也不要用重构这种 不会给实习生做的 3.抽奖这个还是Demo项目,实际在公司里面要考虑策略,满减,触发点,触发规则 库存 之类的,不是这个项目这么简单 4.教育背景提前,格式为 教育背景 实习 项目 技能 自我评价
简历被挂麻了,求建议
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
16
99
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务