新建myled.c,参考Myleds.c,复制他的一些函数代码修改函数名(Myleds.c是我之前自己写的,没有的话按照下面图片写open和write函数就行)
如:
我们定义了这个结构体,但是没有用起来,所以要告诉内核,怎么告诉,需要一个系统函数register_chrdev
原型:int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
参数1:主设备号
参数2:设备名
参数3:file_operations结构体
如:
那么我们用register_chrdev来注册,register_chrdev被谁调用呢,被入口函数调用,怎么写入口函数
我们想,内核中可能有很多驱动入口函数,如seconddrv,thirddrv等,内核怎么分辨这些入口函数
***就要修饰一下,用宏module_init
module_init(入口函数名);
什么是module_init
当模块被加载时,执行moudle_init函数,该函数会调用初始化函数
module_init是定义一个结构体,这个结构体里面有一个函数指针,指向这个入口地址,当我们加载一个驱动,或者安装一个驱动时,内核就会自动去找到这么一个结构体,去指向这个入口函数,然后入口函数就用register_chrdev注册,告诉内核这个file_operations结构体。
我们研究register_chrdev这个函数,major是主设备号,当我们在终端上输入:ls /dev -l 时,可以看到c是指字符设备,7是主设备号,0-...是次设备号
主设备就是为了让应用程序可以找到file_operationsd的open成员的标识
如,对于字符设备驱动:
app: open("/dev/xxx",...);
/dev/xxx有上面图片那种属性:类似crw-rw....,major(主),mior(次)
app的open函数打开/dev/xxx,就是通过主次设备号去找到register_chrdev中的file_operations的open函数,进行上层到底层的操作
register_chrdev是通过在内存里用一个数组,以major为索引,把file_operations挂接上去
6.具体流程:
(1)有入口函数,也有出口函数,参考Myleds.c
(2)我们只是简答写一个驱动程序,打印即可,内核打印是用printk
(2)包含头文件,参考Myleds.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
9.用ftp传到虚拟机上,编写Makefile
KERN_DIR = /work/system/linux-2.6.22.6 //内核目录 all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += myled.o //依赖文件执行make后生成myled.ko文件
编写测试程序mylec_test.c
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { int fd; int val = 1; fd = open("/dev/myled", O_RDWR); if (fd < 0) { printf("can't open!\n"); } write(fd, &val, 4); return 0; }在虚拟机上用交叉编译工具生成可执行文件
#arm-linux-gcc -o mylec_test mylec_test.c
把mylec.ko 和mylec_test拷贝到络文件系统
在开发版终端上执行
发现不能输出打印信息,也没有/dev/myled的设备文件。原因是我们没有设置设备节点,有分手动设置和自动设置。这里我们先讲用mknod手动分配设备节点
我们所写的代码只是注册了一个名为myled的驱动,并通过register_chrdev让内核帮我们分配主设备号,可以使用 cat /proc/devices 查看内核以后主设备号
发现内核帮我们把设备号设置为252,根据这个使用mknod手动分配设备节点
在开发版的终端上用 mknod /dev/xxx c 主设备号 次设备号(删除设备号为 rm /dev/xxx)
这个时候就可以执行可执行文件了,成功打印
这就是最简单的驱动程序了,属于手动分配设备节点。下一节讲使用udev自动分配设备节点,使用
class_create为该设备创建一个class,再为每个设备调用 device_create创建对应的设备。
加载模块后,会自动在/dev/下创建myled设备文件。