視訊監控—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的簡單介紹
- 二、架構分析
-
- 1、sound.c檔案分析
-
- 1.1 `snd_open()`函數,關鍵`snd_minor`數組
- 1.2 `snd_minor`數組來源:`snd_register_device_for_dev()`聲霸卡裝置注冊函數
- 1.3 誰來調用`snd_register_device_for_dev()`,建立聲霸卡裝置結點
- 1.4 小結
- 2、control.c檔案分析
-
- 2.1 `snd_ctl_dev_register()`的調用來源
- 2.2 誰來調用`snd_ctl_create()`函數
- 2.3 小結
- 3、pcm.c檔案分析
-
- 3.1 `snd_pcm_dev_register()`函數
- 3.2 `snd_pcm_dev_register()`的調用來源
- 3.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
數組
snd_open()
snd_minor
這個檔案的
file_operation
結構體對應的
.open
函數,其要做一些初始化工作,找到對應的裝置fops結構體:
- 得到某個裝置的次裝置号
- 根據次裝置号在
數組中找到對應snd_minor
結構體snd_minor
- 擷取到對應的
結構體fops
1.2 snd_minor
數組來源: snd_register_device_for_dev()
聲霸卡裝置注冊函數
snd_minor
snd_register_device_for_dev()
那麼
snd_minor
數組來自于哪裡呢?
通過在
sound.c
檔案中搜尋
snd_minor
數組,找到在
snd_register_device_for_dev()
函數構造:
- 根據傳進來的參數設定
,即preg
結構體snd_minor
- 把設定好的
放入preg
數組中snd_minors
- 建立裝置
1.3 誰來調用 snd_register_device_for_dev()
,建立聲霸卡裝置結點
snd_register_device_for_dev()
那麼誰來調用
snd_register_device_for_dev()
來建立聲霸卡裝置呢?
通過在核心中搜尋,得到以下結果:
分為兩個分支進行:
- control.c檔案的
函數(snd_ctl_dev_register()
在core.h中定義的snd_register_device_for_dev()
函數中被調用,snd_register_device()
最終在control.c檔案的snd_register_device()
函數調用)snd_ctl_dev_register()
- pcm.c檔案的
函數snd_pcm_dev_register()
1.4 小結
在sound.c檔案中,主要做了一下事情:
- 調用
,根據傳入的參數構造了snd_register_device_for_dev()
數組,并把傳入的snd_minor
結構體放入到數組中;fops
- 在sound.c檔案的
結構體的fops
函數,擷取到裝置的.open
結構體fops
2、control.c檔案分析
2.1 snd_ctl_dev_register()
的調用來源
snd_ctl_dev_register()
通過在control.c檔案中的追蹤可以知道:
- 在
函數中,建構了snd_ctl_create()
結構體,在結構體内部把snd_device_ops
聯系起來;snd_ctl_dev_register()
- 在
函數中,把control.c檔案中建構的snd_ctl_dev_register()
結構體傳入到file_operations
函數中,同時制定了這個控制接口的名字snd_register_device()
sprintf(name, "controlC%i", cardnum);
- 在
函數中,最終通過snd_register_device()
函數把snd_register_device_for_dev()
結構體放入到file_operations
數組snd_minor
- 通過名字可以知道,control.c檔案中建構的
結構體,即file_operations
,是與聲霸卡控制接口相關的結構體。snd_ctl_f_ops
2.2 誰來調用 snd_ctl_create()
函數
snd_ctl_create()
通過核心的檢索在發現:
- 在
檔案中的init.c
中調用了snd_card_create()
snd_ctl_create()
2.3 小結
通過分析可以知道,這個分支的主要作用:
- 建立聲霸卡的控制接口
- 調用
,把與控制接口相關的fops結構體放入到snd_register_device_for_dev()
數組中.snd_minior
- 聲霸卡控制接口的名字為
controlC%i
3、pcm.c檔案分析
3.1 snd_pcm_dev_register()
函數
snd_pcm_dev_register()
在這個函數中,主要完成如下事:
- 根據傳入的裝置類型(錄音/播放),注冊對應的聲霸卡裝置
- 制定聲霸卡裝置的名字
- 根據上述資訊,注冊聲霸卡裝置節點
3.2 snd_pcm_dev_register()
的調用來源
snd_pcm_dev_register()
通過在pcm.c檔案中尋找可以知道如下調用順序:
- 與上述control.c分析和相似的,在
函數中建構了_snd_pcm_new()
結構體,在結構體内部把snd_device_ops
聯系起來;snd_pcm_dev_register()
3.3 小結
通過分析可以知道,這個分支的主要作用:
- 建立聲霸卡的裝置接點,對于聲霸卡的錄音與播放,可以建立兩個不同的裝置節點;
- 最終調用
,把與裝置相關的fops結構體放入到snd_register_device_for_dev()
數組中.snd_minior
- 聲霸卡裝置接口的名字為
(播放)與pcmC%iD%ip
"pcmC%iD%ic"
(錄音)(其中, C0D0代表的是聲霸卡0中的裝置0, pcmC0D0c最後一個c代表capture, pcmC0D0p最後一個p代表
playback)
三、整體總結
通過上述的分析,得到了如下的架構圖:
- 主要分為兩個分支:注冊聲霸卡控制節點與聲霸卡裝置節點
-
在注冊聲霸卡控制節點分支中:
2.1 配置設定了記憶體,用來設定控制節點的結構體
2.2 制定了節點的名字
2.3 構造了控制接口相關的fops結構體
2.4 最終調用
,把與控制接口相關的fops結構體放入到snd_register_device_for_dev()
數組中snd_minior
-
在注冊聲霸卡裝置節點分支中:
3.1 配置設定了記憶體,用來設定聲霸卡裝置節點的結構體
3.2 制定了聲霸卡裝置節點的名字
3.3 構造了聲霸卡裝置節點相關的fops結構體
3.4 最終調用
,把與聲霸卡裝置節點相關的fops結構體放入到snd_register_device_for_dev()
數組中snd_minior
-
在sound.c中,當使用者打開聲霸卡裝置時
4.1 得到某個裝置的次裝置号
4.2 通過上述步驟得到的
數組中,根據次裝置好找到對應的snd_minior
snd_minor
結構體
4.3 進而在
結構體中獲得對應的fops結構體snd_minor