cdev设备 字符设备驱动例子
#include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/uaccess.h> #include <linux/fcntl.h> #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/signal.h> #include <asm-generic/siginfo.h> #define NAME "cdev_demo" #define COUNT 3 #define KBUFSIZE 64 #define GPIOA28 28 dev_t dev_no; struct cdev *cdevp = NULL; struct class *cls = NULL; struct device *devp = NULL; char Kbuf[KBUFSIZE] = {'\0'}; int Kbufcount = 0; int irq_a28 = 0; struct fasync_struct *fasync; irqreturn_t key_irq_handler(int irqno, void *args) { kill_fasync(&fasync,SIGIO,POLL_IN); printk(KERN_DEBUG "[%s-%s-%d]:Interrupt...\n",\ __FILE__,__func__,__LINE__); return IRQ_HANDLED; } static int demo_open(struct inode *inode, struct file *filp) { printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",__FILE__,__func__,__LINE__); return 0; } static int demo_release(struct inode *inode, struct file *filp) { printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",\ __FILE__,__func__,__LINE__); return 0; } ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *pos) { if(size > Kbufcount){ size = Kbufcount; } if(copy_to_user(buf, Kbuf, size)){ printk(KERN_ERR "[%s-%s-%d]: copy_to_user failed...\n",\ __FILE__,__func__,__LINE__); return -EAGAIN; } Kbufcount = 0; printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",\ __FILE__,__func__,__LINE__); return size; } ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *pos) { if(size > KBUFSIZE){ size = KBUFSIZE; } if(copy_from_user(Kbuf,buf, size)){ printk(KERN_ERR "[%s-%s-%d]: copy_from_user failed...\n",\ __FILE__,__func__,__LINE__); return -EAGAIN; } Kbufcount = size; printk(KERN_DEBUG "[%s-%s-%d]: Kbuf:%s...\n",\ __FILE__,__func__,__LINE__,Kbuf); return size; } int demo_fasync(int fd, struct file *filp, int on) { return fasync_helper(fd, filp, on , &fasync); } struct file_operations fops = { .owner = THIS_MODULE, .open = demo_open, .release = demo_release, .read = demo_read, .write = demo_write, .fasync = demo_fasync, }; static int __init demo_init(void) { int ret = 0 ,i = 0; //0、申请设备号 ret = alloc_chrdev_region(&dev_no, 0 , COUNT , NAME); if(ret < 0){ printk(KERN_ERR "[%s-%s-%d]:alloc_chrdev_region failed...\n",\ __FILE__,__func__,__LINE__); goto err0; } printk(KERN_DEBUG "[%s-%s-%d]:devno->major:%d--minor:%d--...\n",\ __FILE__,__func__,__LINE__,MAJOR(dev_no),MINOR(dev_no)); //1、分配cdev结构体 cdevp = cdev_alloc(); if(cdevp == NULL){ printk(KERN_ERR "[%s-%s-%d]:cdev_alloc failed...\n",\ __FILE__,__func__,__LINE__); ret = -ENOMEM; goto err1; } //2、初始化cdev结构体 cdev_init(cdevp, &fops); //3、添加到内核中,由内核统一管理 ret = cdev_add(cdevp, dev_no, COUNT); if(ret < 0){ goto err1; } //4、class create cls = class_create(THIS_MODULE,NAME); if(IS_ERR(cls)){ printk(KERN_ERR "[%s-%s-%d]:class_create...\n",\ __FILE__,__func__,__LINE__); ret = PTR_ERR(cls); goto err2; } //5、device create for(i = 0 ; i < COUNT ; i++){ devp = device_create(cls, NULL , MKDEV(MAJOR(dev_no),i) , NULL, "%s%d",NAME,i); if(IS_ERR(devp)){ printk(KERN_ERR "[%s-%s-%d]:device_create[%d]...\n",\ __FILE__,__func__,__LINE__,i); ret = PTR_ERR(devp); goto err3; } } irq_a28 = gpio_to_irq(GPIOA28); if(irq_a28 < 0){ printk(KERN_ERR "[%s-%s-%d]:call failed...\n",\ __FILE__,__func__,__LINE__); ret = irq_a28; goto err3; } ret = request_irq(irq_a28,key_irq_handler,IRQF_TRIGGER_FALLING,"gpioa28_key", NULL); if(ret < 0){ printk(KERN_ERR "[%s-%s-%d]:call failed...\n",\ __FILE__,__func__,__LINE__); goto err3; } return 0; err3: for(--i;i>=0;i--){ device_destroy(cls,MKDEV(MAJOR(dev_no),i)); } class_destroy(cls); err2: cdev_del(cdevp); err1: unregister_chrdev_region(dev_no, COUNT); err0: return ret; } static void __exit demo_exit(void) { int i = 0; free_irq(irq_a28, NULL); for(i=0;i < COUNT;i++){ device_destroy(cls,MKDEV(MAJOR(dev_no),i)); } class_destroy(cls); //cdev从内核中删除 cdev_del(cdevp); //设备号资源释放 unregister_chrdev_region(dev_no, COUNT); } module_init(demo_init); module_exit(demo_exit); MODULE_LICENSE("GPL");
KDIR:=/home/edu/SAMBA_SHARE/BK2101/Driver/03_kernel/kernel-3.4.39 #KDIR:= /lib/modules/`uname -r`/build PWD := $(shell pwd) obj-m += demo.o modules: make -C $(KDIR) M=$(PWD) modules #cp *.ko ~/rootfs/home clean: make -C $(KDIR) M=$(PWD) clean
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> char buf[32]; fd_set r_fds; void sig_callback(int sig) { printf("sig callback...\n"); } int main(int argc, const char *argv[]) { int ret = 0; signal(SIGIO, sig_callback); int fd = open("/dev/cdev_demo0",O_RDWR); if(fd < 0){ perror("open"); return -1; } fcntl(fd,F_SETOWN,getpid()); fcntl(fd,F_SETFL,fcntl(fd,F_GETFL)|FASYNC); while(1){ } //close(fd); return 0; }