在进行驱动程序的编写前建议先对驱动linux系统驱动的原理进行深入了解一下再进行驱动编写可能会更快上手。
对于很多新手来说,驱动开发这块可能概念比较模糊,原理什么的我在这里不讲,因为太多了。。。。如果你刚进行驱动程序的开发学习建议先补充关于linux的一些基础知识,再来看本文章。
本驱动运行的环境是:Ubuntu16.04
其他的一些环境运行的依赖文件或者库请自行安装。
1、接下来我直接贴出来驱动代码源码:
#include#include #include #include #include #include #include #include #include #include static int major = 0; static char kernel_buf[1024];//内核的缓存区 static struct class *hello_class;//定义节点的类 #define MIN(a,b) (a //open函数的实现 printk("%s %s line %dn",__FILE__,__FUNCTION__,__LINE__);//内核的打印用的是printk实现的 return 0; } static int hello_close(struct inode *node,struct file *file) {//close函数的实现 printk("%s %s line %dn",__FILE__,__FUNCTION__,__LINE__); return 0; } static ssize_t hello_read(struct file *file, char __user *buf, size_t size, loff_t *offset) {//read函数的实现 int err;//这个err定义只是为了避免编译告警,没有使用 printk("%s %s line %dn",__FILE__,__FUNCTION__,__LINE__); err=copy_to_user(buf,kernel_buf,MIN(1024,size));/ static struct file_operations hello_drv = { .owner =THIS_MODULE, .open =hello_open, .write =hello_write, .read =hello_read, .release=hello_close, }; static int __init hello_init(void) { int err; printk("%s %s line %dn",__FILE__,__FUNCTION__,__LINE__); major=register_chrdev(0,"hello",&hello_drv);//注册结构体到内核 hello_class =class_create(THIS_MODULE,"hello_class");//创建节点类 err=PTR_ERR(hello_class); if(IS_ERR(hello_class)){ unregister_chrdev(major,"hello"); return -1; } device_create(hello_class,NULL,MKDEV(major,0),NULL,"hello"); return 0; } static void __exit hello_exit(void) { printk("%s %s line %dn",__FILE__,__FUNCTION__,__LINE__); device_destroy(hello_class,MKDEV(major,0));//注销设备注册信息 class_destroy(hello_class);//注销节点类 unregister_chrdev(major,"hello");//注销设备 } module_init(hello_init);//规范化驱动入口函数 module_exit(hello_exit);//规范化驱动出口函数 MODULE_LICENSE("GPL");//规范代码协议符合GPL
以上代码的实现就是一个简单驱动的实现模板,几乎没有什么废程序,如果以后进行其他的驱动程序的编写可以进行参考本模板。
2、接下来将main程序的实现源码贴出来:
#include#include #include #include int main(int argc,char **argv) { int fd; char buf[1024]; int len; if(argc <2) { printf("usage: %s -w n",argv[0]); printf(" %s -rn",argv[0]); return -1; } fd=open("/dev/hello",O_RDWR); if(fd==-1) { printf("can not open file /dev/hellon"); return -1; } if((0==strcmp(argv[1],"-w"))&&(argc==3)) { len=strlen(argv[2])+1; len=len <1024?len:1024; write(fd , argv[2],len); } else{ len=read(fd,buf ,1024); buf[1023]=' '; printf("app read :%sn",buf); } close(fd); }
3、接下来贴出Makefile文件的内容:
obj-m :=hello.o #//目标文件 #module-objs := file1.o file.o //当模块有多个文件组成时,添加本句 KDIR :=/usr/src/linux-headers-4.10.0-28-generic #内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径 PWD := $(shell pwd) #模块源文件路径 all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules gcc -o main main.c #编译main.c的,不喜欢可以删除独立编译main.c @rm -rf *.mod.* @rm -rf .*.cmd @rm -rf *.o @rm -rf Module.* clean: rm -rf *.ko
4、然后就是运行Makefile进行编译驱动和main程序:
5、会生成下面多出来的三个文件:
6、在该文件夹下面将**.ko文件用insmod命令挂载到驱动树上面,利用lsmod查看如下图:
7、用./main** 运行main程序:
8、输入一些字符串进去:你可能会看到下面一句话说不能打开驱动…



