理论的东西不常用时就会慢慢的被遗忘,但是找工作就是一个如何让别人相信自己的过程,理论知识就是一个非常重要的途径。
一次次机会在错失,每次想找工作时,刷一下简历就去面试了,一次次因为理论被鄙视,也该长长记性了。
linux/android驱动工程师面试相关内容总结如下(以后遇到新问题再补充):
1、linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些?
答:Linux内核将内存空间分为两部分。将最高位的一段,供内核使用,称为"内核空间".而将较低位的一段,供各个进程使用,称为"用户空间“。内核地址空间由所有进程共享,但只有运行在内核态的进程才能访问。
a.存储的内容不同,内核空间中存放的是内核代码和数据,而用户空间中存放的是用户程序的代码和数据。不管是内核空间还是用户空间,它们都处于虚拟空间中。
b.分配方式不同,malloc/free;kmalloc/kfree等
等等吧,随便说说,这个不同处太多了。
通信方式有:系统调用、驱动程序本身也是、使用proc文件系统、使用虚拟文件系统、使用内存映像等,其中驱动中常用的是copy_from_user和copy_to_user.
2、linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化,高端内存概念?
答:内存划分为内核空间和用户空间,虚拟地址=物理地址+偏移地址,因为系统安全机制,所有的进程都无法直接访问物理地址,内核的虚拟地址在“高端”,但是映射的物理内存地址在低端。由此地址映射关系,那么内核逻辑地址空间访问为0xc0000000 ~ 0xffffffff,那么对应的物理内存范围就为0×0 ~ 0×40000000,即只能访问1G物理内存。所以地址映射时不能把0×0 ~ 0×40000000范围的地址用完,一般情况下划分三部分:ZONE_DMA、ZONE_NORMAL和 ZONE_HIGHMEM。ZONE_HIGHMEM即为高端内存,这就是内存高端内存概念的由来。使用超出ZONE_NORMAL对应的地址时,借用高端内存进行映射,用过之后及时释放。
3、linux中中断的实现机制,tasklet与workqueue的区别及底层实现区别?为什么要区分上半部和下半部?
答:为了在中断执行时间尽可能快和中断处理完成大量工作之间找到一个平衡点,Linux将中断处理程序分成两个半部,上半部和下半部。上半部的功能是注册中断,当一个中断发生时,它进行相应地硬件读写后就把中断处理函数的下半部挂到该设备的下半部执行队列中去。因此上半部执行速度很快,可以服务更多的中断请求。下半部来完成中断事件的绝大多数任务。上半部和下半部最大的不同是下半部是可中断的,而上半部是不可中断的,下半部完成了中断处理程序的大部分工作,所以通常比较耗时,因此下半部由系统自行安排运行,不在中断服务上下文中执行。Linux实现下半部的机制主要是tasklet和工作队列。Tasklet是一个可以在由系统决定的安全时刻在软件中断上下文被调用运行的特殊函数,它们可以被多次调用运行,但tasklet的调用并不会累积,也就是说只会运行一次,即使在激活tasklet的运行之前重复请求该tasklet的运行也是这样。Tasklet运行时可以有其他中断发生,因此在tasklet和中断服务程序之间的锁还是需要的。tasklet一般会较短的时间内被很快执行完毕,一般用于执行较短的中断下半部;工作队列运行在进程上下文中,因此可在必要时sleep,这是和tasklet最大的区别,工作队列一般可以有较长的时延,可以执行较长的中断下半部。
4、linux中断的响应执行流程?
答:当中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场。从异常中断处理程序退出时,要恢复被中断的程序的执行现场。通常有以下几步操作:
a.保存处理器当前状态、中断屏蔽位以及各条件标志位;
b.设置当前程序状态寄存器(CPSR)中相应的位;
c.将寄存器 lr_mode(当异常出现或调用函数时保存下一条指令的位置)设置成返回地址;
d.将程序计数器(PC)值设置成该异常中断的中断向量地址, 从而跳转到相应的异常中断处理程序处执行。
在接收到中断请求以后, ARM 处理器内核会自动执行以上四步,程序计数器 PC 总是跳转到相应的固定地址。然而从异常中断处理程序中返回也会有一些操作,主要包括下面两个基本操作:
a.恢复被屏蔽的程序的处理器状态;
b.返回到发生异常中断的指令的下一条指令处继续执行。
5、linux中的同步机制?spinlock与信号量的区别?
答:同步机制包括:原子操作、自旋锁和信号量。
自旋锁和信号量的区别:自旋锁同时只会允许一个任务来访问临界区,当自旋锁被占用时,申请者通过旋转来代替休眠,直到占用者释放掉锁。自旋锁一般用于较短的临界区,而且不允许休眠;信号量允许多个任务同时访问临界区,允许休眠,适用较长的共享区,当信号量被初始化为1时就是互斥锁。
原子操作可以保证指令以原子的方式执行,执行过程不被打断。它通过把读取和修改变量的行为包含在一个单步中执行,从而防止了竞争的发生,保证操作结果总是一致的(这里可以和volatile对比一下)。原子操作有专门的函数可以调用。
6、linux中RCU原理?
答:RCU机制是Linux2.6之后提供的一种数据一致性访问的机制,从RCU(read-copy-update)的名称上看,我们就能对他的实现机制有一个大概的了解,在修改数据的时候,首先需要读取数据,然后生成一个副本,对副本进行修改,修改完成之后再将老数据update成新的数据,此所谓RCU。
RCU的思路实际上很简单,如下所示:
a. 对于读操作,可以直接对共享资源进行访问,但是前提是需要CPU支持访存操作的原子化,现代CPU对这一点都做了保证。但是RCU的读操作上下文是不可抢占的(这一点在下面解释),所以读访问共享资源时可以采用read_rcu_lock(),该函数的工作是停止抢占。
b . 对于写操作,其需要将原来的老数据作一次备份(copy),然后对备份数据进行修改,修改完毕之后再用新数据更新老数据,更新老数据时采用了rcu_assign_pointer()宏,在该函数中首先屏障一下memory,然后修改老数据。这个操作完成之后,需要进行老数据资源的回收。操作线程向系统注册回收方法,等待回收。采用数据备份的方法可以实现读者与写者之间的并发操作,但是不能解决多个写者之间的同步,所以当存在多个写者时,需要通过锁机制对其进行互斥,也就是在同一时刻只能存在一个写者。
c. 在RCU机制中存在一个垃圾回收的daemon,当共享资源被update之后,可以采用该daemon实现老数据资源的回收。回收时间点就是在update之前的所有的读者全部退出。由此可见写者在update之后是需要睡眠等待的,需要等待读者完成操作,如果在这个时刻读者被抢占或者睡眠,那么很可能会导致系统死锁。因为此时写者在等待读者,读者被抢占或者睡眠,如果正在运行的线程需要访问读者和写者已经占用的资源,那么死锁的条件就很有可能形成了。
RCU思想是比较简单的,其核心内容紧紧围绕“写时拷贝”,采用RCU机制,能够保证在读写操作共享资源时,基本不需要取锁操作,能够在一定程度上提升性能。但是该机制的应用是有条件的,对于读多写少的应用,机制的开销比较小,性能会大幅度提升,但是如果写操作较多时,开销将会增大,性能不一定会有所提升。总体来说,RCU机制是对rw_lock的一种优化。
7、linux中软中断的实现原理?
答:中断的执行的过程分为上下两部分,但是下半部分执行过程中有两个缺陷:(1)在任意一时刻,系统只能有一个CPU可以执行下半部代码,以防止两个或多个CPU同时来执行下半部函数而相互干扰。因此下半部代码的执行是严格“串行化”的。(2)下半部函数不允许嵌套。
这两个缺点在单CPU系统中是无关紧要的,但在多CPU系统中却是非常致命的。因为下半部机制的严格串行化执行显然没有充分利用多cpu系统的多CPU特点。为此,Linux2.4内核在下半部机制的基础上进行了扩展,这就是所谓的“软中断请求”(softirq)机制。 整个softirq机制的设计与实现中自始自终都贯彻了一个思想:“谁触发,谁执行”(Who marks,Who runs),也即触发软中断的那个CPU负责执行它所触发的软中断,而且每个CPU都由它自己的软中断触发与控制机制。这个设计思想也使得softirq 机制充分利用了SMP系统的性能和特点。
软中断的工作过程模拟了硬中断的处理过程:
a、当某一软中断事件发生后,首先需要设置对应的中断标记位,触发中断、设置软中断状态。
答:字符设备:字符设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少实现open,close,read和write系统调用。字符终端、串口、鼠标、键盘、摄像头、声卡和显卡等就是典型的字符设备。
块设备:和字符设备类似,块设备也是通过/dev目录下的文件系统节点来访问。块设备上能够容纳文件系统,如:u盘,SD卡,磁盘等。
字符设备和块设备的区别仅仅在于内核内部管理数据的方式,也就是内核及驱动程序之间的软件接口,而这些不同对用户来讲是透明的。在内核中,和字符驱动程序相比,块驱动程序具有完全不同的接口。
答:主设备号:主设备号标识设备对应的驱动程序。虽然现代的linux内核允许多个驱动程序共享主设备号,但我们看待的大多数设备仍然按照“一个主设备对应一个驱动程序”的原则组织。
次设备号:次设备号由内核使用,用于正确确定设备文件所指的设备。依赖于驱动程序的编写方式,我们可以通过次设备号获得一个指向内核设备的直接指针,也可将此设备号当作设备本地数组的索引。
10、请简述中断于DMA的区别。
答:DMA:是一种无须CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率.
中断:是指CPU在执行程序的过程中,出现了某些突发事件时CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回源程序被中断的位置并继续执行。
所以中断和DMA的区别就是DMA不需CPU参与而中断是需要CPU参与的。
11、中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?
答:中断是CPU处于被动状态下来接受设备的信号,而轮询是CPU主动去查询该设备是否有请求。凡事都是两面性,所以,看效率不能简单的说那个效率高。如果是请求设备是一个频繁请求cpu的设备,或者有大量数据请求的网络设备,那么轮询的效率是比中断高。如果是一般设备,并且该设备请求cpu的频率比较底,则用中断效率要高一些。主要是看请求频率。