嵌入式面试常见问题(四)—牛客网_面试kzalloc

Linux中断处理过程分为两部分: 上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可以放在上半部完成。 下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部去执行,这样中断处理函数就会快进快出。 那些对时间敏感、执行速度快的操作可以放到中断处理函数中,也就是上半部。剩下的所有工作都可以放到下半部去执行,比如在上半部将数据拷贝到内存中,关于数据的具体处理就可以放到下半部去执行。一般来说,不希望被其他中断打断、对时间敏感、和硬件有关的任务建议放在中断上半部。

13、说一说进程的几个状态及转换条件?

进程状态包括就绪态,运行态,阻塞态,除此以外还包括新建态和退出态。 进程首次创建并未参与调度为新建态 从新建态做好准备(初始化成功)等待调度为就绪态 内核调度此进程时,此进程从就绪态转换为运行态 进程执行完内核分配的时间片后,从运行态再次回到就绪态 进程执行时如果等待其他条件满足后才能执行,则进程从运行态转换为阻塞态 阻塞的进程等待的条件满足后,进程重新进入就绪态 进程终止或者异常,进程将进入退出态

14、static修饰局部变量和全局变量会有什么效果

静态全局变量:具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。 静态局部变量:具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。

15、堆和栈的区别

栈由系统分配,堆由程序员控制,例如C/C++的malloc函数 栈的大小较小,有默认上限,堆理论上可以申请整个虚拟内存的大小 栈向下增长,地址由高到低,堆向上增长,地址从低到高 栈的分配效率较高,保证函数执行跳转的效率,堆的分配更为复杂,容易产生碎片,需要回收 栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等;堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

16、简述gcc编译过程

预处理、编译、汇编和链接,一个hello.c的c语言程序如下。 预处理阶段:hello.c–>hello.i 编译阶段:hello.i–>hello.s 汇编阶段:hello.s–>hello.o 链接阶段:hello.o–>hello

17、线程与进程的区别

进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发;
线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发;
线程是操作系统可识别的最小执行和调度单位。 一个线程只能属于一个进程,而一个进程可以有多个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存 进程是资源分配的最小单位,线程是CPU调度的最小单位进程切换的开销也远大于线程切换的开销。进程编程调试简单可靠性高,但是创建销毁开销大;线程正相反,开销小,切换速度快,但是编程调试相对复杂

18、野指针出现情况、怎么解决

1.指针变量声明时没有被初始化,可以在指针声明时初始化,可以是具体的地址值,也可让它指向NULL。
2.指针 p 被 free 或者 delete 之后,没有置为 NULL。指针指向的内存空间被释放后指针应该指向NULL。
3.指针操作超越了变量的作用范围,在变量的作用域结束前释放掉变量的地址空间并且让指针指向NULL。

19、DMA有什么用

直接存储器存取(Direct Memory Access,DMA)可以让某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道 CPU。在同等程度的CPU负担下,DMA是一种快速的数据传送方式。它允许不同速度的硬件装置来沟通,而不需要依于 CPU的大量中断请求。大大提高了访问效率,减少访问时间,降低CPU资源的消耗。

20、说一说RISC和CISC的区别

精简指令集RISC和复杂指令集CISC CISC处理的是不等长指令集,它必须对不等长指令进行分割,因此在执行单一指令的时候需要进行较多的处理工作。而RISC执行的是等长精简指令集,CPU在执行指令的时候速度较快且性能稳定。因此在并行处理方面RISC明显优于CISC,RISC可同时执行多条指令,它可将一条指令分割成若干个进程或线程,交由多个处理器同时执行。由于RISC执行的是精简指令集,所以它的制造工艺简单且成本低廉。

21、谈一谈什么是系统声明周期,说说你对敏捷开发的理解以及和SDLC的关系

