一、开发模块框架
1),编写源代码
#include <linux/init.h>
#include <linux/module.h>
//加载函数
static int __init hello_init(void)
{
printk("----- ^_^ --------%s-------\n",__FUNCTION__);
return 0;
}
//卸载函数
static void __exit hello_exit(void)
{
printk("-----------%s-----------\n",__FUNCTION__);
}
module_init(hello_init);//声明加载函数
module_exit(hello_exit);//声明卸载函数
MODULE_LICENSE("GPL");//认证
2):写Makefile
1 #指定内核源码的路径
2 KERNEL_DIR = /home/GNNUXXL/s5pv210/kernel/linux-3.0.8
3 CURENT_DIR = $(shell pwd)
4
5 all:
6 #将当前路径下的源码编译为内核模块
7 make -C $(KERNEL_DIR) M=$(CURENT_DIR) modules
8 clean:
9 #清除生成的模块文件
10 make -C $(KERNEL_DIR) M=$(CURENT_DIR) clean
11 install:
12 cp *.ko /opt/rootfs/drv_module/
13 #指定哪个文件生成模块
14 obj-m = hello_drv.o
3):将生成的模块拷贝到开发板中
cp *.ko /opt/rootfs/drv_module/ 或者使用 make install
4)加载模块
[root@GNNUXXL /drv_module]# insmod hello_drv.ko
----- ^_^ --------hello_init-------
5)查看模块信息
root@GNNUXXL /drv_module]# lsmod
hello_drv 779 0 - Live 0x7f00c000
6)卸载模块
[root@GNNUXXL /drv_module]# rmmod hello_drv
-----------hello_exit-----------
二、模块传参特性
1)在加载模块时,可以进行传参,但是在编写代码时要对参数进行声明
例如:
module_param(变量名,类型,权限 0644);
module_param(num,int, 0644);
module_param(name, charp, 0644);
[root@GNNUXXL /drv_module]# insmod hello_arg.ko
-------------hello_arg_init------------
num=1001 name=bao_ma_nan
[root@GNNUXXL /drv_module]# rmmod hello_arg
-------------hello_arg_exit------------
[root@GNNUXXL /drv_module]# insmod hello_arg.ko num=1999 name="fansha"
-------------hello_arg_init------------
num=1999 name=fansha
在加载模块时会创建一个同名文件存放相关参数
[root@GNNUXXL /drv_module]# ls -l /sys/module/hello_arg/parameters/
total 0
-rw-r--r-- 1 0 0 4096 Jan 1 02:29 name
-rw-r--r-- 1 0 0 4096 Jan 1 02:29 num
2)模块调用
//被调用模块
int mysum(int a,int b)
{
return a+b;
}
//声明mysum函数
EXPORT_SYMBOL(mysum);
在加载过程中,先加载被调用模块,后加载本身模块
[root@GNNUXXL /drv_module]# insmod mysum.ko
[root@GNNUXXL /drv_module]# lsmod
mysum 561 0 - Live 0x7f010000
[root@GNNUXXL /drv_module]# insmod hello_call.ko n=100 m=150
-----------hello_call_init-------------
100+150 = 250
[root@GNNUXXL /drv_module]# lsmod
hello_call 1000 0 - Live 0x7f014000
mysum 561 1 hello_call, Live 0x7f010000
在卸载时,先卸载本身模块,后卸载调用模块
[root@GNNUXXL /drv_module]# rmmod hello_call
------------hello_call_exit-----------
[root@GNNUXXL /drv_module]# rmmod mysum
三、一个完成驱动程序的开发
设备号由32位组成
-----------> 主设备号 -------高12位
-----------> 次设备号 -------低20位
1)申请设备号:
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:
当major=0时,主设备号为动态分配,函数返回主设备号
当major>0时,主设备号为静态分配,成功函数返回0
参数2:驱动的描述信息---->自定义
参数3:操作方法
查看设备号 cat /proc/devices
[root@GNNUXXL /drv_module]# cat /proc/devices
Character devices:
1 mem
256 hello_drv
2 pty
3 ttyp
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
21 sg
128 ptm
136 pts
204 ttySAC
2)创建设备节点
----->手动创建设备节点
mknod 设备名 设备类型 主设备号 次设备号
mknod /dev/hello c 254 0
----->自动创建设备节点
创建类
class_create(owner, name)
创建设备
register_device(char * name, unsigned long start, unsigned long len)
3)实现操作方法