字符驱动模板
来源:互联网 发布:淘宝网十字绣架子 编辑:程序博客网 时间:2024/05/22 06:48
led_app.c
#include <stdio.h>#include <stdlib.h>#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/ioctl.h> //定义命令需要加此头文件#include <sys/epoll.h>//#include <poll.h>//#include <fcntl.h>//#include <stdio.h>//#include <stdlib.h>//#include <sys/epoll.h>#include <unistd.h>#include <sys/poll.h>#define LED_IO_MAGIC 'k'#define LED_READ _IO(LED_IO_MAGIC,0x10)#define LED_WRITE _IO(LED_IO_MAGIC,0x11)static intepoll_register( int epoll_fd, int fd )//epoll登记{ struct epoll_event ev; int ret, flags; /* important: make the fd non-blocking 重要:使fd为非阻塞*/ flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | O_NONBLOCK); ev.events = EPOLLIN; ev.data.fd = fd;// do { ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );//注册新的fd到epoll_fd中 // } while (ret < 0); return ret;}static intepoll_deregister( int epoll_fd, int fd )//epoll注销{ int ret;// do { ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );//从epoll_fd中删除一个fd// } while (ret < 0); return ret;}int main(void){int fd = 0;unsigned int cmd = 0;int arg = 0;fd = open("/dev/ledtest",O_RDWR);if(fd < 0){printf("open led dev error !\n");return -1;}else{printf("open led ok !\n");}/**********************************/char Buf[128];memset(Buf,0,sizeof(Buf));int fd1,fd2,fd3,fd4,fd5;fd1 = open("./txt01.txt",O_RDWR);fd2 = open("./txt02.txt",O_RDWR);fd3 = open("./txt03.txt",O_RDWR);fd4 = open("./txt04.txt",O_RDWR);fd5 = open("./txt05.txt",O_RDWR);if(fd1 < 0){printf("open txt01.txt failed !\n");return 0;}else{printf("open txt(1-5).txt success !\n");//return -1;}int epoll_fd = epoll_create(5);//创建一个epoll句柄,内核需监听2个fd epoll_register( epoll_fd, fd1 ); epoll_register( epoll_fd, fd2 ); epoll_register( epoll_fd, fd3 ); epoll_register( epoll_fd, fd4 ); epoll_register( epoll_fd, fd5 ); printf("<-----call cmd test----->\n");cmd = LED_READ;printf("cmd = 0x%x\n",cmd);if(ioctl(fd, cmd, &arg) < 0){printf("Call cmd LED_COMMAND1 fail\n"); return -1;}cmd = LED_WRITE;printf("cmd = 0x%x\n",cmd);if(ioctl(fd, cmd, &arg) < 0){printf("Call cmd LED_COMMAND2 fail\n"); return -1;}printf("led cmd test success ! \n"); /*检测结果*/read(fd, Buf, 10);printf("Read BUF: %s\n",Buf); epoll_deregister( epoll_fd, fd1 ); epoll_deregister( epoll_fd, fd2 ); epoll_deregister( epoll_fd, fd3 ); epoll_deregister( epoll_fd, fd4 ); epoll_deregister( epoll_fd, fd5 );close(fd);return 0;}
led_drv.c
#include <linux/module.h>//module#include <linux/kernel.h>//kernel#include <linux/init.h>//init#include <linux/fs.h>//filesystem#include <linux/device.h>//device#include <linux/cdev.h>//char device#include <linux/slab.h>//#include <linux/uaccess.h>//#include <linux/ioctl.h>//#include <asm-generic/ioctl.h>////#include <stdio.h>#include "led_drv.h"#define LED_IO_MAGIC 'k'#define LED_READ _IO(LED_IO_MAGIC,0x10)#define LED_WRITE _IO(LED_IO_MAGIC,0x11)#define LED_IOC_MAXNR 0x11 static dev_t dev_num;//static struct cdev cdev;static struct cdev *led_cdev = NULL;static struct class *myclass = NULL; struct device *device = NULL; static charbuf1[10];int fd1,fd2,fd3,fd4,fd5;static int led_open(struct inode *inode, struct file *file){printk("led_open have done ! \n ");/*fd1 = open("./txt01.txt",O_RDWR);fd2 = open("./txt02.txt",O_RDWR);fd3 = open("./txt03.txt",O_RDWR);fd4 = open("./txt04.txt",O_RDWR);fd5 = open("./txt05.txt",O_RDWR);if((fd1 && fd2 && fd3 && fd4 && fd5) == 0){printk("open txt(1-5).txt success !\n");return 0;}else{printk("open txt01.txt failed !\n");return -1;}int epoll_fd = epoll_create(5);//创建一个epoll句柄,内核需监听2个fd epoll_register( epoll_fd, fd1 );//登记监听类型,控制命令类消息文件 epoll_register( epoll_fd, fd2 );//登记监听类型,数据类消息文件*/return 0;}static int led_release(struct inode *inode, struct file *file){printk("led_release have done ! \n ");return 0;}/* seek文件定位函数 */static loff_t mem_llseek(struct file *filp, loff_t offset, int whence){ loff_t newpos; switch(whence) { case 0: /* SEEK_SET */ newpos = offset; break; case 1: /* SEEK_CUR */ newpos = filp->f_pos + offset; break; case 2: /* SEEK_END */ newpos = MEMDEV_SIZE -1 + offset; break; default: /* can't happen */ return -EINVAL; } if ((newpos<0) || (newpos>MEMDEV_SIZE)) return -EINVAL; filp->f_pos = newpos; return newpos;}static ssize_t led_read(struct file *file, char __user *ubuf, size_t size, loff_t *offset){struct file *fp;mm_segment_t fs;//定义一个fsloff_t pos;fp = filp_open("/home/zijixie/epoll/txt01.txt",O_RDWR|O_CREAT,0644);if(IS_ERR(fp)){printk("create file error/n");return -1;}fs=get_fs();//把当前的fs保存下来set_fs(KERNEL_DS);//设置当前fs为内核fsget_fs() == KERNEL_DS, checking is bypassed. pos=0; vfs_read(fp,charbuf1,sizeof(charbuf1),&pos); printk("read:%s/n",charbuf1);memcpy(ubuf, charbuf1, 10);filp_close(fp,NULL); set_fs(fs);//在读写文件后再恢复原先fsprintk("led_read have done ! \n ");return 0;}static ssize_t led_write(struct file *file,char __user *ubuf,size_t size,loff_t *offset){printk("led_write have done ! \n ");return 0;}static long led_ioctl(struct file *s_file, unsigned int cmd,unsigned long arg){/*检测命令的有效性*/ if (_IOC_TYPE(cmd) != LED_IO_MAGIC)//检验幻术{printk("MEMDEV_IOC_MAGIC ERROR ! \n");return -EINVAL; } if (_IOC_NR(cmd) > LED_IOC_MAXNR) //是否越界{printk("MEMDEV_IOC_MAXNR ERROR ! \n"); return -EINVAL; }switch(cmd){case LED_READ:printk("User send LED_READ.\n");break;case LED_WRITE:printk("User send LED_WRITE.\n");break;default:printk("COMMAND ERROR !!! \n");}printk("led_ioctl have done ! \n ");return 0;}static struct file_operations led_fops = {.open = led_open,.release = led_release,.read = led_read,.write = led_write,.owner = THIS_MODULE,.llseek = mem_llseek,//用户调用.unlocked_ioctl = led_ioctl,};static int led_init(void){int ret;led_cdev = cdev_alloc();if(led_cdev == NULL){printk("LED_cdev_alloc error\n");return -ENOMEM;}cdev_init(led_cdev, &led_fops);//step1ret = alloc_chrdev_region(&dev_num, 0, 1, "ledtest");//step2设备号名字if(ret != 0){printk("fail to alloc_chrdev_region ! \n ");goto err_alloc_chrdev_region;}ret = cdev_add(led_cdev, dev_num, 1);if(ret != 0){printk("fail to add dev_num to cdev ! \n ");goto err_cdev_add;}myclass = class_create(THIS_MODULE, "ledtest");if(IS_ERR(myclass)){printk("fail to class_create. \n");ret = PTR_ERR(myclass);goto err_class_create;}device = device_create(myclass, NULL, dev_num, NULL, "ledtest");///dev/ledtestif(IS_ERR(device)){printk("fail to deice_create \n");ret = PTR_ERR(device);goto err_device_create;}printk("ledtest driver registered ! \n");return 0;err_device_create:class_destroy(myclass);err_class_create:cdev_del(led_cdev);err_cdev_add:unregister_chrdev_region(dev_num, 1);err_alloc_chrdev_region:return ret;}static int led_exit(void){device_destroy(myclass, dev_num);//1class_destroy(myclass);//2cdev_del(led_cdev);//3unregister_chrdev_region(dev_num, 1);//4return 0 ;}MODULE_LICENSE("GPL");MODULE_AUTHOR("FU HANG");module_init(led_init);module_exit(led_exit);
led_drv.h
#ifndef _LED_DRV_H_#define _LED_DRV_H_#ifndef MEMDEV_SIZE#define MEMDEV_SIZE 4096#endif/*mem设备描述结构体*/struct mem_dev { char *data; //数据指针 unsigned long size; //尺寸 wait_queue_head_t inq; //等待队列};#endif /* _LED_DRV_H_ */
阅读全文