当前位置:懂科普 >

综合知识

> linuxsound驱动架构怎么写 解释一下linux驱动程序结构框架及工作原理

linuxsound驱动架构怎么写 解释一下linux驱动程序结构框架及工作原理

1.解释一下linux驱动程序结构框架及工作原理

一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。

linuxsound驱动架构怎么写 解释一下linux驱动程序结构框架及工作原理

设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1、对设备初始化和释放; 2、把数据从内核传送到硬件和从硬件读取数据; 3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4、检测和处理设备出现的错误。

在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。

块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 已经提到,用户进程是通过设备文件来与实际的硬件打交道。

每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。

最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。

如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。

虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。

由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系统调用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构: STruct file_operatiONs { int (*seek) (struct inode * ,struct file *, off_t ,int); int (*read) (struct inode * ,struct file *, char ,int); int (*write) (struct inode * ,struct file *, off_t ,int); int (*readdir) (struct inode * ,struct file *, struct dirent * ,int); int (*select) (struct inode * ,struct file *, int ,select_table *); int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long); int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *); int (*open) (struct inode * ,struct file *); int (*release) (struct inode * ,struct file *); int (*fsync) (struct inode * ,struct file *); int (*fasync) (struct inode * ,struct file *,int); int (*check_media_change) (struct inode * ,struct file *); int (*revalidate) (dev_t dev); } 这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。

这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域。

下面就开始写子程序。 #include 基本的类型定义 #include 文件系统使用相关的头文件 #include #include #include unsigned int test_major = 0; static int read_test(struct inode *inode,struct file *file,char *buf,int count) { int left; 用户空间和内核空间 if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT ) return -EFAULT; for(left = count ; left > 0 ; left--) { __put_user(1,buf,1); buf++; } return count; } 这个函数是为read调用准备的。

当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf 是read调用的一个参数。

它是用户进程空间的一个地址。但是在read_test被调用时,系统进入核心态。

所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。

请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。

为了验证BUF是否可以用。 static int write_test(struct inode *inode,struct file *file,const char *buf,int count) { return count; } static int open_test(struct inode *inode,struct file *file ) { MOD_INC_USE_COUNT; 模块计数加以,表示当前内核有个设备加载内核当中去 return 0; } static void release_test(struct inode *inode,struct file *file ) { MOD_DEC_USE_COUNT; } 这几个函数都是空操作。

实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。 struct file_operations test_fops = {? read_。

2.为什么Linux的音频驱动位于sound目录下而不是driver/sound

1、早期的2.4内核所有的音频驱动和其他驱动一样都是位于drivers目录下的:drivers/sound

2、到了2.5开发版内核,所有的音频驱动包括音频框架代码由drivers/sound移到了sound目录下:

(1)2.6内核之前的git记录查找:mit;h=

author Jaroslav Kysela <[email protected]>

Wed, 13 Feb 2002 03:32:11 +0000 (19:32 -0800)

committer Jaroslav Kysela <[email protected]>

Wed, 13 Feb 2002 03:32:11 +0000 (19:32 -0800)

commit

tree tree | snapshot

parent commit | diff

[PATCH] ALSA patch for 2.5.4

Integrate ALSA into v2.5.4

Jaroslav

这个提交是在2.5.4~2.5.5-pre1之间发生的

从这个提交信息可以看出,是在Linux内核正式引入ALSA音频构架的时候,所有的代码都被移动到了drivers/sound下。

也就是在同一天,音频子系统的维护由原来的Alan Cox转为Jaroslav Kysela:

mit;h=

Make Jaroslav the sound maintainer, remove Alan on his request.

author Linus Torvalds <[email protected]>

Wed, 13 Feb 2002 04:05:43 +0000 (20:05 -0800)

committer Linus Torvalds <[email protected]>

Wed, 13 Feb 2002 04:05:43 +0000 (20:05 -0800)

commit

tree tree | snapshot

parent commit | diff

Make Jaroslav the sound maintainer, remove Alan on his request.

所以这个代码的移动应该是在ALSA那个分支开发的时候就已经是这样的了

3.声卡驱动说明这一段英文是什么意思

步骤1:解压缩源码tar xfvj 高级Linux声音架构(Advanced Linux Sound Architecture)-驱动 1.0.xx.tar.bz2步骤2:a.读取光碟中高级Linux声音架构-1.0 xx驱动b..声卡配置--inter 高保真音频(High Definition Audio-inter )c.创建d.创建安装步骤3:重启您的机器步骤4.使用音频混音器,终止静音 (所有音频设备默认设置静音)必须编译和安装高级Linux声音架构库和程序 (使用自动安装已执行安装)执行音频混音器Note:注意:1.详细细节可以查阅位于azx-021705.tar.bz2有关高级Linux声音架构内核/程序说明书/ 高级Linux声音架构配置文本文档.2.内核版本必须为2.6或者更新版3.所有混音器通道均被默认设置为静音,你必须使用本地的或者一个unix平台上一个统一的音频接口(Open Sound System )混音器程序打开音频通道.4.如无法读取源码,尝试重命名/usr/src/linux-2.x 文件为 /usr/src/linux.5.驱动增加支持索尼-飞利浦数字界面格式(Sony-Philips Digital Interface Format,)功能.6.a.你可以访问/ sound/其中,sound 就是声卡模块存放目录,大多数的硬件驱动放在 drivers目录,fs 是文件系统模块的目录;net是与网络有关的存放目录,比如一些网络协议支持的模块、防火墙支持的模块等;arch 是cpu方面 。 。

如果我们想自己加载模块,就到这些目录中查看相应模块的信息,然后用 modprobe 来加载; [root@localhost beinan]# modinfo snd-intel8x0 查看一个模块的信息,我们用 modinfo 来查看,所要查看的模块不要带 .ko 或者.o 之类的;比如查看到类似下面的信息; description: Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455 通过这个我们足可以知道这是Intel 集成声卡,通过lspci -v 得到的声卡信息,感觉他们很相近;所以就能尝试用这个模块来驱动; [root@localhost beinan]# modprobe snd-intel8x0 用 modprobe 加载了模块,然后我们通过 lsmod 就能看到了;对于声卡模块是这么加载的,其它设备的驱动模块也是如此。

  • 文章版权属于文章作者所有,转载请注明 https://dongkepu.com/zonghezhishi/xjwx5n.html