完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
问:为什么要将中断处理程序分解为顶半部和底半部呢?
答:有的时候,中断处理程序可能会做大量的工作,相对比较耗时,对于系统的并发能力和响应能力有很大的影响,所以进行拆分。 问:顶半部和底半部如何理解呢,分别做了哪些事情呢? 答:顶半部起始就是中断处理函数,做一些比较紧急的事情,并且这个过程是不可中断的,执行的速度要快。 底半部就是处理以前中断处理程序中比较耗时,比较繁琐的事情。底半部的执行顺序要晚于顶半部。这个过程是可中断的。 问:如何实现底半部呢? 答:tasklet,工作队列,软中断 tasklet和软中断都是工作在中断上下文中,不能休眠 工作队列工作在进程上下文,可以进行休眠操作 tasklet是基于软中断实现的。它有别于软中断! 面试:谈谈中断: 1.为什么有中断 2.中断的硬件处理过程 3.中断的软件的处理过程 4.linux内核中断的实现机制:中断处理函数有四个要求 5.顶半部和底半部 linux内核定时器: 1. 定时器硬件:周期性的自发的产生时钟中断 2.HZ 3.tick 4.时钟中断处理程序:5个事情 5.jiffies 6.struct timer_list: expires function data 7.init_timer/add_timer/mod_timer/del_timer linux的并发和竞态: 案例:如果要求设备只能被一个应用程序所打开访问,如何实现? 通过此案例引出并发和竞态问题: 相关概念: 1.并发 2.竞态 3.共享资源:硬件资源和软件上的全局变量 4.互斥访问 5.临界区 6.哪些情况会产生竞态 SMP(多CPU,共享总线,IO,主存,外存) 进程和进程(抢占) 中断和进程 中断和中断 切记:如果在写代码时,有以上的竞态发生,一定要注意进行互斥访问 7.解决竞态的方法: 中断屏蔽 原子操作 自旋锁 信号量 如何使用以上4个机制呢? 1.中断屏蔽 解决哪些情况的竞态: 进程和进程的抢占 中断和进程 中断和中断 local_irq_disable/local_irq_enable local_irq_save / local_irq_restore 以上函数用于在临界区之前屏蔽中断,执行完临界区再使能中断 例子: unsigned long flags; local_irq_save(flags); //关闭中断,并且将中断状态保存在flags中 临界区代码 local_irq_restore(flags); //打开中断,并且恢复中断状态 使用注意事项:中断对于内核的运行至关重要,长时间的屏蔽中断相当的危险,所以要求临界区的代码执行的速度要快,更不能有休眠的操作! 原子操作: 1.解决哪些情况的竞态? 所有的竞态都能解决 2.原子操作分为: 位原子操作:如果以后在驱动代码中,如果要对一个共享资源进行位操作,并且有竞态的情况,需要使用内核提供的位原子操作的相关方法,保证对这个共享资源的操作是原子的,避免竞态。 内核提供的位原子操作的方法: set_bit/clear_bit/change_bit/test_bit 案例:在驱动的入口函数将0x5555->0xaaaa,不允许使用change_bit #include 整型原子操作 使用场合:如果在驱动代码中,要使用一个整型变量的这么一个共享资源,这时候最好拷贝整型原子操作相关的内容,而不是标准的整型相关的数据类型的数据操作(int a; a+1, a++, a--,这些操作都不是原子的),如果使用整型原子变量对应的数据类型定义一个变量,并且使用内核提供的操作整型原子变量的方法就能保证对这个数的操作是原子的! 数据类型:atomic_t 如何使用呢? 分配整型原子变量:atomic_t v = ATOMIC_INIT(1); //初始化为1 还有一些相关的操作函数: atomic_set/atomic_read/atomic_add/atomic_sub/atomic_inc/atomic_dec/atomic_inc_test... 这些函数的内部实现利用了两条原子操作指令集:ldrex,strex,就保证了对数据访问是原子的。也就说明ldr,str不具有原子性!一般编译器对于a++,汇编以后都是用的ldr,str这两条指令,而不使用ldrex,strex,因为这两条指令会降低运行的效率! 案例:利用整型原子变量的操作实现按键驱动只能被一个应用程序所打开 www.arm8.net 嵌入式论坛 测试步骤: insmod btn_drv.ko ./btn_test & //后台运行 A进程 ./btn_test //B进程 ./btn_test //C进程 每个进程都会首先调用open->btn_open 自旋锁: 1.自旋锁对应的数据类型:spinlock_t 2.如何使用自旋锁: 2.1分配自旋锁 spinlock_t lock; 2.2初始化自旋锁 spin_lock_init(&lock); 2.3获取自旋锁: spin_lock(&lock); //如果没有获取自旋锁,执行单元将一直在这忙等待下去,直到持有自旋锁的执行单元释放锁为止 或者 spin_trylock(&lock); //如果获取自旋锁,返回true,没有获取锁,也会返回,返回false,所以对这个函数一定要对其返回值做判断,由返回值决定是否需要对临界区进行访问 2.4执行临界区的代码(操作共享资源) 2.5释放锁 spin_unlock(&lock); //这个函数一定要和获取锁的函数成对使用 3.自旋锁能够解决哪些场合的竞态问题: 除了中断都能解决,如果要涉及中断的竞态问题,需要使用衍生自旋锁 4.衍生自旋锁怎么使用呢? 获取锁: spin_lock_irq(&lock); //关闭中断和获取自旋锁 或者 unsigned long flags; spin_lock_irqsave(&lock, flags);.//关闭中断保存中断状态到flags中,然后获取自旋锁 www.arm8.net 嵌入式论坛 释放锁: spin_unlock_irq(&lock); 或者 spin_unlock_irqrestore(&lock, flags); 注意:衍生自旋锁能够解决所有的竞态问题! 注意:一般自旋锁要和共享资源要关联使用! 自旋锁使用的注意事项: 1.自旋锁所保护的临界区不要调用可能引起休眠的函数: copy_to_user,copy_from_user,kmalloc 如果调用,别的任务将会忙循环下去,降低系统的性能! 2.自旋锁保护的临界区执行速度尽量要快! 案例:利用自旋锁实现一个设备只能被一个应用程序所打开 测试步骤:同整型原子变量的实验步骤 www.arm8.net 嵌入式论坛 信号量: 1.信号量对应的数据结构:struct semaphore 2.信号量如何使用呢? 2.1 分配信号量 struct semaphore sema; 2.2 初始化为互斥信号量 sema_init(&sema, 1); 2.3 获取信号量: down(&sema); //如果进程获取不了信号量,进程就会进入不可中断的休眠状态(不会立即处理信号,比如kill信号,如果在僵死的状态下,给休眠的进程发信号,它不会立即处理信号,而是被唤醒以后,会判断之前有没有接受过信号,如果有接受过信号,那就处理信号),直到持有信号量的进程释放信号量,休眠的进程才会被唤醒然后获取信号量进行返回,不能用在中断上下文 或者 down_interruptible(&sema); //如果进程获取不了信号量,进程就会进入可中断的休眠状态(接收到信号,立即响应和处理信号),直到持有信号量的进程释放信号量,休眠的进程才会被唤醒然后获取信号量,还有一种唤醒情况就是接收到信号的唤醒,所以要对这个函数的返回值进行判断,如果返回0,表明正常获取信号量,如果返回非0,表明是接收到信号的返回,如果这种返回,不应该在处理临界区的代码。不能用在中断上下文 或者 down_trylock(&sema); //如果获取不了信号量,理解返回非0,获取信号量返回0,所以对其返回值一定也要做判断,决定是否需要执行临界区代码,可以用在中断上下文 2.4 执行临界区 2.5 释放信号量并且唤醒休眠的进程 up(&sema); 案例:利用信号量来实现一个设备只能被一个应用程序所打开操作 实验步骤: insmod btn_drv.ko ./btn_test & //启动A进程 ./btn_test & //启动B进程 top //查看两个进程的状态 kill A进程pid 或者 kill B进程pid 分别看打印的信息 |
|
相关推荐
2个回答
|
|
挺实用功能哇,谢谢lz分享
|
|
|
|
学习了 希望有更多好的东西可以分享出来
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
AI模型部署边缘设备的奇妙之旅:边缘端设备的局域网视频流传输方案
1614 浏览 0 评论
1476 浏览 0 评论
AI模型部署边缘设备的奇妙之旅:如何在边缘端部署OpenCV
6715 浏览 0 评论
tms320280021 adc采样波形,为什么adc采样频率上来波形就不好了?
1861 浏览 0 评论
3548 浏览 0 评论
78273 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 09:16 , Processed in 0.498444 second(s), Total 73, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号