linux的设备驱动程序是内核的关键领域,也是我们能够接触内核,丰富内核的手段。内核源代码中就有大量的设备驱动程序。linux与外设之间的沟通是层次化的,如果下图所描述(该图引自《深入linux内核架构》),对设备的访问,也是通过层次化的多个抽象进行。
linux以外设交互的方式一般通过I/O端口,I/O内存映射,以及轮询和中断。还可以通过总线控制设备。linux通过设备文件来访问扩展设备,这些设备文件与某个设备驱动程序建立起连接,以支持和扩展设备的通信。应用程序几乎感觉不到是跟设备在打交道,这是的用户或者开发者仿佛在跟普通的文件在交互一样,这也就是linux倡导的“万物皆文件-Everything is a file”。
linux将设备文件置于/dev 目录下,例如我们建立camera的设备文件/dev/camera,应用程序就通过这个设备文件和camera外设进行通信和交互了。linux设备不是通过文件名来标识的,而是通过文件的主、从设备好标识,这一点容易引起混淆。
根据外设与系统之间交换数据的方法,设备文件一般分为字符设备、块设备和其他设备(通过socket访问的网络设备)。举例android的audio设备文件,我们看一下它们都属于字符型设备(访问权限前面的字母是c,标识char 字符型设备,如果是b,就是block块设备了),主设备号相同,从设备号不同(mknod创建设备文件)。
crw-rw---- 1 system audio 116, 4 1971-01-09 05:01 comprC0D2
crw-rw---- 1 system audio 116, 0 1971-01-09 05:01 controlC0
crw-rw---- 1 system audio 116, 24 1971-01-09 05:01 pcmC0D0c
crw-rw---- 1 system audio 116, 16 1971-01-09 05:01 pcmC0D0p
crw-rw---- 1 system audio 116, 17 1971-01-09 05:01 pcmC0D1p
crw-rw---- 1 system audio 116, 27 1971-01-09 05:01 pcmC0D3c
crw-rw---- 1 system audio 116, 19 1971-01-09 05:01 pcmC0D3p
crw-rw---- 1 system audio 116, 20 1971-01-09 05:01 pcmC0D4p
crw-rw---- 1 system audio 116, 33 1971-01-09 05:01 timer
理论上音频驱动应该完全可以按照字符型驱动的模式去开发,然而实际上由于音频控制和码流混音等复杂场景,导致各个驱动厂商开发的音频驱动五花八门,兼容性和移植性都有很大的挑战,所以在类unix系统中存在着oss和alsa两个音频开发框架,linux目前主流的是alsa,至于他们之间的演变和特点,网上有很多介绍,以下摘抄一部分
最早出现在Linux上的音频编程接口是OSS(Open Sound System),它由一套完整的内核驱动程序模块组成,可以为绝大多数声卡提供统一的编程接口。OSS
出现的历史相对较长,这些内核模块中的一部分(OSS/Free)是与Linux内核源码共同免费发布的,另外一些则以二进制的形式由4Front Technologies公司提
供。由于得到了商业公司的鼎力支持,OSS已经成为在Linux下进行音频编程的事实标准,支持OSS的应用程序能够在绝大多数声卡上工作良好。虽然OSS已经
非常成熟,但它毕竟是一个没有完全开放源代码的商业产品,ALSA(Advanced Linux Sound Architecture)恰好弥补了这一空白,它是在Linux下进行音频编
程时另一个可供选择的声卡驱动程序。ALSA除了像OSS那样提供了一组内核驱动程序模块之外,还专门为简化应用程序的编写提供了相应的函数库,与OSS提
供的基于ioctl的原始编程接口相比,ALSA函数库使用起来要更加方便一些。
此外,在linux里所提到的数字音频设备,由于基于pc机系统发展过来的,往往称之为声卡,有时也称codec,PCM,DSP,ADC/DAC设备,用来播放或录制数字化的声音。它的指标主要有:采样速率(电话为8K,DVD为96K)、channel数目(单声道,立体声)、采样分辨率(8-bit,16-bit)等。mixer(混频器):用来控制多个输入、输出的音量,也控制输入(microphone,line-in,CD)之间的切换。synthesizer(合成器):通过一些预先定义好的波形来合成声音,有时用在游戏中声音效果的产生。MIDI接口:MIDI接口是为了连接舞台上的synthesizer、键盘、道具、灯光控制器的一种串行接口。所以音频编程接口可以理解为一组音频设备文件,通过它们可以从声卡读取数据,或者向声卡写入数据,并且能够对声卡进行控制,设置采样频率和声道数目等等。
最后要明确的是linux中字符设备驱动程序的主要功能是实现设备的读写和控制接口。对于字符设备驱动程序,最核心的就是file_operations结构,这个结构实际上是VFS(虚拟文件系统)的文件接口,它的每个成员函数一般都对应一个系统调用。用户进程利用系统调用对设备文件进行诸如读和写等操作时,系统调用通过设备文件的猪设备号找到对应的设备驱动程序,并且调用相应的驱动程序函数。所alsa架构也融合了fops的操作。
声明:本文摘抄《深入linux内核架构》和部分网络上的成熟段落,经过理解重新组织了内容。由于来源比较分散,不一一列出。