loading请求处理中...

字符设备linux驱动程序开发_驱动程序开发入门linux实例

2021-12-01 06:19:17 阅读 9238次 标签: linux基础教程 作者: anyi
字符设备linux驱动程序开发_驱动程序开发入门linux实例
    对于嵌入式的开发,linux系统是比较常见的,而linux设备驱动程序的一个基本功能就是管理和控制设备,同时为用户应用程序提供管理和控制设备的接口。当我们访问一个设备节点时,系统是如何知道使用哪个设备驱动及访问哪个设备的呢?这个是通过设备号来实现的。当我们创建一个设备节点时需要指定主设备号和次设备号。对于设备节点来说,名字不是重要的,设备号才是最重要的,它实际指定了对应的驱动程序和对应的设备。
字符设备linux驱动程序开发
字符设备linux驱动程序开发_驱动程序开发入门linux实例
    嵌入式系统中,操作系统是通过各种驱动程序来驾驭硬件设备的。设备驱动程序是操作系统内核和硬件设备之间的接口,它为应用程序屏蔽了硬件的细节,这样在应用程序开发看来,硬件设备只是一个设备文件,可以像操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,完成以下功能:
    *驱动程序的注册和注销。
    *设备的打开和释放。
    *设备的读写操作。
    *设备的控制操作。
    *设备的中断和轮询处理。
    Linux主要将设备分为三类:字符设备、块设备和网络设备。字符设备是指发送和接收数据以字符的形式进行,没有缓冲区的设备;块设备是指发送和接收数据以整个数据缓冲区的形式进行的设备;网络设备是指网络设备访问的BSD socket 接口。下面一品威客网以字符设备为例,写出其驱动编写框架:
    一、编写驱动程序初始化函数
    驱动程序的初始化在函数xxx_init()中完成,包括对硬件初始化、中断函数、向内核注册驱动程序等。
    首先理解硬件结构,搞清楚其功能,接口寄存器以及CPU怎么访问控制这些寄存器等。
    其次向内核注册驱动程序。设备驱动程序可以直接编译进内核,在系统启动的时候初始化,也可以在需要的时候以模块的方式动态加载到内核中去。每个字符设备或是块设备都是通过register_chrdev()函数注册,调用该函数后就可以向系统申请主设备号,操作成功,设备名就会出现在/proc/devices里。
    此外,在关闭设备时,需要先解除原先设备的注册,需要有清除函数,在xxx_exit()中通过unregister_chrdev()函数在实现,此后设备就会从/proc/devices里消失。
    当驱动程序开发被编译成模块时,使用insmod加载模块,模块的初始化函数xxx_init()被调用,向内核注册驱动程序;使用rmmod卸载模块,模块的清除函数xxx_exit()被调用。
    二、构造file_operations结构中要用到的各个成员函数
    Linux操作系统将所有的设备都看成文件,以操作文件的方式访问设备。应用程序不能直接操作硬件,使用统一的接口函数调用硬件驱动程序,这组接口被成为系统调用。每个系统调用中都有一个与之对应的函数(open、release、read、write、ioctl等),在字符驱动程序中,这些函数集合在一个file_operations类型的数据结构中。以一个键盘驱动程序为例:
    struct file_operations Key7279_fops =    
    {
    .open = Key7279_Open,    
    .ioctl = Key7279_Ioctl,    
    .release = Key7279_Close,
    .read = Key7279_Read,
    };
    1、设备的打开和释放
    打开设备是由open()函数来完成,在大部分设备驱动中open完成如下工作:
    *递增计数器
    *检查特定设备的特殊情况
    *初始化设备
    *识别次设备号
    释放设备由release()函数来完成。当一个进程释放设备时,其它进程还能继续使用该设备,只是该进程暂时停止对该设备的的使用,而当一个进程关闭设备时,其它进程必须重新打开此设备才能使用。Release完成如下工作:
    *递减计数
    *在最后一次释放设备操作时关闭设备
    2、设备的读写操作
    读写设备的主要任务就是把内核空间的数据复制到用户空间,或者是从用户空间复制到内核空间,也就是将内核空间缓冲区里的数据复制到用户空间的缓冲区中或者相反。字符设备使用各自的read()函数和write()函数来进行数据读写。
    3、设备的控制操作
    大部分设备除了读写能力,还可进行超出简单的数据传输之外的操作,所以设备驱动也必须具备进行各种硬件控制操作的能力. 这些操作常常通过 ioctl 方法来支持。与读写操作不同,ioctl()的用法与具体设备密切相关。以键盘Key7279_Ioctl为例:
    static int Key7279_Ioctl(struct inode *inode,struct file *file,unsigned int cmd, unsigned long arg)
    {
    switch(cmd)    
        {
    case Key7279_GETKEY:
    return key7279_getkey();
        default:
        printk("Unkown Keyboard Command ID.n");
       }
        return 0;
    }
    cmd的取值及含义都与具体的设备有关,除了ioctl(),设备驱动程序还可能有其他控制函数,比如llseek()等。
    当应用程序使用open、release等函数打开某个设备时,设备驱动程序的file_operations结构中的相应成员就会被调用。
    三、设备的中断和轮询处理
    对于不支持中断的设备,读写时需要轮询设备状态,以及是否需要继续进行数据传输。例如,打印机。如果设备支持中断,则可按照中断方式进行。
模块在使用中断前要先请求一个中断通道(或者 IRQ中断请求),并在使用后释放它。通过request_irq()函数来注册中断,free_irq()函数来释放。
    四、驱动程序的测试
    对驱动程序的调试可以通过打印的方式来进行,就是通过在驱动程序中添加printk()打印函数,来跟踪驱动程序的执行过程,以此来判断问题。
    以上是我根据自己的Linux驱动程序开发总结的,可能写的比较简单,对于比较复杂的驱动函数,会添加更多的函数,但是大体的框架就是这样了。
    Linux为所有的设备文件都提供了统一的操作函数接口,方法是使用数据结构struct file_operations。这个数据结构中包括许多操作函数的指针,如open()、close()、read()和write()等,但由于外设的种类较多,操作方式各不相同。Struct file_operations结构体中的成员为一系列的接口函数,如用于读/写的read/write函数和用于控制的ioctl等。打开一个文件就是调用这个文件file_operations中的open操作。不同类型的文件有不同的file_operations成员函数,如普通的磁盘数据文件,接口函数完成磁盘数据块读写操作;而对于各种设备文件,则最终调用各自驱动程序中的I/O函数进行具体设备的操作。这样,应用程序根本不必考虑操作的是设备还是普通文件,可一律当作文件处理,具有非常清晰统一的I/O接口。所以file_operations是文件层次的I/O接口。 

    一品威客网汇聚了数百万专业的程序开发软件美工插件开发软件汉化脚本制作软件测试游戏开发办公系统开发程序修改嵌入式桌面软件多媒体软件其他软件开发等优秀威客人才,只要您在网站发布任务需求,就能够吸引众多威客给您献上最好的创意服务。

推荐更多与“字符设备linux驱动程序开发_驱动程序开发入门linux实例”相关推荐:

 安卓程序开发 | 微信功能开发 | 微信公众号开发 | 手机wap网站开发 | 微信定制功能开发

 手机程序开发 | 微信商城开发 | 手机微网站开发 | 微信api功能开发 | 微信签到功能开发

 手机网站制作 | 网站开发框架 | 微信3g网站开发 | Windows驱动开发 | 嵌入式应用程序开发

公司推荐

成为一品威客服务商,百万订单等您来有奖注册中

留言( 展开评论