linux驱动工程面试必问知识点
Posted alantu2018
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动工程面试必问知识点相关的知识,希望对你有一定的参考价值。
linux内核原理面试必问(由易到难)
简单型
1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些?
2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化,高端内存概念?
3:linux中中断的实现机制,tasklet与workqueue的区别及底层实现区别?为什么要区分上半部和下半部?
4:linux中断的响应执行流程?中断的申请及何时执行(何时执行中断处理函数)?
5:linux中的同步机制?spinlock与信号量的区别?
6:linux中RCU原理?
7: linux中软中断的实现原理?(2014.03.11)
8:linux系统实现原子操作有哪些方法? (2014.03.22)
9:MIPS Cpu中空间地址是怎么划分的?如在uboot中如何操作设备的特定的寄存器? (2014.03.22)
复杂型:
1:linux中netfilter的实现机制?是如何实现对特定数据包进行处理(如过滤,NAT之类的)及HOOK点的注册?
2:linux中系统调用过程?如:应用程序中read()在linux中执行过程即从用户空间到内核空间?
3:linux内核的启动过程(源代码级)?
4:linux调度原理?
5:linux网络子系统的认识?
三: 笔试
1:二分法查找
2:大小端转化及判断
3: 二维数组最外边个元素之和?
4:特定比特位置0和1
5:字符串中的第一个和最后一个元素交换(字符串反转)?
1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些?
答:
-在32位架构cpu中,物理内存大小限制在4G。linux将4G内存分为两部分,0~1G为kernel使用,1~4G为用户使用;进程运行在kernel,就是运行在0-1G,进程运行在用户空间,就是运行在1-4G。
-用户空间和内核空间通信方式有那些?
1. 使用API:这是最常使用的一种方式了
A.get_user(x,ptr):在内核中被调用,获取用户空间指定地址的数值并保存到内核变量x中。
B.put_user(x,ptr):在内核中被调用,将内核空间的变量x的数值保存到到用户空间指定地址处。
C.Copy_from_user()/copy_to_user():主要应用于设备驱动读写函数中,通过系统调用触发。
2. 使用proc文件系统:和sysfs文件系统类似,也可以作为内核空间和用户空间交互的手段。
3. netlink
4. 使用mmap系统调用
5. 信号
内核空间和用户空间通信方式
2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化,高端内存概念?
1. 用户虚拟地址
这是在用户空间进程所能看到的常规地址。每个进程多有自己的虚拟地址,并且可以使用大于物理内存大小的空间。
2. 物理地址
该地址在处理器和系统内存之间使用,对应与真是物理地址。
3. 总线地址
没看懂,不说了。
4. 内核逻辑地址
内核逻辑地址组成了内核的常规地址空间。该地址映射了部分(或者全部)内存,并经常被视为物理地址。
逻辑地址使用硬件内建的指针大小,因此在安装了大量内存的32位系统中,它无法寻址全部的物理内存。
逻辑地址通常保存在unsigned long或者void *这样类型的变量中。kmalloc返回的内存就是内核逻辑地址。
(上面这段话很重要,一定要理解,建议自己使用记号笔标红)
5. 内核虚拟地址
内核虚拟地址与物理地址的映射不必是一对一的,而这是虚拟地址的特点。
所有逻辑地址都是内核虚拟地址,但是许多内核虚拟地址不是逻辑地址。vmalloc分配的内存就是一个虚拟地址。
可以参考下面的地址:
总结:高端内存的作用就是用于建立临时地址映射,用于kernel申请user空间内存
3: linux中中断的实现机制,tasklet与workqueue的区别及底层实现区别?为什么要区分上半部和下半部?
答:
tasklet和workqueue区别?
tasklet运行于中断上下文,不允许阻塞 、休眠,而workqueue运行与进程上下文,可以休眠和阻塞。
为什么要区分上半部和下半部?
中断服务程序异步执行,可能会中断其他的重要代码,包括其他中断服务程序。因此,为了避免被中断的代码延迟太长的时间,中断服务程序需要尽快运行,而且执行的时间越短越好,所以中断程序只作必须的工作,其他工作推迟到以后处理。所以Linux把中断处理切为两个部分:上半部和下半部。上半部就是中断处理程序,它需要完成的工作越少越好,执行得越快越好,一旦接收到一个中断,它就立即开始执行。像对时间敏感、与硬件相关、要求保证不被其他中断打断的任务往往放在中断处理程序中执行;而剩下的与中断有相关性但是可以延后的任务,如对数据的操作处理,则推迟一点由下半部完成。下半部分延后执行且执行期间可以相应所有中断,这样可使系统处于中断屏蔽状态的时间尽可能的短,提高了系统的响应能力。实现了程序运行快同时完成的工作量多的目标。
4:linux中断的响应执行流程?中断的申请及何时执行(何时执行中断处理函数)?
中断的响应流程:cpu接受终端->保存中断上下文跳转到中断处理历程->执行中断上半部->执行中断下半部->恢复中断上下文。
中断的申请request_irq的正确位置:应该是在第一次打开 、硬件被告知终端之前。
5:linux中的同步机制?spinlock与信号量的区别?
linux中的同步机制:自旋锁/信号量/读取所/循环缓冲区
spinlock在得不到锁的时候,程序会循环访问锁,性能下降
信号量在得不到锁的时候会休眠,等到可以获得锁的时候,继续执行。
1、255.255.254.0网段最多能支持多少主机?(大概有5个备选项)
2、10M网卡传输过程中物理层采用什么编码?(SNAP?)(大概有4个备选项)
3、栈与队列的特点?(备选大概只有两个,A为FIFO,B为LIFO)
4、Cache的工作方式划分?(大概也有4个答案,大概是:write-none,write-all,write-through,write-back)。
5、什么叫NMI中断?(四个备选项)
6、RISC主要性能及特性?(大概有6个备选项)
7、在嵌入式系统中,所谓的北桥指的是什么?
(2)简答题:
1、说说轮巡任务调度与抢占式任务调度的区别?(大概为8分吧,记不清了)
2、什么叫存储器高速缓存技术,其主要目的?(大概6分)
3、画出计算机组成的最小逻辑框图。(哼,这道题竟然10分)
4、谈谈Volatile与Register修饰符的作用?
1、linux驱动分类
a. 字符设备
b. 块设备
c.网络设备
字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。
块设备可以用任意顺序进行访问,以块为单位进行操作,如硬盘、软驱等。
字符设备不经过系统的快速缓冲,而块设备经过系统的快速缓冲。但是,字符设备和块设备并没有明显的界限,如对于Flash设备,符合块设备的特点,但是我们仍然可以把它作为一个字符设备来访问。
网络设备在Linux里做专门的处理。Linux的网络系统主要是基于BSD unix的socket 机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递。系 统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。
2、信号量与自旋锁
自旋锁
自旋锁是专为防止多处理器并发而引入的一种锁,它应用于中断处理等部分。对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁。
自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。
事实上,自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。但是自旋锁节省了上下文切换的开销。
自旋锁的基本形式如下:
spin_lock(&mr_lock);
//临界区
spin_unlock(&mr_lock);
因为自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务。在单处理器上,自旋锁仅仅当作一个设置内核抢占的开关。如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核。
简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用。
死锁:假设有一个或多个内核任务和一个或多个资源,每个内核都在等待其中的一个资源,但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待,但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源,无法继续运行,这便意味着死锁发生了。自死琐是说自己占有了某个资源,然后自己又申请自己已占有的资源,显然不可能再获得该资源,因此就自缚手脚了。递归使用一个自旋锁就会出现这种情况。
信号量
信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。
信号量基本使用形式为:
static DECLARE_MUTEX(mr_sem);//声明互斥信号量
if(down_interruptible(&mr_sem))
//可被中断的睡眠,当信号来到,睡眠的任务被唤醒
//临界区
up(&mr_sem);
信号量和自旋锁区别
从严格意义上讲,信号量和自旋锁属于不同层次的互斥手段,前者的实现有赖于后者。
注意以下原则:
如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。
自旋锁对信号量
需求 建议的加锁方法
低开销加锁 优先使用自旋锁
短期锁定 优先使用自旋锁
长期加锁 优先使用信号量
中断上下文中加锁 使用自旋锁
持有锁是需要睡眠、调度 使用信号量
3、platform总线设备及总线设备如何编写
Linux设备模型(总线、设备、驱动程序和类)【转】
文章的例子和实验使用《LDD3》所配的lddbus模块(稍作修改)。
提示:在学习这部分内容是一定要分析所有介绍的源代码,知道他们与上一部分内容(kobject、kset、attribute等等)的关系,最好要分析一个实际的“flatform device”设备,不然会只学到表象,到后面会不知所云的。
总线
总线是处理器和一个或多个设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟"platform"总线。总线可以相互插入。设备模型展示了总线和它们所控制的设备之间的实际连接。
在 Linux 设备模型中, 总线由 bus_type 结构表示, 定义在 <linux/device.h> :
|