- 博客(23)
- 收藏
- 关注
原创 面试必会(嵌入式)操作系统面试高频(三)线程与进程
在阻塞式 IO 模型中,当应用程序发起一个 IO 操作时,它会一直等待,直到操作完成并返回结果。在这个过程中,应用程序无法进行其他任务,会一直阻塞在该 IO 操作上。阻塞式 IO 模型简单易用,但会导致应用程序的整体性能受限,因为在等待 IO 完成期间无法进行其他工作。
2025-01-20 17:58:50
1143
原创 面试必会(嵌入式)操作系统面试高频(一)线程与进程
⭐⭐⭐进程进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位。是操作系统结构的基础。进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。线程线程是操作系统最小的运算调度单位。线程包含在进程中,是进程中实际执行任务的单位。在一些操作系统中,线程也被称为轻量级进程信号量是一种同步机制,它本质上是一个计数器,用于多进程或多线程对共享资源的访问。信号量的主要作用是保护共享资源,使得在一个时刻只有一定数量的进程或线程可以访问。
2025-01-19 17:14:18
816
原创 栈与队列(代码随想)
寻找前k个最大元素流程如图所示:(图中的频率只有三个,所以正好构成一个大小为3的小顶堆,如果频率更多一些,则用这个小顶堆进行扫描)
2025-01-17 18:25:03
763
原创 面试必会(嵌入式)-C++之<STL>(六)
双端操作:可以在头部和尾部进行高效的插入和删除操作。分段结构:内部实现采用分段的数据结构,只需要移动对应段内的元素,而不需要移动整个容器中的元素。随机访问:支持通过索引进行随机访问,可以在常量时间内访问任意位置的元素。迭代器稳定性:插入和删除不会使已存在的迭代器失效。增长特性:根据需要自动增长内部存储空间。内存分配效率:在增加新的段时分配更多的内存空间,提高内存利用效率。
2025-01-15 17:28:21
679
原创 面试必会(嵌入式)-C++之虚函数(五)
1.析构函数一般写成虚函数的原因:多态性支持:通过将析构函数声明为虚函数,可以实现指向派生类对象的基类指针或引用在运行时调用正确的析构函数。这样做可以确保派生类的析构函数得到调用,从而正确地清理派生类所分配的资源,而不仅仅是基类部分的资源。动态绑定:当基类指针或引用指向派生类对象时,将析构函数声明为虚函数可以实现动态绑定,即在运行时根据对象的类型选择正确的函数实现。如果析构函数不是虚函数,当删除一个基类指针时,只会调用基类的析构函数,而不会调用派生类的析构函数。
2024-12-24 10:02:41
1016
原创 面试必会(嵌入式)-C++面试高频(四)
右值引用(R-value reference)是 C++11 引入的一种新的引用类型,用于标识和操作右值。右值引用使用&&符号进行声明,例如int&&表示一个右值引用类型的整数。标识右值:右值引用主要用于标识和操作右值(临时值、表达式结果、将被销毁的值等)。右值引用只能绑定到右值,不能绑定到左值。移动语义:右值引用支持移动语义,通过对临时对象的资源所有权进行移动而不是复制,提高了操作的效率。例如,在对象的拷贝构造函数和拷贝赋值运算符中,可以通过移动构造函数和移动赋值运算符来实现对资源的转移。
2024-12-19 22:03:38
1102
原创 面试必会(嵌入式)-C++面试高频(三)
在C语言中,结构是一种复合数据类型,它可以由基本数据类型(如int、long、float等)的变量和其他复合数据类型(如数组、结构、联合等)的数据单元组成。结构中的成员按照声明的顺序在内存中顺序存储,但是为了提高CPU对变量的访问效率,变量在内存中需要进行字节对齐。为了使CPU能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的"对齐",比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除,也即"对齐"跟数据在内存中的位置有关。
2024-12-16 17:43:02
694
原创 面试必会(嵌入式)-C++面试高频(二)
拷贝构造函数的作用是创建一个对象的副本。对象的复制:当使用一个同类对象来初始化另一个同类对象时,拷贝构造函数被调用。例如,通过复制一个对象来创建一个新对象。参数传递:当将对象作为参数传递给函数时,拷贝构造函数用于创建参数的副本。返回值:当函数返回一个对象时,拷贝构造函数用于创建返回值的副本。浅拷贝不够:如果类中有指针成员或资源(如文件句柄)需要进行深度拷贝,以防止多个对象共享同一资源。否则,当一个对象销毁时,共享的资源可能会被释放,从而导致其他对象的资源变为无效。
2024-12-13 15:33:17
852
原创 面试必会(嵌入式)-C++面试高频(一)
野指针(Dangling Pointer):指的是没有初始化过的指针,它指向的地址是未知的、不确定的、随机的。产生野指针的原因主要是指针未初始化,防止的措施就是指针初始化(包括及时初始化或置空)。举例:int* ptr;// 未初始化的指针,成为野指针// 使用野指针会导致未定义的行为*ptr = 5;// 解引用野指针,可能导致程序崩溃return 0;悬挂指针(Dangling Reference):指针最初指向的内存已经被释放了的一种指针。
2024-12-12 22:24:34
847
原创 面试必会(嵌入式)-C语言面试高频(内存管理)
内存池(Memory Pool)是一种动态内存分配与管理技术。通常情况下习惯使用new/delete/malloc/free等API申请分配和释放内存,这样导致的后果是:当程序长时间运行时,由于所申请的内存块大小不定,频繁使用时会造成大量的内存碎片从而降低程序和操作系统的性能。内存池则是在真正使用内存之前,先申请分配一大块内存(内存池)留作备用,当我们申请内存时,从池中取出一块动态分配的内存,释放内存时,再将我们使用的内存释放到我们申请的内存池内,再次申请内存池也可以再取出来使用。
2024-12-12 18:56:11
717
原创 面试必会(嵌入式)-C语言高频(二)
原码:最高位表示符号,其余位表示数值的绝对值。正数的原码就是二进制表示,符号位为0。负数的原码符号位为1,数值位根据绝对值的二进制表示。反码:正数的反码与原码相同,负数的反码是对原码除符号位外的每一位取反(0 变为 1,1 变为 0)。补码:正数的补码与原码和反码相同,负数的补码是对反码加 1。
2024-12-11 15:08:08
1047
原创 面试必会(嵌入式)-C语言高频(一)
整型变量int a;:定义了一个变量a,它的类型是int。指针常量类型名 * const 指针名:一个指针类型的常量,本质上还是一个常量,因此常量p指向的地址就不可以更改(地址是一个常量),也就是说指针的值不可以更改,因为指针的值就是地址。代码示例:int * const p = &a // 常量必须初始化p = &b;// 错误,地址不可更改*p = 30;// 正确,值可以更改常量指针 ---- 常量类型的指针两种表示方式:1、const 类型名 * 指针名。
2024-12-11 10:32:35
732
原创 linux内存管理
如果这样的块存在,内核把 1024 个页框块的 256 个页框用作请求,然后从剩余的 768 个页框中拿 512 个插入到 512 个页框的链表中,再把最后的 256 个插入到 256 个页框的链表中。如果要是能将内存请求打散,比如以 10KB 为单位打散,那么 160KB 请求就是 16 片,150KB 的空闲内存区域能满足 15 片请求,然后在 50KB 空闲内存区域上分配 1 片,160KB 的内存请求就能全部满足。线性地址的低12位直接作为物理地址的低12位,从而组成一个完整的32位物理地址。
2024-11-28 15:21:21
1157
原创 linux操作系统-信号
在Linux操作系统中,信号(Signal)是一种重要的进程间通信机制,它允许一个进程向另一个进程发送异步通知。这些通知可以是简单的消息,如用户按下了中断键(如Ctrl+C),也可以是复杂的系统事件,如除零错误或定时器到期。信号的产生和处理是Linux系统编程中的一个关键方面,对于理解和优化系统行为至关重要。信号的基本特性:1.异步性:信号是异步事件,可以在任何时候、由任何进程(包括内核进程和用户进程)发送给另一个进程。2.通知性:信号的主要目的是通知接收进程某个事件的发生,而不是传递数据。
2024-11-23 19:28:34
1081
原创 linux-进程间通信
一个完整的系统离不开各种各样的进程执行不同的任务,不同的任务之间存在着一些联系,为了能够保证进程之间的协调运作,使系统达到的理想的效果,需要进程之间传递信息。由于一个进程是不能访问到另一个进程的资源的,即进程之前是具有独立性的。那么进程之间要通信,就不能使用属于进程的资源,。的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享内存、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
2024-11-22 17:29:40
876
原创 二叉树-总结
刚刚我们说过了二叉树有两种存储方式顺序存储,和链式存储,顺序存储就是用数组来存,这个定义没啥可说的,我们来看看链式存储的二叉树节点的定义方式。int val;大家会发现二叉树的定义 和链表是差不多的,相对于链表 ,二叉树的节点里多了一个指针, 有两个指针,指向左右孩子。这里要提醒大家要注意二叉树节点定义的书写方式。在现场面试的时候 面试官可能要求手写代码,所以数据结构的定义以及简单逻辑的代码一定要锻炼白纸写出来。
2024-11-13 16:31:02
1019
原创 哈希表、字符串
std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希, 使用unordered_set 读写效率是最高的,本题并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
2024-11-11 10:45:54
1007
原创 UART、I2C、SPI、RS485、RS232通讯协议
通用异步(波特率--时间)收发器,全双工,串行、异步通信总线;两线制(两根数据线 RX TX)、可以实现全双工的发送和接收;UART空闲状态通常保持在高电平,起始位给一个低电平,然后读取数据,停止位给一个高电平。起始位:1位低电平(先打招呼);数据位:5/6/7/8位,先发低位,后发高位(再发信息)每次最大发送8位,防止累计误差产生;校验位:校验数据正确性,降低但不可消除误码率,可有可无。奇偶校验数据中奇偶个数;停止位:1/1.5/2位高电平;
2024-11-10 11:50:32
2266
原创 c++(vector、map、list、deque、set)总结-面试
C++中有两种类型的容器:顺序容器和关联容器。顺序容器主要有vector、list、deque等。其中vector表示一段连续的内存,基于数组实现,list表示非连续的内存,基于链表实现,deque与vector类似,但是对首元素提供插入和删除的双向支持。关联容器主要有map和set。map是key-value形式,set是单值。map和set只能存放唯一的key,multimap和multiset可以存放多个相同的key。
2024-11-08 16:46:49
909
原创 面试嵌入式-数组
二分法是非常重要的基础算法,为什么很多同学对于二分法都是一看就会,一写就废?其实主要就是对区间的定义没有理解清楚,在循环中没有始终坚持根据查找区间的定义来做边界处理。区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。本篇根据两种常见的区间定义,给出了两种二分法的写法,每一个边界为什么这么处理,都根据区间的定义做了详细介绍。
2024-11-07 20:34:52
1026
原创 面试嵌入式-链表
/ 单链表int val;// 节点上存储的元素// 指向下一个节点的指针ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数我不定义构造函数行不行,答案是可以的,C++默认生成一个构造函数。但是这个构造函数不会初始化任何成员变量,下面我来举两个例子:所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值!动态内存分配链表节点的创建和删除操作相对灵活,可以根据需要动态地分配和释放内存,无需事先确定链表的长度。
2024-11-04 15:34:00
1078
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人