接上文中,我们编写了一个字符设备驱动的框架程序,在这个示例中,我们定义了一个字符设备驱动程序,包括设备打开、读取、写入和关闭的基本操作。在my_chardev_init函数中,我们动态分配了设备号,并初始化了cdev结构体,然后将其添加到系统中。在my_chardev_exit函数中,我们删除了cdev并释放了设备号。
请注意,这个示例中只实现了my_write函数的基本操作。在实际开发中,您需要根据您的硬件设备来实现这些函数,以执行实际的读取和写入操作。
此外,为了编译这个驱动程序,您需要编写一个Makefile,并使用适当的内核头文件和编译器选项来编译它。然后,您可以使用insmod命令加载模块,并使用rmmod命令卸载模块。在加载模块后,您可以使用mknod命令在/dev目录下创建一个设备节点,以便用户空间程序可以访问这个字符设备。具体测试流程如下:
1.通过如下Makefile,编译驱动文件xuedaon.c,生成模块xuedaon.ko
KDIR=/lib/modules/$(shell uname -r)/build
#规则头
#规则体
xxx:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=`pwd` modules clean
obj-m += xuedaon.o
2.通过insmod命令插入模块:
插入模块后,通过dmesg查看内核打印信息:
3.通过mknod在目录/dev/下面新建设备节点:mydev,该设备的主设备号和次设备号需要和驱动注册是生成的主设备号和次设备号对应:
4.编写上层应用程序,实现上层应用到驱动的调用:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDWR );
if( fd < 0 ){
perror("open error");
return -1;
}else{
printf("open success ");
}
int ret = write( fd, argv[2], strlen(argv[2]) );
if( ret < 0 ){
printf("write error");
return -1;
}
close( fd );
return 0;
}
5.上层应用程序编译生成可执行文件:app, 如下执行可以调用到设备/dev/mydev,向设备写入字符串“helllo”:
通过dmesg打印驱动执行信息:
在此测试中,我们通过上层中的open、close、write函数调用了驱动中my_open、my_close、 my_write操作。你也可以在此基础上测试my_read,亦或测试file_operations中的其他操作接口。