SDLC:sdlc(系统生命周期,系统生存周期)是软件的产生直到报废的生命周期,是软件工程中的一种思想原则,包括: 问题定义及规划、需求分析、软件设计、程序编码、软件测试、运行维护 敏捷开发的核心是迭代开发(iterative development)。敏捷一定是采用迭代开发的方式。迭代开发将一个大任务,分解成多次连续的开发,本质就是逐步改进。一般采用"增量开发"(incremental development)划分迭代。所谓"增量开发",指的是软件的每个版本,都会新增一个用户可以感知的完整功能。 虽然敏捷开发将软件开发分成多个迭代,但是也要求,每次迭代都是一个完整的软件开发周期,必须按照软件工程的方法论,进行正规的流程管理。也就是说,敏捷开发的每一次迭代都需要一个完整的SDLC。

22、说说对MMU及TLB的理解

MMU是内存管理单元,它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线的仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。 TLB(Translation Lookaside Buffer)传输后备缓冲器是一个内存管理单元用于改进虚拟地址到物理地址转换速度的缓存。TLB是一个小的,虚拟寻址的缓存,其中每一行都保存着一个由单个PTE组成的块。如果没有TLB,则每次取数据都需要两次访问内存,即查页表获得物理地址和取数据。 TLB( Translation Look- aside buffer)专门用于缓存内存中的页表项,一般在MMU单元内部。TLB是一个很小的 cache,TLB表项( TLB entry)数量比较少,每个TLB表项包含一个页面的相关信息,例如有效位、虚拟页号、修改位、物理页帧号等。当处理器要访问一个虚拟地址时,首先会在TLB中查询。如果TLB表项中没有相应的表项,称为TLB Miss,那么就需要访问页表来计算出相应的物理地址。如果TLB表项中有相应的表项,那么直接从TLB表项中获取物理地址,称为TLB命中。

23、芯片选型考虑哪些因素?

1.根据功能设计需求、成本、供应商等主要因素初步确定几款合适的芯片。
2.普通I/O口,考虑数量、负载能力,还需要保证裕量,如果有迭代升级,还需要考虑兼容性
3.片上存储和外围存储,保证bootloader和程序image的容量;内存支持,由程序的RAM需求决定
4.主频及时钟,决定芯片的运行效率,响应和处理速度
5.电源及功耗,由板上电源和承载能力决定
6.如果是CPU芯片,考虑多核和多线程并发能力;如果是FPGA芯片,考虑逻辑单元资源数;如果是DSP芯片,考虑浮点计算能力
7.工作环境,如辐射、单粒子和温度范围 8.芯片成本和交付日期,是否可以购买到,以及购买周期与开发周期的平衡 总结,与软件相关的因素:I/O,内存,外存,处理器核和多线程,系统可移植性等

24、有cache的CPU上使用DMA如何保证数据的一致性

Cache是CPU和主存之间的缓冲,DMA是为了主存和I/O数据交互设计的,期间CPU不参与控制。那么如果数据在主存中被CPU修改但是仍在cache中,即尚未更新主存,此时DMA获取的将是旧的数据,导致数据的不一致性。因此DMA在访问主存时,应当先检查cache是否命中,如果命中的话,DMA需要从Cache读取数据而非内存。 在设计时可以使用总线监视技术或者nocache机制解决非一致性问题,在软件层次上,当DMA往主存写数据时,在DMA传输之前,可以invalid DMA Buffer地址范围的高速缓存。在DMA传输完成后,程序读取数据不会由于cache hit导致读取过时的数据。 相反,DMA将数据输出时,在DMA传输之前,可以clean DMA Buffer地址范围的高速缓存,clean的作用是写回cache中修改的数据。在DMA传输时,不会把主存中的过时数据发送到I/O设备。

25、volatile关键字作用?

操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。一般说来,volatile用在如下的几个地方:

  1. 中断服务程序中修改的供其它程序检测的变量需要加volatile;
  2. 多任务环境下各任务间共享的标志应该加 volatile;
  3. 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
26、简述字节对齐?

