第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

视频监控—ALSA驱动框架的简单分析

  • 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
  • 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
  • 开发环境:arm-linux-gcc-4.3.2工具链、linux-3.4.2内核(开发版根文件系统)
  • 源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3


一、ALSA的简单介绍

ALSA是在Linux内核中的高级Linux声音体系结构为Linux操作系统提供音频和MIDI功能。其具有以下重要功能

  • 对所有类型的音频接口的有效支持,从消费类声卡到专业的多通道音频接口
  • 完全模块化声音驱动程序
  • SMP和线程安全设计
  • 用户空间库(alsa-lib)可以简化应用程序编程并提供更高级别的功能。
  • 支持较早的Open Sound System(OSS)API,为大多数OSS程序提供二进制兼容性

Linux中ALSA的主要文件

  • include/sound/driver.h
  • sound/core/*.c

二、框架分析

框架分析针对的是对声卡的控制接口与设备接口的结构,会忽略一些其他的东西。


1、sound.c文件分析

通过入口函数alsa_sound_init(),来进行分析,得到如下图:

1.1 snd_open()函数,关键snd_minor数组

这个文件file_operation结构体对应的.open函数,其要做一些初始化工作找到对应的设备fops结构体

  1. 得到某个设备的次设备号
  2. 根据次设备号在snd_minor数组中找到对应snd_minor结构体
  3. 获取到对应的fops结构体
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

1.2 snd_minor数组来源:snd_register_device_for_dev()声卡设备注册函数

那么snd_minor数组来自于哪里呢?

通过在sound.c文件中搜索snd_minor数组,找到在snd_register_device_for_dev()函数构造:

  1. 根据传进来的参数设置preg,即snd_minor结构体
  2. 设置好的preg放入snd_minors数组中
  3. 创建设备
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

1.3 谁来调用snd_register_device_for_dev(),创建声卡设备结点

那么谁来调用snd_register_device_for_dev()来创建声卡设备呢?
通过在内核中搜索,得到以下结果:

分为两个分支进行:

  • control.c文件的snd_ctl_dev_register()函数snd_register_device_for_dev()在core.h中定义snd_register_device()函数中被调用snd_register_device()最终在control.c文件的snd_ctl_dev_register()函数调用
  • pcm.c文件的snd_pcm_dev_register()函数
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

1.4 小结

在sound.c文件中,主要做了一下事情:

  1. 调用snd_register_device_for_dev(),根据传入的参数构造了snd_minor数组,并把传入的fops结构体放入到数组中
  2. sound.c文件的fops结构体的.open函数获取到设备的fops结构体

2、control.c文件分析

2.1 snd_ctl_dev_register()的调用来源

通过在control.c文件中的追踪可以知道:

  1. snd_ctl_create()函数中,构建了snd_device_ops结构体,在结构体内部把snd_ctl_dev_register()联系起来
  2. snd_ctl_dev_register()函数中,把control.c文件中构建的file_operations结构体传入到snd_register_device()函数中,同时制定了这个控制接口的名字sprintf(name, "controlC%i", cardnum);
  3. snd_register_device()函数中,最终通过snd_register_device_for_dev()函数把file_operations结构体放入到snd_minor数组
  4. 通过名字可以知道,control.c文件中构建的file_operations结构体,即snd_ctl_f_ops,是与声卡控制接口相关的结构体
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

2.2 谁来调用snd_ctl_create()函数

通过内核的检索在发现:

  1. init.c文件中的snd_card_create()中调用了snd_ctl_create()
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

2.3 小结

通过分析可以知道,这个分支的主要作用

  1. 创建声卡的控制接口
  2. 调用snd_register_device_for_dev(),把与控制接口相关的fops结构体放入到snd_minior数组中.
  3. 声卡控制接口的名字为controlC%i

3、pcm.c文件分析

3.1 snd_pcm_dev_register()函数

在这个函数中,主要完成如下事:

  1. 根据传入的设备类型(录音/播放),注册对应的声卡设备
  2. 制定声卡设备的名字
  3. 根据上述信息,注册声卡设备节点
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

3.2 snd_pcm_dev_register()的调用来源

通过在pcm.c文件中寻找可以知道如下调用顺序:

  1. 与上述control.c分析和相似的,在_snd_pcm_new()函数中构建了snd_device_ops结构体,在结构体内部把snd_pcm_dev_register()联系起来
    第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析

3.3 小结

通过分析可以知道,这个分支的主要作用

  1. 创建声卡的设备接点,对于声卡的录音与播放,可以创建两个不同的设备节点
  2. 最终调用snd_register_device_for_dev(),把与设备相关的fops结构体放入到snd_minior数组中.
  3. 声卡设备接口的名字为pcmC%iD%ip(播放)与"pcmC%iD%ic"(录音)(其中, C0D0代表的是声卡0中的设备0, pcmC0D0c最后一个c代表capture, pcmC0D0p最后一个p代表
    playback)

三、整体总结

通过上述的分析,得到了如下的框架图:

  1. 主要分为两个分支:注册声卡控制节点与声卡设备节点

  2. 注册声卡控制节点分支中
    2.1 分配了内存,用来设置控制节点的结构体
    2.2 制定了节点的名字
    2.3 构造了控制接口相关的fops结构体
    2.4 最终调用snd_register_device_for_dev(),把与控制接口相关的fops结构体放入到snd_minior数组中

  3. 注册声卡设备节点分支中
    3.1 分配了内存,用来设置声卡设备节点的结构体
    3.2 制定了声卡设备节点的名字
    3.3 构造了声卡设备节点相关的fops结构体
    3.4 最终调用snd_register_device_for_dev(),把与声卡设备节点相关的fops结构体放入到snd_minior数组中

  4. 在sound.c中,当用户打开声卡设备时
    4.1 得到某个设备的次设备号
    4.2 通过上述步骤得到的snd_minior数组中根据次设备好找到对应的snd_minor结构体
    4.3 进而snd_minor结构体中获得对应的fops结构体

第三阶段应用层——2.10 视频监控—ALSA驱动层框架的简单分析