嵌入式面经篇十——驱动开发

文章目录


前言

记录一些招聘公司在招聘嵌入式软件岗位时的一些问题,此文为第十篇。


一、驱动开发

1、Linux 驱动程序的功能是什么?

  • 对设备初始化和释放。
  • 进行内核与硬件的数据交互。
  • 检测和处理设备出现的错误。

2、内核程序中申请内存使用什么函数?

答:kmalloc()、kzalloc()、vmalloc()。

解读:

  • void *kmalloc(size_t size, gfp_t flags);
    • 申请连续的物理内存,这对于要进行 DMA 的设备十分重要,但大小不能超过 128KB,其中有 16B 是被页描述符占用了。
    • 较常用的 flag 有GFP_ATOMIC(分配内存的过程是一个原子过程)、GFP_KERNEL(正常分配内存)、GFP_DMA(给DMA控制器分配内存)。
    • 对应的内存释放函数为 void kfree(const void *objp)
  • void *kzalloc(size_t size, gfp_t flags);
    • kzalloc() 相对 kmalloc() 只是额外增加了 __GFP_ZERO 标志,除了申请内存外,还会对申请到的内存内容清零。
    • 对应的释放函数也是 kfree()
  • void *vmalloc(unsigned long size);
    • 申请虚拟地址连续的内存空间,但其对应的物理内存不一定连续,因此对申请的内存大小没有限制。
    • 对应的内存释放函数为 void vfree(const void *addr)
    • 注意:vmalloc()vfree() 可以睡眠,因此不能在中断上下文调用。

3、内核程序中申请内存和应用程序时申请内存有什么区别?

答:内核中申请内存空间用的是函数 kmalloc、kzalloc、vmalloc,应用程序申请内存用的函数是malloc。

解读:

  • kmalloc/kzalloc 直接分配连续的物理地址(虚拟地址也是连续的)。
  • vmalloc 分配连续的虚拟地址,但物理地址不一定连续。分配时实际分配了物理内存,不过这个物理内存页面是在公共的页表进行了映射,并没有在本进程的页表进行映射,当访问这段内存时,触发 do_page_fault 异常(缺页中断)才完成页表的同步工作。
  • malloc 是用户空间申请内存的方法,分配连续的虚拟地址,物理地址一般不会连续。在分配时并没有做实际物理页的分配动作,实际分配物理页的动作是在 do_page_fault 异常(缺页中断)处理中完成的。

4、自旋锁和信号量在互斥使用时需要注意什么?在中断服务程序里面的互斥是使用自旋锁还是信号量?

  • 使用自旋锁的进程不会睡眠, 而使用信号量的进程会睡眠。
  • 中断服务程序使用的是自旋锁,原因是中断服务程序处于中断上下文,中断上下文是不参与调度的,也就没有保护现场与恢复现场,一旦睡眠就回不来了。

5、驱动卸载异常可能是由什么原因引起的?

可能是因为有进程在使用该模块。

6、Linux 中引入模块机制有什么好处?

  • 应用程序在退出时,可以不管资源的释放或者其他的清除工作,而把这些任务交给模块退出函数(exit)。
  • 模块机制有助于缩短模块的开发周期,因为模块的安装和卸载都很方便。

7、Linux 设备驱动程序中,使用哪两个函数进行中断处理程序的注册和注销?

  • 注册中断:

    c 复制代码
    int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flag, const char *dev_name, void *dev_id); 

    参数的意义依次是中断号,中断处理函数,中断管理有关掩码,中断请求设备名,中断信号线。

  • 注销中断:

    c 复制代码
    void free_irq(unsigned int irq, void *dev_id);

    参数的意义分别是中断号和中断信号线。

8、写一个中断服务程序需要注意哪些地方?

  • 中断服务程序应该尽可能短,把能放在底半部(tasklet、workqueue)的任务尽量放在底半部。
  • 中断服务程序中不能有阻塞操作,因为中断期间是完全占用 CPU 的,不存在内核调度,中断被阻塞住,其他进程将无法推进。
  • 中断服务程序的返回值要用操系统定义的宏,而不能用自己定义的。
  • 中断服务程序不能有不可重入的操作,如浮点数计算、printf() 等。

9、Linux 系统打开设备文件,进程可能处于三种基本状态,如果多次打开设备文件,驱动程序应该实现什么?

互斥。

10、简述 static 对于工程模块化的作用。

static 可以让全局变量或函数的作用域限制在当前模块,不会与其他模块发生冲突。因为在嵌入式系统中,一个程序可能是很多程序员共同完成的,在定义变量及函数的过程中,可能会重命名,给系统集成带来麻烦。

11、并发是什么?驱动里面为什么要有互斥控制?如何实现?

  • 并发是指多个执行单元同时、并行地被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量)的访问很容易导致竞态。
  • 解决竞态问题的途径是保证对共享资源的互斥访问。
  • 访问共享资源的代码区域被称为临界区,临界区需要用某种互斥机制加以保护,中断屏蔽、原子操作、信号量、自旋锁都是 Linux 设备驱动中可以采取的互斥机制。

12、Linux 内核有哪些同步方式?

原子操作、信号量、自旋锁、读写锁、顺序锁等。

13、在一个多任务嵌入式系统中,有一个 CPU 可直接寻址的 32 位寄存器 REGn,地址为 0x1F000010,编写一个安全的函数将寄存器 REGn 的指定位反转?

答:

c 复制代码
void bit_reverse(uint32_t nbit)  
{  
    *((volatile unsigned int *)0x1F000010) ^= (0x01 << nbit);  
}  

注意:

  • 指定位反转用异或 ^。
  • 由于是寄存器地址,因此强制类型转换的时候要加上 volatile。

我的qq:2442391036,欢迎交流!


相关推荐
gopher951117 小时前
linux驱动开发-设备树
linux·驱动开发
三菱-Liu1 天前
三菱变频器以模拟量电流进行频率设定(电流输入)
驱动开发·单片机·嵌入式硬件·硬件工程·制造
三菱-Liu2 天前
三菱FX5U CPU 内置以太网功能
网络·驱动开发·硬件工程·制造·mr
让开,我要吃人了2 天前
OpenHarmony鸿蒙( Beta5.0)摄像头实践开发详解
驱动开发·华为·移动开发·harmonyos·鸿蒙·鸿蒙系统·openharmony
OH五星上将3 天前
如何更换OpenHarmony SDK API 10
驱动开发·嵌入式硬件·sdk·harmonyos·openharmony·鸿蒙开发
OH五星上将4 天前
OpenHarmony(鸿蒙南向开发)——标准系统移植指南(二)Linux内核
linux·驱动开发·嵌入式硬件·移动开发·harmonyos·鸿蒙开发·鸿蒙内核
芊言芊语4 天前
蓝牙驱动开发详解
驱动开发
让开,我要吃人了5 天前
OpenHarmony鸿蒙( Beta5.0)RTSPServer实现播放视频详解
驱动开发·嵌入式硬件·华为·移动开发·harmonyos·鸿蒙·openharmony
OH五星上将5 天前
OpenHarmony(鸿蒙南向开发)——轻量和小型系统三方库移植指南(二)
驱动开发·移动开发·harmonyos·内存管理·openharmony·鸿蒙内核·鸿蒙移植
CS_素锦少年5 天前
Linux_kernel驱动开发11
linux·运维·驱动开发