嵌入式Linux以其可应用于多种硬件平台,内核高效稳定,源码开放,软件丰富,网路通讯和文件管理机制建立等优良特点,成为了嵌入式系统领域中的一个研究热点。
嵌入式Linux系统中,内核提供保护机制,用户空间的进程通常不能直接访问硬件,进行嵌入式系统的开发,很大的工作量视为各类设备编撰驱动程序,除非系统不适用操作系统。
嵌入式Linux设备驱动程序开发流程
三类主要的设备文件类型:块设备、字符设备和网路设备。这些分类方式可以将控制不同的输入/输出设备的驱动程序与其他操作系统软件分离开来。
字符设备与块设备的主要区别是:在对字符设备发出读/写恳求时,实际的硬件I/O通常紧接着发生;块设备则不然,它借助用一块系统显存做缓冲区,若用户进程对设备的恳求能满足用户的要求,就返回恳求的数据,否则,就调用恳求函数来进行实际的I/O操作。
网路设备可以通过BSD套插口访问数据。
BSDSocket是UNIX系统中通用的网路插口,它除了支持各类不同的网路类型,并且也是一种内部进程之间的通讯机制。两个通讯进程都用一个套插口来描述通讯链路的两端。套插口可以觉得是一种特殊的管线,但和管线不同的是,套插口对于可以容纳的数据的大小没有限制。
Linux支持多种类型的套插口,也称作套插口轮询族,这是由于每种类型的套插口都有自己的轮询方式。
Linux支持以下的套插口类型:
-UNIXUNIX域套插口
-INETInternet地址族TCP/IP合同支持通讯。
-AX25AmateurradioX25
-IPXNovellIPX
-APPLETALKAppletalkDDP
-X25X25
Linux的BSD套插口支持下边的几种套插口类型:
1.流式(stream)这种套插口提供了可靠的单向次序数据流联接。它们可以保证数据传输中的完整性、正确性和单一性。INET轮询族中的TCP合同支持这种类型的套插口。
2.数据报(Datagram)这种类型的套插口也可以像流式套插口一样提供单向的数据传输,但它们不能保证传输的数据一定就能抵达目的节点。虽然数据才能抵达,也难以保证数据以正确的次序抵达以及数据的单一性、正确性。UDP合同支持这种类型的套插口。
3.原始(Raw)这种类型的套插口容许进程直接存取上层的合同。
4.可靠递送消息(ReliableDeliveredMessages)这些套插口和数据报套插口一样,只能保证数据的抵达。
5.次序数据包(SequencedPackets)这些套插口和流式套插口相同,不仅数据包的大小是固定的。
6.数据包(Packet)这不是标准的BSD套插口类型,而是Linux中的一种扩充。它容许进程直接存取设备层的数据包。
驱动程序共有的特点:
读/写:具体的读/写操作由驱动程序屏蔽掉了,操作系统定义好一些读/写插口,由驱动程序完成具体的功能,在驱动程序初始化时,须要把具有这些插口的读/写函数注册到操作系统。
中断:操作系统提供驱动程序响应中断的能力linux 设备驱动程序,通常是把一个中断处理程序注册到系统中,操作系统在硬件终端发生后,调用驱动程序的处理程序,Linux支持中断的共享,即多个设备共享一个中断。
时钟:操作系统应为驱动程序提供时钟机智,通常是在预定的时间过了之后,反弹注册的时钟函数。
实现一个嵌入式Linux设备驱动的大致流程如下:
设备文件的操作要复杂得多,所有其他类型的操作都可以通过VFS的ioctl低啊拿来执行。因此,只须要在驱动程序中实现ioctl函数,并在其中添加相应的case即可,通过cmd分辨操作linux系统怎么样,通过arg传递参数和结果。
模块化驱动程序设计及框架
Linux的内核是一个整体式内核(monolithickernel,与之对应的是微内核,microkernel),即所有的内核功能联接在一起,在同一个地址空间执行,但完全这样做会带来好多不便和浪费,Linux操作系统提供了一种机制,即内核模块来解决这个问题。
模块是内核的一部份,并且都是设备驱动程序,但它们并没有编译到内核中,而是被分别编译并链接成一组目标文件,依照须要动态载入模块可以保证内核达到最小,而且具有很大的灵活性。
内核魔铠一部份保存在kernel中,另一部份在modules包中。
两个重要的函数
内核为之后处理个别恳求而注册自己,完成这个任务后,它的“主”函数就立刻中止了深度linux,模块的作用就是扩充内核的功能linux 设备驱动程序,运行在内核中模块化的代码,一般,一个设备驱动程序完成两个任务:模块的个别函数作为系统调用执行,而另一些函数则负责处理中断。
-init_module():在模块调入内核时调用,它在内核中注册一定的功能函数,在注册以后,假如有程序访问内核模块的某个功能,内核将查表获得该功能在module中的位置,之后调用功能函数。
-cleanup_module():在模块从内核中卸载时被调用,它把原先注册的功能函数卸载掉。
init_module()函数在运行insmod后由系统调用,完成驱动模块的初始化工作,clesnup_module()函数在运行rmmod后有系统调用。
Linux模块调用如图所示:
设备驱动加到嵌入式Linux内核中
嵌入式Linux设备驱动程序编撰完成后,须要将该驱动程序加到内核中,这要求更改嵌入式Linux的源代码,之后重新编译内核。具体步骤如下:
1.将设备驱动程序文件(如:mydriver.c)复制到/linux/drivers/char/目录下。该目录保存了Linux下字符设备的设备驱动程序。更改该目录下mem.c文件,在intchr_dev_init()函数中降低如下代码:
#地方的发CONFIG_MYDRIVER
device_init();
#endif
其中,CONFIG_MYDRIVER是在配置Linux内核时形参的。
2.在/linux/drivers/char/目录下Makefile中降低如下代码:
ifeq($(CONFIG_MYDRIVER),y)
L_OBJS+=mydriver.o
endif
假如在配置Linux内核时选择了支持新定义的设备,则在编译内核是会编译mydriver.c生成mydriver.o文件。
3.更改/linux/drivers/char/目录下config.in文件,在commentcharacterdevices句子下边加上boolsupportformydriverCONFIG_MYDRIVER。这样,若内核编译,运行makeconfig、makemenuconfig或makexconfig,这么在配置字符设备时才会有选项supportformydriver,连任中这个选项时,设备驱动就加到内核中了。
4.重新编译内核,在上将当前目录cd到lLinux目录下,之后执行以下代码:
#makemenuconfig
#makedep
#make
在配置选项时,要注意选择支持用户添加的设备。这样,得到的内核就包含了用户的设备驱动程序。
本文原创地址://lrxjmw.cn/qrslxtsbwjlx.html编辑:刘遄,审核员:暂无