您的位置 首页 系统

你知道Linux audio(OSS)子系统是怎样?

你知道Linux audio(OSS)子系统是怎样?-在linux声卡的驱动中存在两种架构,一种是OSS(开放声音系统),一种是ALSA(先进Linux声音架构)。OSS是一个商业声卡驱动程序,需要花钱购买。一般我们现在使用的是ALSA的声音架构。OOS(Open Sound System),在这里主要介绍两个设备,DSP与MIXER.DSP: 用来采样和播放的文件,对该设备写操作就是播放,对该设备读就是录音操作。

  简介

  在linux声卡的驱动中存在两种架构,一种是OSS(敞开声响体系),一种是ALSA(先进Linux声响架构)。OSS是一个商业声卡驱动程序,需求花钱购买。一般咱们现在运用的是ALSA的声响架构。OOS(Open Sound System),在这儿首要介绍两个设备,DSPMIXER.DSP: 用来采样和播映的文件,对该设备写操作便是播映,对该设备读便是录音操作。

  这个设备能够有多个。对该设备操作时应留意一次写入数据块的巨细,假如数据块过大会引起设备的block操作。归于使用领域的内容不在此介绍了。

  MIXER: 使用程序对混音器的软件接口。混音器电路一般由两个部分组成:input mixer和ouput mixer. 该设备的大部分操作都是由ioctl完成的, mixer设备答应一起多个用户一起拜访。 首要设备的参数有Rate ,Channel, Format. Volume, Standby等

  首要参数

  Oss体系的首要文件:

  sound/sound_core.c

  include/linux/sound.h

  sound/sound_core.h

  sound/sound_core.cinclude/linux/sound.hsound/sound_core.h

  Oss体系的首要结构介绍:

  structsound_unit

  {

  int unit_minor;

  const struct file_operations *unit_fops;

  struct sound_unit *next;

  char name[32];

  };

  structsound_unit{int unit_minor;const struct file_operaTIons *unit_fops;struct sound_unit *next;char name[32];};

  每个sound设备都会对应这样一个结构,unit_minor对应子设备号, unit_fops对应操作

  函数,这个是由各厂商应现,在注册设备的时分传入。Next指向下一个同类形设备,name

  就不需多说了。

  sound_class /sys/class/sound类

  staTIc struct sound_unit*chains[SOUND_STEP];

  /*整个OSS体系的链表数组,数组的每一项代表一种声卡设备,如下表所示:*/

  * 0 *16 Mixers

  * 1 *8 Sequencers

  * 2 *16 Midi

  * 3 *16 DSP

  * 4 *16 SunDSP

  * 5 *16 DSP16

  * 6 — sndstat (obsolete)

  * 7 *16 unused

  * 8 — alternate sequencer (see above)

  * 9 *16 raw synthesizer access

  * 10 *16 unused

  * 11 *16 unused

  * 12 *16 unused

  * 13 *16 unused

  * 14 *16 unused

  * 15 *16 unused

  sound_class /sys/class/sound类staTIc struct sound_unit*chains[SOUND_STEP];/*整个OSS体系的链表数组,数组的每一项代表一种声卡设备,如下表所示:*/* 0 *16 Mixers* 1 *8 Sequencers* 2 *16 Midi* 3 *16 DSP* 4 *16 SunDSP* 5 *16 DSP16* 6 — sndstat (obsolete)* 7 *16 unused* 8 — alternate sequencer (see above)* 9 *16 raw synthesizer access* 10 *16 unused* 11 *16 unused* 12 *16 unused* 13 *16 unused* 14 *16 unused* 15 *16 unused

  OSS体系的注册进程:

  本节描绘soundclass的注册进程,与及实例阐明dsp与mixer设备的注册进程,用户层

  是怎么经过设备节点拜访到各厂商供给设备的操作函数的。

  staTIc int __init init_soundcore(void)

  {

  intrc;

  rc= init_oss_soundcore();

  if(rc)

  returnrc;

  /*留意这儿的sound_class是大局函数,用于保存sound类*/

  sound_class= class_create(THIS_MODULE, “sound”); //注册/sys/class/sound类

  if(IS_ERR(sound_class)) {

  cleanup_oss_soundcore();

  returnPTR_ERR(sound_class);

  }

  sound_class-》devnode= sound_devnode;

  return0;

  }

  static int __init init_soundcore(void){intrc;rc= init_oss_soundcore();if(rc)returnrc;/*留意这儿的sound_class是大局函数,用于保存sound类*/sound_class= class_create(THIS_MODULE, “sound”); //注册/sys/class/sound类if(IS_ERR(sound_class)) {cleanup_oss_soundcore();returnPTR_ERR(sound_class);}sound_class-》devnode= sound_devnode;return0;}

  在体系启动阶段,kernel会调用到module_init,进入init_soundcore,初始化

  init_oss_soundcore, 并注册sound类,这样在/sys/class/下就有了sound类了, sound_devnode()

  也决议了相应的设备节点也将会呈现在/dev/snd/下面。

  static void __exit cleanup_soundcore(void)

  {

  cleanup_oss_soundcore();

  class_destroy(sound_class);

  }

  module_init(init_soundcore);

  module_exit(cleanup_soundcore);

  static void __exit cleanup_soundcore(void){cleanup_oss_soundcore();class_destroy(sound_class);}module_init(init_soundcore);module_exit(cleanup_soundcore);

  cleanup_soundcore函数对应于init_soundcore,首要用于铲除oss_soundcore, 并毁掉

  sound_class类。

  下面首要介绍一下,mixer与dsp设备的注册进程, 其它设备相同:

  int register_sound_dsp(const structfile_operations *fops, int dev)

  {

  returnsound_insert_unit(&chains[3], fops, dev, 3, 131,

  “dsp”, S_IWUSR | S_IRUSR, NULL);

  }

  EXPORT_SYMBOL(register_sound_dsp);“font-family: Arial, Verdana, sans-serif; white-space: normal; ”》

  int register_sound_dsp(const structfile_operations *fops, int dev){returnsound_insert_unit(&chains[3], fops, dev, 3, 131,“dsp”, S_IWUSR | S_IRUSR, NULL);}EXPORT_SYMBOL(register_sound_dsp);

  register_sound_dsp是注册dsp设备的函数,需求传入dsp设备的fops, 便是dsp设备的

  详细操作方法完成。register_sound_dsp调用sound_insert_unit函数完成注册, 这时传入

  的chains[3]便是在声卡数组链表的3上注册dsp设备,假如注册mixer设备便是chains[0]了。

  static intsound_insert_unit(struct sound_unit **list, const struct file_operations

  *fops,int index, int low, int top, const char *name, umode_t mode, struct device *dev)

  {

  struct sound_unit *s =kmalloc(sizeof(*s), GFP_KERNEL); //分配声卡设备内存

  int r;

  ………………………。

  r = __sound_insert_unit(s, list, fops,index, low, top); //注册声卡设备到list上

  spin_unlock(&sound_loader_lock);

  ………………………

  device_create(sound_class, dev,MKDEV(SOUND_MAJOR, s-》unit_minor),

  NULL, s-》name+6);

  //调用device_create播送设备信息到userspace,udev创立

  static intsound_insert_unit(struct sound_unit **list, const struct file_operations*fops,int index, int low, int top, const char *name, umode_t mode, struct device *dev){struct sound_unit *s =kmalloc(sizeof(*s), GFP_KERNEL); //分配声卡设备内存int r;……………………….r = __sound_insert_unit(s, list, fops,index, low, top); //注册声卡设备到list上spin_unlock(&sound_loader_lock);………………………device_create(sound_class, dev,MKDEV(SOUND_MAJOR, s-》unit_minor),NULL, s-》name+6);//调用device_create播送设备信息到userspace,udev创立

  现在就进入剖析__sound_insert_unit,剖析这儿就有点技巧了,咱们C基本功可得过关,

  分得清指针数组和数组指针,指针数组便是存在一个数组,数组里满是指针变量,在32位

  arm上,大于约等于max*int, 数组指针便是1个指向数组的指针,在32位arm上便是4byte.

  static int__sound_insert_unit(struct sound_unit * s, struct sound_unit **list,

  conststruct file_operations *fops, int index, int low, int top)

  { //传入的参数依次为: s,&chains[3], fops, dev, 3, 131

  ……………………………。.

  if (index 《 0) { /* first free */ //index 传入为 -1, 故进入此分支

  while (*list &&(*list)-》unit_minor//*list 就等于chains[3]值是否为空,为空

  list=&((*list)-》next);

  while(n

  {

  /* Found a hole ? */

  if(*list==NULL ||(*list)-》unit_minor》n) //因为第一次注册list为空,跳出

  break;

  list=&((*list)-》next);

  n+=SOUND_STEP;

  }

  if(n》=top)

  return -ENOENT;

  } else {

  ……………………………。.

  }

  s-》unit_minor=n; //直接赋值退出

  s-》unit_fops=fops;

  s-》next=*list;

  *list=s;

  static int__sound_insert_unit(struct sound_unit * s, struct sound_unit **list,conststruct file_operations *fops, int index, int low, int top){ //传入的参数依次为: s,&chains[3], fops, dev, 3, 131……………………………。.if (index 《 0) { /* first free */ //index 传入为 -1, 故进入此分支while (*list &&(*list)-》unit_minornext);while(nunit_minor》n) //因为第一次注册list为空,跳出break;list=&((*list)-》next);n+=SOUND_STEP;}if(n》=top)return -ENOENT;} else {……………………………。.}s-》unit_minor=n; //直接赋值退出s-》unit_fops=fops;s-》next=*list;*list=s;

  接下来返回到sound_insert_unit, 经过__register_chrdev将s, 注册到体系上,这

  里/dev/snd/下就呈现dsp姓名了,但古怪的时,这儿传入的fops不是s-》fops,而是体系公

  用的大局soundcore_fops, 在翻开dsp时接着剖析。

  r = __register_chrdev(SOUND_MAJOR,s-》unit_minor, 1, s-》name,

  &soundcore_fops);

  r = __register_chrdev(SOUND_MAJOR,s-》unit_minor, 1, s-》name,&soundcore_fops);

  翻开设备流程

  因为注册的时分传入的是soundcore_fops, 故翻开设备时会进入soundcore_fops的

  open函数。Soundcore_fops结构体如下。

  static const struct file_operationssoundcore_fops =

  {

  /*We must have an owner or the module locking fails */

  .owner = THIS_MODULE,

  .open = soundcore_open,

  };

  static const struct file_operationssoundcore_fops ={/*We must have an owner or the module locking fails */.owner = THIS_MODULE,.open = soundcore_open,};

  在这儿进入soundcore_open函数, 现在咱们就跟进去剖析。

  static int soundcore_open(struct inode*inode, struct file *file)

  {

  …………………

  if(s)

  new_fops= fops_get(s-》unit_fops);

  /*在这儿取得__sound_insert_unit注册的fops, 便是咱们在注册dsp时传入的fops. */

  if(preclaim_oss && !new_fops) { //这儿的new_fops是有值的,一切不会进入此分支

  spin_unlock(&sound_loader_lock);

  …………。.

  if(new_fops) {

  …………………。.

  conststruct file_operations *old_fops = file-》f_op;

  file-》f_op= new_fops; //在这儿批红判白,将体系的fops转换为s-》fops

  spin_unlock(&sound_loader_lock);

  if(file-》f_op-》open)

  err= file-》f_op-》open(inode,file);

  if(err) {

  fops_put(file-》f_op);

  file-》f_op= fops_get(old_fops);

  }

  fops_put(old_fops);

  unlock_kernel();

  returnerr;

  }

  static int soundcore_open(struct inode*inode, struct file *file){…………………if(s)new_fops= fops_get(s-》unit_fops);/*在这儿取得__sound_insert_unit注册的fops, 便是咱们在注册dsp时传入的fops. */if(preclaim_oss && !new_fops) { //这儿的new_fops是有值的,一切不会进入此分支spin_unlock(&sound_loader_lock);…………。.if(new_fops) {…………………。.conststruct file_operations *old_fops = file-》f_op;file-》f_op= new_fops; //在这儿批红判白,将体系的fops转换为s-》fopsspin_unlock(&sound_loader_lock);if(file-》f_op-》open)err= file-》f_op-》open(inode,file);if(err) {fops_put(file-》f_op);file-》f_op= fops_get(old_fops);}fops_put(old_fops);unlock_kernel();returnerr;}

  在这儿就发现在open设置时,体系将设备的fops转换为dsp注册时的fops, 偷天换

  日啊, linux kernel仍是蛮奇特的。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/xitong/88648.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部