内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。 如果不按照平台要求对数据存放进行对齐,会带来存取效率上的损失。比如32位的Intel处理器通过总线访问(包括读和写)内存数据。每个总线周期从偶地址开始访问32位内存数据,内存数据以字节为单位存放。如果一个32位的数据没有存放在4字节整除的内存地址处,那么处理器就需要2个总线周期对其进行访问,显然访问效率下降很多。因此,通过合理的内存对齐可以提高访问效率。为使CPU能够对数据进行快速访问,数据的起始地址应具有“对齐”特性。比如4字节数据的起始地址应位于4字节边界上,即起始地址能够被4整除。此外,合理利用字节对齐还可以有效地节省存储空间。但要注意,在32位机中使用1字节或2字节对齐,反而会降低变量访问速度。因此需要考虑处理器类型。还应考虑编译器的类型。在VC/C++和GNU GCC中都是默认是4字节对齐。 字节对齐最主要反映在结构体对齐,对齐的原则如下:

  1. 数据类型自身的对齐值:char型数据自身对齐值为1字节,short型数据为2字节,int/float型为4字节,double型为8字节。
  2. 结构体或类的自身对齐值:其成员中自身对齐值最大的那个值。
  3. 指定对齐值:#pragma pack (value)时的指定对齐值value。
  4. 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}。
27、宏函数和内联函数的区别

内联函数是代码被插入到调用者代码处的函数。如同#define宏,内联函数通过避免被调用的开销来提高执行效率,尤其是它能够通过调用(“过程化集成”)被编译器优化。 宏定义不检查函数参数和返回值,只是展开,相对来说,内联函数会检查参数类型,所以更安全。 内联函数和宏很类似,而区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以像调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。

28、虚拟地址怎么转换到物理地址

地址转换(Address Translation)负责将虚拟地址转换成物理地址。现代操作系统有很多实现手段: 最简单的base+bound技术,进程通过寄存器base和bound来转换内存,不能保证安全性,程序的不同内存区需要连续,不能动态管理。

段技术:硬件为每个进程分配一组Base和Bound寄存器,每一对Base和Bound控制虚拟地址空间的一部分内存,称为段。每一段的虚拟地址空间是连续的,转换得到物理地址空间也是连续的,各个段之间不需要连续。这个技术可以很好的管理不同内存区,但是对于长度掌控的管理开销较大,寻找一段长度适合的物理地址需要额外开销。

页技术:将虚拟内存空间和物理内存空间皆划分成大小相同的页面,例如4KB、8KB和16KB等。并将页作为内存空间的最小分配单位,一个程序的一个页面(虚拟页面)可以存放在任何一个物理页面中。一个程序发出的虚拟地址由虚拟页面号和页内偏移值两部分组成。 快表TLB通常和处理器在一起,查找速度非常快,包含多级TLB,第一级TLB容量小、速度快,第二级TLB容量大、速度比第一级慢一些。可以大大提高虚拟地址转换为物理地址的效率。

29、进程A执行,发生一个中断,中断发了一个信号,会让更高优先级的进程B执行,这时候中断结束,应该返回进程A还是进入进程B,并解释理由

返回进程A。操作系统中中断优先级高于普通的进程,中断发生时,将保护进程A的现场并进入中断上下文,此时进程A仍然是执行态;中断结束后,操作系统将恢复进程A的现场并执行剩下的时间片,进程B的优先级虽然提高了,但需要等待A执行结束后下次调度时才可以执行,如果系统中没有其他中断或者更高优先级的进程的情况。

30、如果两个进程,都要去调用一个设备驱动,设备驱动里面定义的变量是在内核态吗?如果进程A访问并改变了这个变量,那么进程B再访问,是不是读到改变之后的值

驱动程序中的变量是在内核态中,因为操作系统只有内核态可以访问到硬件设备,驱动程序从内核态像用户态输出API以便调用和间接访问硬件设备。 进程B访问的是改变后的值,只有在没有考虑并发编程的驱动程序中才可能发生数据的不一致性。内核驱动程序开发必须考虑并发的问题,因为驱动程序将会被一个或者多个进程访问,对于共享的变量,需要加入互斥锁、自旋锁、信号量或者原子操作等同步技术保证数据的一致性。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

系化!**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

  • 21
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值