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);  
View Code

 

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
View Code

 

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 }
View Code

 

有错误请留言

posted @ 2017-11-22 19:54  一枚小苦工  阅读(347)  评论(0编辑  收藏  举报