驱动中一些重要函数

来源:互联网 发布:刻相片礼物淘宝 编辑:程序博客网 时间:2024/04/30 20:33
驱动中一些重要函数

1.驱动程序中的若干重要函数ioctl,register_chrdev,request_irq

(1)Ioctl方法

Ioctl方法主要用于对设备进行读写之外的其他控制,比如配置设备、进入或退出某种操作模式,这些操作一般都无法通过read/write文件操作来完成,无法通过write操作控制,这就是ioctl操作的功能。

用户空间的ioctl函数的原型为:

int ioctl(inf fd,int cmd,…)

其中的…代表可变数目的参数表,实际中是一个可选参数,一般定义为:

int ioctl(inf fd,int cmd,char *argp)

驱动程序中定义的ioctl 方法原型为:

int (*ioctl) (struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)

inode 和file两个指针对应应用程序传递的文件描述符fd(即在用户态下,调用ioctl时,就是把fd映射到内核态的前两个参数),cmd不会被修改地传递给驱动程序,可选的参数arg则无论用户应用程序使用的是指针还是其他类型值,都以unsigned long的形式传递给驱动。

(2)驱动程序的注册,这个工作是和驱动模块获 得主设备号时初始化一同进行的。你可以使用头文件 linux/fs.h中的函数register_chrdev来实现。

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
其中unsigned int major是你申请的主设备号, const char*name是设备文件名,将要在文件/proc/devices中出现。 struct file_operations*fops是指向你的驱动模块的 file_operations表的指针即用来登记驱动程序实际执行操作的函数的指针。负的返回值意味着注册失败。注册时并不需要提供从设备号。内核本身并不在意从设备号。如何申请一个没有被使用的主设备号?最简单的方法是查看文件Documentation/devices.txt从中挑选一个没有被使用的。这不是一劳永逸的方法因为你无法得知该主设备号在将来会被占用。最终的方法是让内核为你动态分配一个。如果你向函数register_chrdev传递为0的主设备号,那么 返回的就是动态分配的主设备号(如ret =register_chrdev(0, DEVICE_NAME,&s3c2410_fops);)。副作用就是既然你无法得知主设备号,你就无法预先建立一个设备文件。有多种解决方法。第一种方法是新注册的驱动模块会输出自己新分配到的主设备号,所以我们可以手工建立需要的设备文件。第二种是利用文件/proc/devices新注册的驱动模块的入口,要么手工建立设备文件,要么编一个脚本去自动读取该文件并且生成设备文件。第三种是在我们的模块中,当注册成功时,使用mknod调用建立设备文件并且调用 rm删除该设备文件在驱动模块调用函数(cleanup_module(void){unregister_chrdev(major,’DEVICE_NAME’)}第一参数表示主设备号,第二个参数表示设备名)前。

一种问题要注意的是,在操作驱动程序时,系统处于内核态,此进要输出打印信息要用printk()函数,而在用户态时,要输出打印信息时,要用printf()函数。

编译驱动程序时,$gcc –O2 –DMODULE –D__KERNEL__ -c(test.o可加可不加)test.c其中各个参数表示:本机gcc,二级优化,编译成模块,声明为要加载到内核的模块。如果设备驱动程序有多个文件,把每个文件按上面的命令行编译后,ld –r file1.o file2.o –o modulename进行链接。

编译完成后,要加载到内核中去,$insmod –f test.o如果安装成功在/proc/devices中可以看到设备test,并可以看到它的主设备号。

要卸载的话,$rmmod test

要创建设备文件,mknod /dev/test c major minor

用mknod命令来创建一个设备文件:mknod device_driver c 120 0,device_driver为设备文件名,c指的是字符设备,120是主设备号,0为次设备号。device_driver这个名字与注册函数中使用的字符串要一致!即register_chrdev(0, DEVICE_NAME, &s3c2410_fops); 中的DEVICE_NAME要与device_driver一致。

要查看驱动程序的主设备号,$ cat /proc/devices对应,就可以看到主设备号,从设备号一般设置为0。

(3)中断申请函数int request_irq(unsigned int irq,void (*handle)(int,void*,struct pt_regs*),unsigned int long flags,const char *device,void*dev_id)各个参数表示:要申请的中断号,申请的中断服务程序入口,中断标识(SA_INTERRUPT快速中断(区别于ARM中的快速中断),0为正常中断,或共享中断),中断产生的设备名(哪一设备要用到这个中断, 用于在/proc/interrupts中显示的中断的拥有者),用于标识产生中断的设备号。如果登记成功会返回0,这时在/proc/interrupts文件中可以看到你请求的中断。

(4) devfs_register函数

其原型为:

devfs_register(devfs_handle_t dir, const char *name, unsigned int flags,

unsigned int major, unsigned int minor,

umode_t mode, void *ops, void *info)

其中的参数说明如下:

Dir 新创建的设备文件的父目录,一般设为null, 表示父目录为/dev

Name 设备名称,如想包含子目录,可以直接在名字中包含’/’

Flags Devfs标志的位掩码。

Major 主设备号 如果在flags参数中指定为DEVFS_FL_AUTO_DEVNUM,则主次设备号就无用了。

Minor 次设备号,

Mode 设备的访问模式

Ops 设备的文件操作数据结构指针

Info filp->private_data的默认值。

原创粉丝点击