现在对linux设备驱动还没有什么认识,跟着书上敲了一个字符驱动,这里把代码贴一下.
测试环境是 Ubuntu 16.04 64bit
驱动程序:
#include <linux/fs.h> #include <linux/module.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/uaccess.h> #define CDEVDEMO_MAJOR 0 #define BUFFER_SIZE 512 static int cdevdemo_major = CDEVDEMO_MAJOR; static char msgbuff[BUFFER_SIZE]; void cdevdemo_exit(void); int cdevdemo_init(void); MODULE_LICENSE("Dual BSD/GPL"); module_param(cdevdemo_major,int,S_IRUGO);
//注册初始化方法 module_init(cdevdemo_init);
//注册退出方法 module_exit(cdevdemo_exit); struct cdev *my_cdev; ssize_t cdev_write(struct file *, const char __user *, size_t, loff_t *); ssize_t cdev_read (struct file *, char __user *, size_t, loff_t *); int cdev_open (struct inode *,struct file *); int cdev_release (struct inode *,struct file *); struct file_operations my_fops = { .owner = THIS_MODULE, .open = cdev_open, .release = cdev_release, .read = cdev_read, .write = cdev_write, }; void init_cdev(void) { int ret; my_cdev = cdev_alloc(); my_cdev->owner = THIS_MODULE; my_cdev->ops = &my_fops; //添加字符设备 ret = cdev_add(my_cdev,MKDEV(cdevdemo_major,),); ) { printk(KERN_NOTICE "=== cdev_add fail"); } printk(KERN_NOTICE "=== init_cdev finish"); } int __init cdevdemo_init(void) { int ret; dev_t devno; printk(KERN_NOTICE "=== cdevdemo_init 0"); devno = MKDEV(cdevdemo_major,); if(cdevdemo_major) { printk(KERN_NOTICE "=== cdevdemo_init try register"); ret = register_chrdev_region(devno,,"cdevdemo"); }else { printk(KERN_NOTICE "=== cdevdemo_init auto register"); ret = alloc_chrdev_region(&devno,,,"cdevdemo"); cdevdemo_major = MAJOR(devno); } ) { printk(KERN_NOTICE "=== cdevdemo_init register fail"); return ret; } init_cdev(); printk(KERN_NOTICE "=== cdevdemo_init finish"); ; } void __exit cdevdemo_exit(void) { printk (KERN_NOTICE "=== cdevdemo_exit"); //去除字符设备 cdev_del(my_cdev); unregister_chrdev_region(MKDEV(cdevdemo_major,),); } ssize_t cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp) { int ret; printk(KERN_NOTICE "=== cdev_write"); ret = copy_from_user(msgbuff,buf,count%BUFFER_SIZE); ) { printk(KERN_NOTICE "=== cdev_write copy_from_user fail %d",ret); return -EFAULT; } msgbuff[count] = '-'; msgbuff[count+] = '-'; msgbuff[count+] = 'k'; msgbuff[count+] = 'e'; msgbuff[count+] = 'r'; msgbuff[count+] = 'n'; msgbuff[count+] = 'e'; msgbuff[count+] = 'l'; msgbuff[count+] = '\0'; printk(KERN_NOTICE "--- cdev_write : %s",msgbuff); return count%BUFFER_SIZE; } ssize_t cdev_read (struct file *filp, char __user *buf, size_t count, loff_t *offp) { int ret; printk(KERN_NOTICE "=== cdev_read"); ret = copy_to_user(buf,msgbuff,count%BUFFER_SIZE); ) { printk(KERN_NOTICE "=== cdev_read copy_to_user fail %d",ret); return -EFAULT; } printk(KERN_NOTICE "--- cdev_read :%s",msgbuff); return count%BUFFER_SIZE; } int cdev_open (struct inode *inode,struct file *filp) { printk(KERN_NOTICE "=== cdev_open"); ; } int cdev_release (struct inode *inode,struct file *filp) { printk(KERN_NOTICE "=== cdev_release"); ; }
Makefile
ifneq ($(KERNELRELEASE),) mymodule-objs := cdev obj-m := cdev.o else PWD := $(shell pwd) KVER ?= $(shell uname -r) KDIR := /lib/modules/$(KVER)/build all: $(MAKE) -C $(KDIR) M=$(PWD) clean: rm -rf *.cmd *.o *.mod.c *.ko .tmp_versions endif
install.sh
#!/bin/bash module="cdev" device="cdev" name="cdevdemo" insmod $module.ko ] then exit fi major=$(awk "{if(\$2==\"$name\"){print \$1}}" /proc/devices) /dev/$device
uninstall.sh
#!/bin/bash module="cdev" device="cdev" file="/dev/$device" if [ -e $file ] then rm -rf /dev/$device echo 'rm device' fi echo 'rm module' /sbin/rmmod $module
测试程序
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> int main(void) { int fd,ret; ] = "hello I'm from user"; ] = {}; fd = open("/dev/cdev",O_RDWR); ) { puts("open fail"); ; } ret = write(fd,buff,strlen(buff)); printf("write ret :%d\n",ret); ret = read(fd,rbuff,); printf("read ret :%d\n%s",ret,rbuff); ; }
运行结果:
write ret : read ret : hello I'm from user--kernel