嵌入式常见面试题总结(6)_低开销加锁,优先使用自旋锁

答:底层的程序包括,内核,bootloader和驱动。基本开发Android硬件产品公司主要需要这一类人。而不同产品中,内核和bootloader变化较小,主要的工作量是在驱动之上。驱动相当于 单片机程序+linux内核接口。

但是从单片机转型为Linux驱动开发的,几个主要问题的,是代码量急剧增加,在单片机中有一些习惯在驱动开发里变成致命的陷阱。比如不喜欢用宏,在驱动大量用到内核复杂结构而单片机往往自写,还有一个并发处理,也是一个难点。

相同点:
单片机开发和LINUX的驱动开发都有对硬件的操作,最底层对硬件的寄存器操作,对时序的理解是一致的。
不同点:
1.单片机是对外设的IO实地址进行直接操作,而LINUX里面,由于使能了MMU,所以对外设IO地址的操作必须先通过ioremap()或者通过静态映射,把外设IO地址映射到内核的虚拟地址空间后才能正确操作。
2.在单片机编写对应设备的驱动不用考虑系统太多的系统分层问题,重用其他的代码量比较小,而LINUX采用分层抽象的思想,在LINUX中编写设备驱动,要按照LINUX已经搭建好的层次结构进行驱动编写,经常调用LINUX提供的函数和机制,代码重用性大。
3.由于LINUX是一个多任务的系统,即使在单核CPU上也存在资源竞争的情况(思考一下,LINUX里面那些地方可能导致资源竞争),所以在对驱动的编写的时候,对竞争资源需要采用一定的资源保护机制,比如原子变量,自旋锁等
4.单片机中断处理时,一般直接在产生中断的进入到中断处理函数里面在关中断的情况下处理完中断就可以。而LINUX里面把中断分为2部分,上半部分和下班部分,在上半部分中,是在关中断情况下,只做最基本和最核心的部分,然后在下半部分在开中断情况下,通过LINUX提供的各种机制来处理(思考: LINUX中断的底半部分有哪些模式)。

53.请从网卡、USB HOST、LCD驱动器、NAND FLASH、WIFI 、音频芯片中选择一个或者2个(可以以具体的芯片为例),对下面的问题做答: 
1)如果是外部扩展芯片,请说出你用的芯片的型号 
2)画出上题中你选定相应硬件模块与CPU的主要引脚连线

  1. 编写上题中你选定相应硬件模块相应LINUX驱动的流程?

54**,linux驱动分类?**

答:Linux设备驱动的分类
  (1)字符设备。
  (2) 块设备。
  (3) 网络设备。
  字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。块设备可以用任意顺序进行访问,以块为单位进行操作,如硬盘、软驱等。字符设备不经过系统的快速缓冲,而块设备经过系统的快速缓冲。但是,字符设备和块设备并没有明显的界限,如对于Flash设备,符合块设备的特点,但是我们仍然可以把它作为一个字符设备来访问。网络设备在Linux里做专门的处理。Linux的网络系统主要是基于BSD unix的socket 机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递。系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。
55**,信号量与自旋锁?**

答:自旋锁是专为防止多处理器并发而引入的一种锁,它应用于中断处理等部分。对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁。自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。事实上,自旋锁的初衷就是:在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。但是自旋锁节省了上下文切换的开销。
自旋锁的基本形式如下:
  spin_lock(&mr_lock);
  //临界区
  spin_unlock(&mr_lock);
因为自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务。在单处理器上,自旋锁仅仅当作一个设置内核抢占的开关。如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核。简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用。

死锁:假设有一个或多个内核任务和一个或多个资源,每个内核都在等待其中的一个资源,但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待,但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源,无法继续运行,这便意味着死锁发生了。自死琐是说自己占有了某个资源,然后自己又申请自己已占有的资源,显然不可能再获得该资源,因此就自缚手脚了。递归使用一个自旋锁就会出现这种情况。

信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
  信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。
信号量基本使用形式为:
  static DECLARE_MUTEX(mr_sem);//声明互斥信号量
  if(down_interruptible(&mr_sem))
           //可被中断的睡眠,当信号来到,睡眠的任务被唤醒
           //临界区
       up(&mr_sem);
信号量和自旋锁区别
  从严格意义上讲,信号量和自旋锁属于不同层次的互斥手段,前者的实现有赖于后者。
注意以下原则:
   如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。
自旋锁对信号量
需求              建议的加锁方法
低开销加锁           优先使用自旋锁
短期锁定            优先使用自旋锁
长期加锁            优先使用信号量
中断上下文中加锁        使用自旋锁
持有锁是需要睡眠、调度     使用信号量 
 
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

img

img

img

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

img

img

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

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

%;" />

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

更多资料点击此处获qu!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值