驱动程序的组成部分(.ko的C文件内容)
(1) module_init() 指定insmod命令时调用的初始化函数init()。
module_exit() 指定rmmod命令时调用的退出函数exit()。
(2) name_fops定义 将用户层的open、ioctl函数与驱动程序中的name_open、name_ioctl函数联系起来。
(3) name_init() 驱动初始化函数。insmod.ko时候调用该函数(经过(1)指定后)。里面包含动作有:
A:register函数,将驱动模块信息注册到内核中,驱动信息包括(2)中的fops,设备名,主设备号。如此之后,设备号、设备名与驱动程序中的name_open、name_ioctl函数联系起来。
B:(可选)建立设备文件(mknod)。class_create()与device_create()。
(4) name_open() 对硬件进行初始化
name_ioctl() 由用户层进行的带参数传递操作。
这两个函数是驱动实际操作函数,可根据实际需求进行灵活编写。
总体理解:
使用一个驱动模块,首先要insmodname.ko文件,这时系统会先根据name.ko文件中的module_init()(1)指定到name_init()函数(3)中,该函数将主设备号,设备名以及fops函数注册内核中。(在/pro/devices可见)
然后再mknod(可在初始化函数中进行),建立主设备号、设备名
然后用户层主程序操作,主程序中必须先有open函数然后再ioctl。用户调用驱动时,先通过设备名找到/dev/name(通过open函数实现),这是一个入口,再通过设备号联系到驱动程序中的ioctl函数((2)、(3)步骤实现)。
Makefile 驱动模块编写
在天嵌提供的资料里,驱动模块(.ko)文件都是加在源码树中进行编译的。即驱动代码放在内核源码树的固定位置,然后进行make modules。
这样做过于麻烦,可以将驱动代码放在任何目录下,然后在该目录下编写makefile文件。直接make。如下:
all:
make -C/opt/EmbedSky/linux-2.6.30.4 M=/work/LED_driver modules
clean:
make -C/opt/EmbedSky/linux-2.6.30.4 M=/work/LED_driver modules clean
rm -f modules.order
obj-m =EmbedSky_LED.o
/opt/EmbedSky/linux-2.6.30.4是内核源码目录,这个位置必须指定,因为驱动模块需要在内核环境下编译(头文件、函数等),将其指定之后即可类似于在内核下进行make modules.
/work/LED_driver是驱动代码目录,注意是目录而非文件。
obj-m=EmbedSky_LED.o m表示将生成一个.ko文件,而这个文件要从目标文件EmbedSky_LED.o中创建。