linux底半部机制在视频采集驱动中的应用
最近在做一个arm+linux平台的视频驱动。本来这个驱动应该是做板子的第三方提供的,结果对方软件实力很差,自己做不了这个东西,外包给了一个暑期兼职的在读博士。学生嘛,只做过实验,没做过产品,给出的东西自然和产品的实际需要相去十万八千里。博士同学给我们的驱动甚至是从未编译过的,充满了"unsigned void "这样可笑的语法错误,不得已跑到北平追着那厮现场联调,最后所谓的“调通”,也仅仅是寄存器配置正确而已。
视频驱动的输出是连续的帧数据,必须要有完善的缓冲、跳帧和同步阻塞机制。而这些机制在博士同学给我的驱动程序中全部付之阙如。在这份驱动程序中,是没有阻塞机制的,在采集一帧图像期间连续两次调用采集API,得到的会是同一帧图像的buffer。如果你写一个线程循环采集,那么这个线程必定会耗尽CPU所有空闲的资源。诸如此类的问题还有一大堆,这样的驱动肯定是没法用到实际产品中的。
不得已只好自己操刀上阵改写这个驱动。我的思路是这样的:
驱动程序流程
1、在驱动中创建两个内核链表,一个用来缓冲新采集到的图像buffer,而另一个用来缓冲废弃的图像buffer。
2、从预先分配的buffer中取出三个buffer,第一个作为前帧buffer,第二个作为当前buffer设置为dma目的地址,第三个作为后备buffer。
3、当新图像到来时,将dma目的地址更新为后备buffer,然后将前帧buffer链入新图像链表尾端。
4、将当前buffer的值赋给前帧buffer,将后备buffer的值赋给当前buffer,再判断废弃图像链表中是否有buffer存在。
5、如果废弃链表不为空,则从废弃图像链表取出一个buffer赋给后备buffer;如果废弃图像链表中没有buffer可用,则从新图像链表中获取一个buffer赋给后备buffer,也就是发生了跳帧。
备注:链表中buffer的进出使用信号量进行增减计数
客户程序流程
1、判断新图像链表是否为空。
2、不为空则从新图像链表获取一个buffer,即采集到一帧图像;为空则由于计数信号量为0,导致线程挂起等到新buffer链入链表。
3、使用采集到的图像。
4、将使用过的图像buffer送入废弃链表。
由于使用信号量对链表进行了计数,当链表为空时,从链表获取buffer的线程可以挂起,也就达到了阻塞同步的目的。新图像被链表串联在一起,达到了缓冲的目的。当废弃链表中的buffer耗尽时,从新图像链表获取buffer进行采集,达到了跳帧的目的。这样的流程设计似乎是没有问题,但是实现起来就遇到了些麻烦。这个机制中,链表的更新是在中断和线程并发执行的,有很大的几率发生访问冲突,这就要求引入互斥机制。然而中断是不可阻塞或挂起的,互斥量不能在中断中使用。基于循环等待的自旋锁,在这种场合又会引起死锁(当用户线程获得自旋锁之后,如果有中断发生,线程会被中断抢占;此时中断试图获取自旋锁,必然由于获取不到而循环等待;此时线程被中断抢占,无法释放手中的自旋锁,就会造成死锁)。这就要求引入一种机制,既要能够被阻塞,又要能在中断isr返回之后立即执行。将链表的更新操作全部安排到这种机制中,就能够实现与用户线程的互斥。
linux提供了一种称为“底半部(bottom half)”的机制。ISR是软件代码,由硬件设备触发。底半部机制类似中断,却是由软件代码触发的。常用的底半部机制有软中断、基于软中断的tasklet(小任务)和基于内核线程的工作队列等。软中断类似于中断,也是不可阻塞的,显然软中断和基于软中断的tasklet等机制无法满足我的需求。而工作队列是可以阻塞的,又可以在中断中触发执行,看起来这是一个不错的选择。
于是我将原先规划给中断的链表操作全部移到了工作队列绑定的函数中,每次中断触发时,isr将后备buffer的值置为dma目的地址,然后触发工作队列。工作队列绑定的函数根据链表当前的情况更新当前buffer和后备buffer的地址,供isr下一次执行时使用。当然这个过程是加了互斥机制的,在用户线程调用的驱动api中也加了同样的互斥机制,这样二者就不会发生冲突。
在我看来,所谓“底半部”机制这种说法很有故弄玄虚的味道。在任何处理器或操作系统中,中断都是一种不可阻塞且必须快速返回的机制,遇到长时间的运算或必须阻塞的情形,都会采用由中断触发某种线程或任务的方法。例如在DSP/BIOS或ucOS-II中,一般会为类似的工作预留一个高优先级的线程,平时被信号或邮箱阻塞,在中断isr中发送信号或消息来触发这个线程。虽然采用了类似的处理方法,但是并没有什么“底半部”之类的术语。可能是linux内核太过庞杂了吧,还严格区分了内核态和用户态,不能像准操作系统内核那样使用普通线程实现这种机制,而内核线程等机制调用又太过复杂,必须进行专门的封装才能得到易于使用的API。按照我的理解,所谓的“底半部”,其实就是这种“封装”而已。
linux底半部机制在视频采集驱动中的应用的更多相关文章
- Linux中断底半部机制
参考: Linux下半部处理之软中断 linux中断底半部机制 <深入理解Linux内核>软中断/tasklet/工作队列 软中断和tasklet介绍 详解操作系统中断 Linux内核:中 ...
- linux 中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案【转】
转自:http://blog.chinaunix.net/uid-20768928-id-5077401.html 在LINUX RS485的使用过程中,由于各种原因,最后不得不使用中断底半部机制的方 ...
- Linux内核中断顶半部和底半部的理解
文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...
- 嵌入式LINUX环境下视频采集知识
V4L2是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中.V4L2不仅给驱动程序编写者带来极大的方便 ...
- Linux 驱动框架---驱动中的中断
在单片机开发中中断就是执行过程中发生了一些事件需要及时处理,所以需要停止当前正在运行的处理的事情转而去执行中断服务函数,已完成必要的事件的处理.在Linux中断一样是如此使用但是基于常见的中断控制器的 ...
- V4L2视频采集原理
一.简介 Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版.V4L2是linux操作系统下用于采集图片.视频和音频数据的API接口,配合适当的视频采集设备 ...
- 基于PCIe的多路视频采集与显示子系统
基于PCIe的多路视频采集与显示子系统 1 概述 视频采集与显示子系统可以实时采集多路视频信号,并存储到视频采集队列中,借助高效的硬实时视频帧出入队列管理和PCIe C2H DMA引擎, ...
- Linux kernel workqueue机制分析
Linux kernel workqueue机制分析 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.10.108的workqueue文档分析其基 ...
- Linux内核同步机制之completion【转】
Linux内核同步机制之completion 内核编程中常见的一种模式是,在当前线程之外初始化某个活动,然后等待该活动的结束.这个活动可能是,创建一个新的内核线程或者新的用户空间进程.对一个已有进程的 ...
随机推荐
- PKU 1050-To The Max(找矩形内元素最大和)
Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous s ...
- [Ruby学习总结]Ruby中的类
1.类名的定义以大写字母开头,单词首字母大写,不用"_"分隔 2.实例化对象的时候调用new方法,实际上调用的是类里边的initialize方法,是ruby类的初始化方法,功能等同 ...
- IP、路由配置
IP地址组成: 网络地址主机地址32位二进制 A类: 255.0.0.0, 8: 0 000 0001 - 0 111 1111 127个A类,127用于回环,1-126 2^7- ...
- 点击链接直接跳转到 App Store 指定应用下载页面
//跳转到应用页面 NSString *str = [NSString stringWithFormat:@"http://itunes.apple.com/us/app/id%d" ...
- 序列变换(Lis变形)
序列变换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 随机函数(Pascal入门)
随机函数是最主要的,在比赛的时候我们能够用随机函数来測试自己的程序是否会超时. 随机函数也能够做出一些大数据.用于两个程序之间对拍(一个是爆搜.一个是正解). 当然平时我们也能够用随机函数測自己的程序 ...
- Windows Mobile 6 sdk installation error, COM3 in use,please check the implementation
问题:Windows Mobile 6 sdk installation error, COM3 in use,please check the implementation 1. Windows-& ...
- 【分割平面,分割空间类题】【HDU1290 HDU2050】
HDU 2050 折线分割平面 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 【二分答案】【POJ3122】【Northwestern Europe 2006】Pie
Pie Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10629 Accepted: 3744 Special Ju ...
- sql必知必会(第四版) 学习笔记二 视图
本书用到的几个表的建表sql语句如下: --销售产品供应商 CREATE TABLE Vendors ( vend_id varchar(20) not null, vend_name varchar ...