转载-Linux驱动面试题汇总
1、基础题
(1)Linux系统中内核空间与用户空间的区别?用户空间与内核空间的通信方式有哪些?
https://blog.csdn.net/bingqingsuimeng/article/details/7924756
(2)Linux系统中字符设备与块设备的区别?请列举一些实际的设备并归档属于哪类设备。
- 字符设备:是能够像字节流(类似于文件)一样被访问的设备,由字符设备驱动程序来实现这种特性,字符设备驱动程序通常至少实现open、close、read、write等系统调用,字符终端、串口、鼠标、键盘、摄像头、声卡和显卡等就是典型的字符设备;
- 块设备:和字符设备类似,块设备也是通过/dev/目录下的文件系统节点来进行访问的,不过块设备是以块为单位进行访问,并且支持随机读写,能容纳文件系统,U盘、TF卡、eMMC、磁盘等就是典型的块设备。
字符设备和块设备的区别仅仅在于内核内部管理数据的方式,也就是内核及驱动程序之间的软件接口,而这些不同对用户来讲是透明的,在内核中,块设备驱动和字符设备驱动程序具有完全不同的接口。
(3)Linux内核的启动过程(源码级)?
https://www.cnblogs.com/CrazyCatJack/p/6135435.html
(4)Linux系统中系统调用的过程是如何的?例如:应用程序中的read系统调用执行过程,从用户空间到内核空间。
https://blog.csdn.net/kai_zone/article/details/80459334
https://my.oschina.net/haomcu/blog/468656
(5)Linux系统调度原理
https://blog.csdn.net/janneoevans/article/details/8125106
(6)查看驱动模块中的打印信息应该使用什么命令?如何查看内核中已有的字符设备信息?如何查看正在使用的有哪些中断号?
- 查看驱动模块中打印信息可以使用dmesg;
- 查看字符设备信息可以使用lsmod和modprobe命令,lsmod可以查看模块的依赖关系,modprobe命令在加载模块时会加载其它依赖的模块;
- 显示当前使用的中断号,可以使用cat /proc/interrupt命令。
(7)copy_to_user()和copy_from_user()主要用于实现什么功能?一般应用于struct file_operations结构体的哪些函数里面?
由于内核空间和用户空间是不能直接相互访问的,如果需要访问就必须借助内核函数进行数据读写,copy_to_user()函数用来完成内核空间到用户空间数据的复制,copy_from_user()是完成用户空间到内核空间数据的复制,一般用于struct file_operations结构体里的read、write、ioctl等内存数据交换作用的函数。
(8)主设备号和次设备号的用途有什么?如果执行命令mknod chartest c 4 64,创建chartest设备,请分析chartest使用的是哪一类设备驱动程序。
- 主设备号标识设备对应的驱动程序,虽然现代的Linux内核允许多个驱动程序共享主设备号,但我们看待的大多数设备仍然按照"一个主设备对应一个驱动程序"的原则组织;
- 次设备号由内核使用,用于正确确定设备文件所指的设备,依赖于设备驱动程序的编写方式,我们可以通过次设备号获得一个指向内核设备的直接指针,也可以将此设备号当作设备本地数组的索引;
- chartest表示设备节点,4表示主设备号,64表示次设备号,该设备类似于串口终端或者字符设备终端。
(9)设备驱动程序中如何注册一个字符设备?分别解释一下函数参数的含义。
注册一个字符设备驱动具有两种方法:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
该注册函数可以将cdev结构体嵌入到自己的设备特定的结构中,cdev是一个指向结构体cdev的指针,而fops是指向file_operations结构体的指针。
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
该注册函数是早期的注册函数,major是主设备号,name是驱动程序的名称,fops是指向file_operations结构体的指针,该函数的调用将为给定的主设备号注册0~255作为次设备号,并为每个设备建立一个对应的默认的cdev结构体。
(10)Linux系统中RCU的基本原理?
https://www.cnblogs.com/-wang-cheng/p/5401653.html
(11)Linux系统中内存是如何划分以及如何使用的?虚拟地址以及物理地址的概念和转换,高端内存的概念?
https://www.cnblogs.com/dongzhiquan/p/5621906.html
(12)字符驱动设备如何创建设备文件?
- 手动创建,使用命令mknod /dev/char c 250 0可以创建设备文件,其中/dev/char为设备节点,c代表字符设备,250是设备的主设备号,0是设备的次设备号;
- 使用UDEV/MDEV自动创建设备文件的方式,UDEV/MDEV是运行在用户态的程序,可以动态管理设备文件,包括创建和删除设备文件,运行在用户态意味着系统要运行之后在/etc/init.d/rcS脚本中会执行mdev -s自动创建设备节点。
(13)insmod加载一个驱动模块,会执行模块中的哪个函数?rmmod卸载一个驱动模块,会执行模块中的哪个函数?这两个函数在设计的过程中需要注意什么?有遇到过卸载驱动出现异常吗?是什么问题引起的?
insmod加载一个驱动模块,会调用module_init()函数,rmmod卸载一个驱动模块,会调用module_exit()函数,卸载模块时曾出现过卸载失败的情形,原因是存在进程正在使用模块,检查代码后发现产生了死锁的问题,要注意在module_init()函数中申请的资源,要在module_exit()函数中释放,包括存储、ioremap、定时器、工作队列相关资源。
(14)设备驱动模型的三个重要成员是什么?platform总线的匹配规则是什么?在具体应用上要不要先注册驱动再注册设备,是否有先后顺序?
设备驱动模型的三个重要成员是总线、设备、驱动。
platform总线的匹配规则是,要匹配的设备和驱动都要注册,设备可以在设备树里注册,也可以通过代码注册设备,当设备和驱动匹配成功后,会调用驱动程序里面的probe函数,该函数在platform_driver结构体中进行注册。
(15)内核函数mmap的实现原理以及机制?
https://blog.csdn.net/yinjiabin/article/details/7575653
https://blog.csdn.net/edwardlulinux/article/details/8604400
(16)在驱动调试过程中,遇到过oops没,你是怎么处理的?
https://blog.csdn.net/kangear/article/details/8217329
(17)ioctl和unlock_ioctl有什么区别?
https://blog.csdn.net/zhuangtim1987/article/details/41963411
https://blog.csdn.net/cbl709/article/details/7295772
(18)在驱动程序中操作物理地址为什么要先ioremap?
因为在内核中是没有办法直接访问到物理地址的,必须先要通过ioremap获取到相应的虚拟地址。
https://blog.csdn.net/zqixiao_09/article/details/50859505
(19)你平常是怎么用C写嵌入式系统的死循环的?
一般有for(;;){}和while(1){},一般for(;;)性能更优,对于for(;;){},这两个;;语句,编译器一般会优化掉的,直接进入死循环,对于while(1){},每循环一次都要判断常量1是否为0,while比for多做了这点事,但是从汇编的交度来说,代码是一样的。
(20)列举最少三种你所知道的嵌入式的体系结构,并请说明什么是ARM体系结构。
嵌入式的体系结构有arm、mips、x86等。
https://blog.csdn.net/qq_32651225/article/details/78176567
https://blog.csdn.net/chengtong222/article/details/64440661
(21)在内核驱动编程中,kmalloc和vmalloc的区别?
https://www.cnblogs.com/hongzhunzhun/p/4533960.html
https://www.cnblogs.com/wuchanming/p/4465155.html
(22)I2C的基本原理,总线框架,设备驱动编写方式?
https://blog.csdn.net/kai_zone/article/details/78026931
https://blog.csdn.net/kai_zone/article/details/78029501
(23)什么是kernel panic?
https://www.cnblogs.com/cherishui/p/3881428.html
(24)Linux中的用户模式和内核模式是什么含意?
https://blog.csdn.net/sinat_15799399/article/details/44238893
(25)如何在内核中申请大块的内存空间?
可以使用vmalloc()内核函数进行分配。
(26)Linux系统中,用户进程间通信主要有哪几种方式?
https://blog.csdn.net/gatieme/article/details/50908749
(27)Linux编译时用到的参数含义?
https://blog.csdn.net/taoyanqi8932/article/details/51758722
(28)Linux内核配置编译以及Makefile?
https://www.cnblogs.com/CrazyCatJack/p/6121231.html
(29)谈谈对volatile关键字的理解?
https://blog.csdn.net/kai_zone/article/details/77965302
(30)Framebuffer的基本机制?
Linux系统抽象出Framebuffer设备来提供给用户态进程实现屏幕读写操作,Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象,可以通过Framebuffer的读写直接对显存进行操作,用户可以将Framebuffer看出是显示内存的一个映像,通过mmap将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上,这种操作是抽象,统一的,用户不必关心物理显存的位置、换页机制等具体细节,这些是由Framebuffer设备驱动程序来实现。
2、同步相关
(1)spinlock与信号量的区别?
https://blog.csdn.net/xiaohuima_dong/article/details/46423793
https://www.cnblogs.com/tureno/articles/6067441.html
(2)Linux系统中的同步机制?
https://blog.csdn.net/waltonhuang/article/details/52212762
https://blog.csdn.net/tong646591/article/details/8484596
(3)Linux系统中实现原子操作有哪些方法?
https://www.cnblogs.com/fanzhidongyzby/p/3654855.html
https://blog.csdn.net/vividonly/article/details/6599502
(4)自旋锁和信号量在互斥使用时需要注意什么问题?在中断服务程序里面的互斥是使用自旋锁还是信号量?还是两者都能用?为什么?
使用自旋锁的进程不能睡眠,使用执行时间短的任务,使用信号量的进程可以睡眠,适合于执行时间比较长的任务,中断服务程序里面使用的自旋锁,原因是在中断服务处理程序中,硬中断是关闭的,可能会丢失到来的中断。
(5)Linux驱动程序中为什么要有并发、互斥的控制?如何去实现?
并发(concurrency)指的是多个执行单元同时、并行被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量)的访问,则会很容易产生竞态(race conditions)。
解决竞态问题的途径是保证对共享资源的互斥访问,所谓的互斥访问,就是指一个执行单元在访问共享资源的时候,其它的执行单元都被禁止访问。
访问共享资源的代码区域被称为临界区,临界区需要以某种互斥机制加以保护,中断屏蔽、原子操作、自旋锁、信号量等都是Linux设备驱动程序中可以采用的互斥途径。
3、中断相关
本文转载于: