Linux 字符驱动
char_driver.c
1 #include <linux/module.h> 2 #include <linux/slab.h> //kmalloc 3 #include <linux/cdev.h> //cdev 4 #include <linux/fs.h> //register_chrdev_region 5 #include <linux/device.h> //class_create 6 #include <asm/uaccess.h> //copy_from_user copy_to_user 7 #include <linux/timer.h> //timer 8 #include <linux/sched.h> //jiffies 9 #include <linux/poll.h> 10 #include "char_driver.h" 11 12 13 static int val = 200; 14 static struct timer_list char_driver_timer; 15 16 static DECLARE_WAIT_QUEUE_HEAD(char_driver_queue); 17 18 19 20 static P_CHAR_DRIVER pDriver = NULL; 21 static unsigned char value = 0; 22 static unsigned char ready = 0; 23 24 static void char_driver_timer_func(unsigned long arg) 25 { 26 printk(KERN_INFO"Kernel Timer\n"); 27 memset(pDriver->data,value,DATASIZE); 28 ready = 1; 29 value++; 30 mod_timer(&char_driver_timer,jiffies + (2 * HZ)); 31 32 //防止应用层crtl+c结束进程,内核定时器无法停止 33 if(value >= 60) 34 { 35 printk(KERN_INFO"del timer\r\n"); 36 del_timer(&char_driver_timer); 37 } 38 } 39 40 static void _init_timer(unsigned long data,unsigned long expires) 41 { 42 init_timer(&char_driver_timer); 43 44 //超时时间,定时间隔 45 char_driver_timer.expires = jiffies + (expires * HZ); 46 char_driver_timer.data = data; 47 char_driver_timer.function = char_driver_timer_func; 48 } 49 50 51 52 53 54 //OPEN 55 static ssize_t char_driver_open(struct inode *inode, struct file *filp) 56 { 57 int minor = 0; 58 minor = MINOR(inode->i_rdev); 59 if(minor<0 || minor>TOTALDEVICE) 60 { 61 printk(KERN_ERR"open failed!Wrong minor\n"); 62 } 63 filp->private_data = pDriver->data; 64 printk(KERN_NOTICE"open\n"); 65 return 0; 66 } 67 68 //release 69 static ssize_t char_driver_release(struct inode *inode, struct file *filp) 70 { 71 printk(KERN_NOTICE"release\n"); 72 73 return 0; 74 } 75 76 //read 77 static ssize_t char_driver_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) 78 { 79 printk(KERN_NOTICE"read\n"); 80 copy_to_user(buf,filp->private_data,count); 81 return 0; 82 } 83 84 85 //write 86 static ssize_t char_driver_write (struct file *filp, const char __user *buf, size_t count,loff_t *ppos) 87 { 88 printk(KERN_NOTICE"write\n"); 89 copy_from_user(filp->private_data,buf,count); 90 return 0; 91 } 92 93 //poll 94 static unsigned int char_driver_poll (struct file *filp, struct poll_table_struct *wait) 95 { 96 int mask = 0; 97 printk(KERN_INFO"poll\n"); 98 99 poll_wait(filp,&char_driver_queue,wait); 100 101 if(1 == ready) 102 { 103 ready = 0; 104 mask |= POLLIN |POLLRDNORM; 105 } 106 107 return mask; 108 } 109 //mmap 110 static int char_driver_mmap (struct file *filp, struct vm_area_struct *p) 111 { 112 printk(KERN_NOTICE"mmap\n"); 113 return 0; 114 } 115 static long char_driver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 116 { 117 char magic = 0; 118 //char * p = (char*)arg; 119 int * p2 = (int*)arg; 120 printk(KERN_NOTICE"ioctl\n"); 121 magic = _IOC_TYPE(cmd); 122 if(CHAR_DRIVER_MAGIC != magic) 123 { 124 printk(KERN_ERR"error magic\n"); 125 return -EINVAL; 126 } 127 else 128 { 129 switch(cmd) 130 { 131 //数据清零 132 case CHAR_DRIVER_CLEAR: 133 memset(filp->private_data,0,DATASIZE); 134 break; 135 136 //将测试VAL返回 137 case CHAR_DRIVER_GET_VAL: 138 *p2 = val; 139 break; 140 //设置val 141 case CHAR_DRIVER_SET_VAL: 142 val = arg; 143 break; 144 // 145 case CHAR_DRIVER_SET_MEM: 146 memset(filp->private_data,arg,DATASIZE); 147 break; 148 149 //开启定时器,从参数传来的数开始自增1 150 case CHAR_DRIVER_START: 151 152 //定时器2s间隔 153 _init_timer(arg,2); 154 value = (unsigned char)arg; 155 add_timer(&char_driver_timer); 156 break; 157 158 //停止定时器 159 case CHAR_DRIVER_STOP: 160 printk(KERN_INFO"del timer\n"); 161 del_timer(&char_driver_timer); 162 break; 163 default: 164 break; 165 166 } 167 } 168 169 return 0; 170 } 171 172 static const struct file_operations char_driver_fops = 173 { 174 .owner = THIS_MODULE, 175 .open = char_driver_open, 176 .release = char_driver_release, 177 .read = char_driver_read, 178 .write = char_driver_write, 179 .poll = char_driver_poll, 180 .mmap = char_driver_mmap, 181 .unlocked_ioctl = char_driver_ioctl, 182 }; 183 184 185 int char_driver_init(void) 186 { 187 unsigned char i = 0; 188 int ret = 0; 189 190 191 printk(KERN_NOTICE "char_driver_init\n"); 192 193 //申请内核空间内存 194 pDriver = (P_CHAR_DRIVER)kzalloc(sizeof(CHAR_DRIVER),GFP_KERNEL); 195 196 if(NULL == pDriver) 197 { 198 printk(KERN_NOTICE"Kmalloc Error\n"); 199 return -ENOMEM; 200 } 201 pDriver->majornum = MAJORNUM; 202 203 //构建设备号 204 pDriver->DeviceNum = MKDEV(pDriver->majornum,0); 205 206 //静态注册设备 207 ret = register_chrdev_region(pDriver->DeviceNum, TOTALDEVICE, DEVICENAME); 208 209 //静态注册失败,动态注册 210 if(ret < 0) 211 { 212 ret = alloc_chrdev_region(&pDriver->DeviceNum,0,TOTALDEVICE, DEVICENAME); 213 if(ret < 0) 214 { 215 printk(KERN_ERR"chrdev_region failed!\n"); 216 unregister_chrdev_region(pDriver->DeviceNum,TOTALDEVICE); 217 return -ENOMEM; 218 } 219 220 //动态注册设备后,更新主设备号 221 pDriver->majornum = MAJOR(pDriver->DeviceNum); 222 } 223 224 //注册完毕,初始化设备 225 cdev_init(&pDriver->cdev, &char_driver_fops); 226 pDriver->cdev.owner = THIS_MODULE; 227 pDriver->cdev.ops = &char_driver_fops; 228 229 //初始化完毕,添加设备 230 ret = cdev_add(&pDriver->cdev,pDriver->DeviceNum,TOTALDEVICE); 231 if(ret < 0 ) 232 { 233 printk(KERN_ERR"cdev_add failed!\n"); 234 unregister_chrdev_region(pDriver->DeviceNum,TOTALDEVICE); 235 return -ENOMEM; 236 } 237 238 //添加设备成功,在/sys下产生系统文件接口 239 pDriver->chardriver_class = class_create(THIS_MODULE, DEVICENAME); 240 241 //创建class失败,注销和删除 242 if(NULL == pDriver->chardriver_class) 243 { 244 printk(KERN_ERR"class_create failed!\n"); 245 unregister_chrdev_region(pDriver->DeviceNum,TOTALDEVICE); 246 class_destroy(pDriver->chardriver_class); 247 return -ENOMEM; 248 } 249 250 //在dev下产生设备文件 251 for(i=0;i<TOTALDEVICE;i++) 252 { 253 device_create(pDriver->chardriver_class, NULL, MKDEV(pDriver->majornum, i),DEVICENAME,"xym%d",i); 254 } 255 256 _init_timer(5,5); 257 258 return 0; 259 } 260 261 void char_driver_exit(void) 262 { 263 unsigned char i = 0; 264 265 266 //注销 267 unregister_chrdev_region(pDriver->DeviceNum,TOTALDEVICE); 268 269 //删除设备 270 cdev_del(&pDriver->cdev); 271 272 //删除/dev下设备文件 273 for(i=0;i<TOTALDEVICE;i++) 274 { 275 device_destroy(pDriver->chardriver_class,MKDEV(pDriver->majornum,i)); 276 } 277 278 //删除class 279 class_destroy(pDriver->chardriver_class); 280 281 //销毁内核内存 282 if(NULL != pDriver) 283 { 284 kfree(pDriver); 285 } 286 287 del_timer(&char_driver_timer); 288 289 printk(KERN_NOTICE "char_driver_exit\n"); 290 } 291 292 293 MODULE_AUTHOR("XinYuMing"); 294 MODULE_ALIAS ("XYM'sDriver"); 295 MODULE_DESCRIPTION("A Char Driver for Test"); 296 MODULE_LICENSE("Dual BSD/GPL"); 297 MODULE_VERSION("V1.0"); 298 299 module_init(char_driver_init); 300 module_exit(char_driver_exit);
char_driver.h
1 #ifndef __CHAR_DRIVER__ 2 #define __CHAR_DRIVER__ 3 4 #include <linux/ioctl.h> 5 6 7 8 #define MAJORNUM 255 //主设备号 9 #define TOTALDEVICE 4 //设备数量 10 #define DEVICENAME "MYCHAR" //设备名称 11 #define DATASIZE 10 12 13 14 #define CHAR_DRIVER_MAGIC 'o' 15 #define CHAR_DRIVER_GET_VAL _IOR(CHAR_DRIVER_MAGIC,0,int) //返回val的值 16 #define CHAR_DRIVER_SET_VAL _IOW(CHAR_DRIVER_MAGIC,1,int) 17 #define CHAR_DRIVER_CLEAR _IO(CHAR_DRIVER_MAGIC,2) 18 #define CHAR_DRIVER_SET_MEM _IOW(CHAR_DRIVER_MAGIC,3,char) 19 #define CHAR_DRIVER_START _IOW(CHAR_DRIVER_MAGIC,4,unsigned long) 20 #define CHAR_DRIVER_STOP _IO(CHAR_DRIVER_MAGIC,5) 21 22 23 struct _CHAR_DRIVER 24 { 25 int majornum; //主设备号 26 struct cdev cdev; //字符设备结构 27 struct class *chardriver_class; //设备类 28 dev_t DeviceNum; //设备号 29 30 unsigned char data[DATASIZE]; 31 }; 32 33 typedef struct _CHAR_DRIVER CHAR_DRIVER; 34 typedef struct _CHAR_DRIVER* P_CHAR_DRIVER; 35 36 37 38 39 #endif
char_test_app.c
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <fcntl.h> 4 #include <string.h> 5 #include <sys/ioctl.h> 6 #include <signal.h> 7 #include <stdlib.h> 8 9 #define DEVICEPATH0 "/dev/xym0" 10 #define DEVICEPATH1 "/dev/xym1" 11 12 13 14 15 #define CHAR_DRIVER_MAGIC 'o' 16 #define CHAR_DRIVER_GET_VAL _IOR(CHAR_DRIVER_MAGIC,0,int) //返回val的值 17 #define CHAR_DRIVER_SET_VAL _IOW(CHAR_DRIVER_MAGIC,1,int) 18 #define CHAR_DRIVER_CLEAR _IO(CHAR_DRIVER_MAGIC,2) 19 #define CHAR_DRIVER_SET_MEM _IOW(CHAR_DRIVER_MAGIC,3,char) 20 #define CHAR_DRIVER_START _IOW(CHAR_DRIVER_MAGIC,4,unsigned long) 21 #define CHAR_DRIVER_STOP _IO(CHAR_DRIVER_MAGIC,5) 22 #define DATASIZE (unsigned char)10 23 24 int fd0 = 0; 25 26 //捕获crtl c,删除内核定时器,退出程序 27 void signal_func(int sig) 28 { 29 30 printf("sig ----------- %d\n",sig); 31 ioctl(fd0,CHAR_DRIVER_STOP); 32 exit(0); 33 34 } 35 36 int main(void) 37 { 38 39 int val = 0; 40 char c = 'a'; 41 int i=0; 42 fd_set fds; 43 struct timeval timeout; 44 unsigned char buf[DATASIZE] = {0}; 45 46 signal(SIGINT, signal_func); 47 48 49 fd0 = open(DEVICEPATH0,O_RDWR); 50 if(fd0 < 0) 51 { 52 printf("Open file fd0 faild!\n"); 53 } 54 55 //读取驱动的中的某个值 56 ioctl(fd0,CHAR_DRIVER_GET_VAL,&val); 57 printf("val --- %d\n",val); 58 59 //设置驱动中的某个值 60 ioctl(fd0,CHAR_DRIVER_SET_VAL,300); 61 ioctl(fd0,CHAR_DRIVER_GET_VAL,&val); 62 printf("val --- %d\n",val); 63 64 //驱动中原始数据 65 read(fd0,buf,sizeof(buf)); 66 for(i=0;i<sizeof(buf);i++) 67 { 68 printf("%d ",buf[i]); 69 } 70 printf("\n"); 71 72 //写成11 73 memset(buf,0x11,sizeof(buf)); 74 write(fd0,buf,sizeof(buf)); 75 read(fd0,buf,sizeof(buf)); 76 for(i=0;i<sizeof(buf);i++) 77 { 78 printf("%d ",buf[i]); 79 } 80 printf("\n"); 81 82 //清空 83 ioctl(fd0,CHAR_DRIVER_CLEAR); 84 read(fd0,buf,sizeof(buf)); 85 for(i=0;i<sizeof(buf);i++) 86 { 87 printf("%d ",buf[i]); 88 } 89 printf("\n"); 90 91 //格式化 92 ioctl(fd0,CHAR_DRIVER_SET_MEM,c); 93 read(fd0,buf,sizeof(buf)); 94 for(i=0;i<sizeof(buf);i++) 95 { 96 printf("%d ",buf[i]); 97 } 98 printf("\n"); 99 100 //从55开始2s增加1 101 ioctl(fd0,CHAR_DRIVER_START,55); 102 while(1) 103 { 104 FD_ZERO(&fds); 105 FD_SET(fd0, &fds); 106 timeout.tv_sec = 0; 107 timeout.tv_usec = 1000000; 108 switch (select(fd0 + 1, &fds, NULL, NULL, &timeout)) 109 { 110 case -1: 111 printf("wrong\n"); 112 break; 113 case 0: 114 printf("time out\n"); 115 break; 116 default: 117 printf("I get it\n"); 118 read(fd0,buf,sizeof(buf)); 119 for(i=0;i<sizeof(buf);i++) 120 { 121 printf("%d ",buf[i]); 122 } 123 printf("\n"); 124 break; 125 } 126 } 127 128 return 0; 129 }
有错误请留言