最近在做一个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底半部机制在视频采集驱动中的应用的更多相关文章

  1. Linux中断底半部机制

    参考: Linux下半部处理之软中断 linux中断底半部机制 <深入理解Linux内核>软中断/tasklet/工作队列 软中断和tasklet介绍 详解操作系统中断 Linux内核:中 ...

  2. linux 中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案【转】

    转自:http://blog.chinaunix.net/uid-20768928-id-5077401.html 在LINUX RS485的使用过程中,由于各种原因,最后不得不使用中断底半部机制的方 ...

  3. Linux内核中断顶半部和底半部的理解

    文章目录 中断上半部.下半部的概念 实现中断下半部的三种方法 软中断 软中断模版 tasklet tasklet函数模版 工作队列 工作队列函数模版 进程上下文和中断上下文 软中断和硬中断的区别 硬中 ...

  4. 嵌入式LINUX环境下视频采集知识

    V4L2是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中.V4L2不仅给驱动程序编写者带来极大的方便 ...

  5. Linux 驱动框架---驱动中的中断

    在单片机开发中中断就是执行过程中发生了一些事件需要及时处理,所以需要停止当前正在运行的处理的事情转而去执行中断服务函数,已完成必要的事件的处理.在Linux中断一样是如此使用但是基于常见的中断控制器的 ...

  6. V4L2视频采集原理

    一.简介 Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版.V4L2是linux操作系统下用于采集图片.视频和音频数据的API接口,配合适当的视频采集设备 ...

  7. 基于PCIe的多路视频采集与显示子系统

    基于PCIe的多路视频采集与显示子系统 1        概述 视频采集与显示子系统可以实时采集多路视频信号,并存储到视频采集队列中,借助高效的硬实时视频帧出入队列管理和PCIe C2H DMA引擎, ...

  8. Linux kernel workqueue机制分析

    Linux kernel workqueue机制分析 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.10.108的workqueue文档分析其基 ...

  9. Linux内核同步机制之completion【转】

    Linux内核同步机制之completion 内核编程中常见的一种模式是,在当前线程之外初始化某个活动,然后等待该活动的结束.这个活动可能是,创建一个新的内核线程或者新的用户空间进程.对一个已有进程的 ...

随机推荐

  1. LLinux系统编程(10)——进程间通信之管道

    管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别.有名管道叫named ...

  2. mvc和三层架构到底有什么区别

    原文地址:http://zhidao.baidu.com/question/82001542.html?qbl=relate_question_3&word=MVC%20%CA%FD%BE%D ...

  3. JavaScript中setTimeout()和setInterval()的区别

    含义: setTimeout()和setInterval()经常被用来处理延时和定时任务.使用setTimeout()处理延时任务,而使用setInterval()方法处理定时任务: setTimeo ...

  4. HDU 3308 LCIS(线段树单点更新区间合并)

    LCIS Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting ...

  5. postgresql基本语句

    preface,熟悉pgsql sql Language article disorder; 1,pgsql数据库控制台Cli(command line interface) help mannual ...

  6. mongoDB global,startUplog

    1,show logs (Ruiy看到一些人干些事就跟拉shit一样(磨叽),就来气,娃儿的,还不知所谓,抱怨,叫器一大堆!!!,喝喝,就这它还三心二意学一个故事中的主人公小小明上课偷打`皮卡`玩,三 ...

  7. poj 2356 Find a multiple(鸽巢原理)

    Description The input contains N natural (i.e. positive integer) numbers ( N <= ). Each of that n ...

  8. 水务新、老营收系统大PK

    今天想撩一下咱水务界的大拿——营业收费管理系统. 营业收费 随着城市供水规模的不断扩大及户表改造的深入以及阶梯水价的实行还有移动平台等第三方支付的蓬勃发展,原有的营收软件系统已经不能适应目前水司的管理 ...

  9. Java正則表達式

    近期工作中常常要用到正則表達式,不得不花点时间对其进行一定的学习.   JDK中提供了2个类来支持正則表達式,各自是java.util.regex.Pattern和java.util.regex.Ma ...

  10. vi/vim经常使用命令

    工作模式 插入命令 a 在光标后附加文本 A 在本行行尾附加文本 i 在光标前插入 I 在本行行首插入文本 o 在光标以下插入新的一行 O 在光标上面插入新的一行 定位命令 h 左移一个字符/ 向左的 ...