LINUX设备驱动程序阅读同步代码

  1 #include<linux/module.h>
  2 #include<linux/init.h>
  3 #include<linux/list.h>
  4 #include<linux/fs.h>
  5 #include<linux/types.h>
  6 #include<linux/kdev_t.h>
  7 #include<linux/cdev.h>
  8 #include<linux/errno.h>
  9 #include<linux/slab.h>
 10 #include<asm/uaccess.h>
 11 #include<asm/ioctl.h>
 12 #include<linux/ioctl.h>
 13 #include<linux/semaphore.h>
 14 #include"scull.h"
 15 
 16 #define SCULL_QUANTUM 4000
 17 #define SCULL_QSET 1000
 18 #define NR_DEVS 1
 19 
 20 
 21 
 22 MODULE_LICENSE("Dual BSD/GPL");
 23 
 24 //************************************************
 25 //下边这些是该设备模块的全局数据区
 26 int scull_quantum = SCULL_QUANTUM;
 27 int scull_qset = SCULL_QSET;
 28 
 29 int scull_major=0;
 30 int scull_minor=0;
 31 unsigned int scull_nr_devs=NR_DEVS;
 32 
 33 
 34 struct scull_qset
 35 {
 36     void **data;
 37     struct scull_qset *next;
 38 };
 39 
 40 struct scull_dev
 41 {
 42     struct scull_qset *data;
 43     int quantum;
 44     int qset;
 45     unsigned long size;
 46     struct semaphore sem; //在此加入了信号量,
 47     struct cdev cdev;
 48 } scull_dev[NR_DEVS];
 49 
 50 //**************************************************
 51 //供底层调用的内部函数
 52 //**************************************************
 53 static int scull_trim(struct scull_dev *dev)
 54 {
 55     struct scull_qset *next,*dptr;
 56     
 57     int i;
 58     if( dev->data == NULL )
 59         goto out;
 60     for( next=dev->data; next; )
 61     {
 62         dptr=next;
 63         next=next->next;
 64         if( dptr->data )
 65         {
 66             for(i=0;i<dev->qset;i++)
 67             {
 68                 kfree(dptr->data[i]);    
 69             }
 70             kfree(dptr->data);
 71         }
 72         kfree(dptr);        
 73     }
 74     dev->data = NULL;
 75 out:
 76     
 77     dev->size =0;
 78     dev->quantum = scull_quantum;
 79     dev->qset = scull_qset;
 80     sema_init(&dev->sem,1);
 81     return 0;
 82 }
 83 
 84 
 85 static struct scull_qset *scull_follow(struct scull_dev *dev,int index)
 86 {
 87     int i;
 88     struct scull_qset *dptr=NULL,*next=dev->data;
 89     printk(KERN_INFO "dev->data=%p\n",dev->data);
 90     for(i=0;i<=index;i++)
 91     {
 92         dptr = next;
 93         if( !dptr )
 94         {
 95             dptr=kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
 96             if( !dptr )
 97                 return NULL;
 98             dptr->next=NULL;
 99             dptr->data=NULL;
100             if( i==0 )
101                 dev->data = dptr;
102         }
103         
104         next = dptr->next;
105     }
106     printk(KERN_INFO "after follow:the dev->data=%p\n",dev->data);
107     return dptr;
108 }
109 //**************************************************************
110 // 赋值给struct file_operations结构的函数指针成员的函数
111 //*************************************************************
112 ssize_t scull_read(struct file *filp,char __user *buf,size_t len,loff_t *f_pos)
113 {
114     struct scull_dev *dev = filp->private_data;
115     int node_index,qset_index,quantum_index;
116     struct scull_qset *dptr;
117     int retval=0;
118     if( down_interruptible(&dev->sem) )
119         return -ERESTARTSYS;
120     if( dev->size <= *f_pos )
121         goto out;
122  
123     node_index = (long)(*f_pos) /( dev->quantum * dev->qset );
124     qset_index = ( (long)(*f_pos) / dev->quantum )% dev->qset ;
125     quantum_index = (long)(*f_pos) % dev->quantum;
126 
127     if( dev->size < *f_pos+len )
128         len = dev->size-*f_pos;
129     if( quantum_index + len > dev->quantum )
130         len = dev->quantum-quantum_index;
131 
132     
133     dptr = scull_follow(dev,node_index);
134     if( !dptr || !dptr->data || !dptr->data[qset_index] )
135         goto out;
136     if( copy_to_user(buf,dptr->data[qset_index]+quantum_index,len) )
137     {
138         retval = -EFAULT;
139         goto out;
140     }
141     retval = len;
142     *f_pos = *f_pos+len;    
143 out:
144     up(&dev->sem);
145     return retval;    
146 }
147 
148 ssize_t scull_write(struct file *filp,const char __user *buf,size_t len,loff_t *f_pos)
149 {
150     struct scull_dev *dev = filp->private_data;
151     int node_index,qset_index,quantum_index;
152     struct scull_qset *dptr=NULL;
153     int retval=0;
154     if( down_interruptible(&dev->sem) )
155         return -ERESTARTSYS;
156     node_index = (long)(*f_pos) /( dev->quantum * dev->qset );
157     qset_index = ( (long)(*f_pos) / dev->quantum )% dev->qset ;
158     quantum_index = (long)(*f_pos) % dev->quantum;
159     printk(KERN_INFO "here is in scull_write before scull_follow\n");
160     dptr = scull_follow(dev,node_index);
161     printk(KERN_INFO "here is in scull_write after scull_follow\n");
162     if( dptr )
163     {
164         if( !dptr->data )
165         {
166             dptr->data = kmalloc(sizeof(void*)*dev->qset,GFP_KERNEL);
167             if( !dptr->data )
168                 goto out;
169             memset(dptr->data,0,dev->qset*sizeof(void*));
170         }
171         if( !dptr->data[qset_index] )
172         {
173             dptr->data[qset_index] = kmalloc(dev->quantum,GFP_KERNEL);
174             if( !dptr->data[qset_index] )
175                 goto out;
176         }
177         if( quantum_index + len > dev->quantum )
178             len = dev->quantum-quantum_index;
179         if( copy_from_user(dptr->data[qset_index]+quantum_index,buf,len) )
180         {
181             retval = -EFAULT;
182             goto out;
183         }
184     
185         retval = len;
186         *f_pos = *f_pos+len;
187         if( dev->size < *f_pos )
188             dev->size += *f_pos;
189     }
190     printk(KERN_INFO "here is in scull_write before out label\n");
191 out:
192     up(&dev->sem);
193     return retval;       
194 }
195 
196 int scull_open(struct inode * inode,struct file *filp)
197 {
198     struct scull_dev *dev;
199     dev = container_of(inode->i_cdev,struct scull_dev,cdev);
200     filp->private_data = dev;
201     if( ( filp->f_flags & O_ACCMODE ) == O_WRONLY )
202         scull_trim(dev);
203     printk(KERN_INFO "here is end of scull_open\n");
204     return 0;
205 }
206 
207 long scull_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
208 {
209     long retval=0,tmp;
210     switch(cmd)
211     {
212         case SCULL_IOCRESET :
213             scull_quantum = SCULL_QUANTUM;
214             scull_qset = SCULL_QSET;
215             break;
216         case SCULL_IOCSQUANTUM :
217             if( !capable(CAP_SYS_ADMIN))
218                 return -EPERM;
219             retval = __get_user(scull_quantum,(int __user*)arg);
220             break;
221 
222         case SCULL_IOCTQUANTUM :
223             if(!capable(CAP_SYS_ADMIN))
224                 return -EPERM;
225             scull_quantum = arg;
226             break;
227 
228         case SCULL_IOCGQUANTUM :
229             retval = __put_user(scull_quantum,(int __user*)arg);
230             break;
231         case SCULL_IOCQQUANTUM :
232             return scull_quantum;
233 
234         case SCULL_IOCXQUANTUM :
235             if(!capable(CAP_SYS_ADMIN))
236                 return -EPERM;
237             tmp = scull_quantum;
238             retval = __get_user(scull_quantum,(int __user*)arg);
239             if(retval == 0 )
240                 retval = __put_user(tmp,(int __user*)arg);
241             break;
242         case SCULL_IOCHQUANTUM :
243             if( !capable(CAP_SYS_ADMIN))
244                 return -EPERM;
245             tmp = scull_quantum;
246             scull_quantum=arg;
247             return tmp;
248         default: return -ENOTTY;
249                 
250     }
251     return retval;
252 }
253 
254 
255 struct file_operations scull_fops=
256 {
257     .owner = THIS_MODULE,
258     .read = scull_read,
259     .write = scull_write,    
260     .open = scull_open,
261     .unlocked_ioctl = scull_ioctl,
262 };
263 //*************************************************************
264 //以下是模块初始化和模块退出代码
265 //************************************************************
266 
267 
268 int get_major(void)
269 {
270     dev_t dev;
271     int result;
272     if( scull_major )
273     {
274         dev = MKDEV(scull_major,scull_minor);
275         result=register_chrdev_region(dev,scull_nr_devs,"scull");
276     }
277     else
278     {
279         result=alloc_chrdev_region(&dev,scull_minor,scull_nr_devs,"scull");
280         scull_major = MAJOR(dev);
281     }
282     if( result<0 )
283     {
284         printk(KERN_INFO "scull: can't get major %d\n",scull_major);
285         return result;
286     }
287     return result;
288 }
289 
290 
291 static void scull_setup_cdev(struct scull_dev *dev,int index)
292 {
293     int err,devno = MKDEV(scull_major,scull_minor+index);
294     cdev_init(&dev->cdev,&scull_fops);
295     dev->cdev.owner = THIS_MODULE;
296     err = cdev_add(&dev->cdev,devno,scull_nr_devs);
297     if( err )
298         printk(KERN_INFO "error %d adding scull %d",err,index);
299 }
300 
301 static int scull_init(void)
302 {
303     int i;
304     printk(KERN_INFO "scull_init \n");
305     get_major();
306     for(i=0;i<scull_nr_devs;i++)
307     {
308         scull_setup_cdev(scull_dev+i,i);
309         if( scull_trim(scull_dev+i) )
310             return -1;
311     }
312     return 0;
313 }
314 
315 static void scull_exit(void)
316 {
317     int i;
318     printk(KERN_INFO "scull_exit\n");
319     for(i=0;i<scull_nr_devs;i++)
320     {
321         cdev_del(&((scull_dev+i)->cdev));
322     }
323     unregister_chrdev_region(MKDEV(scull_major,scull_minor),scull_nr_devs); 
324 
325 }
326 
327 module_init(scull_init);
328 module_exit(scull_exit);
329 
330 //**************************************************************************

以上代码是边看书边敲出来的,综合书上的理论和部分示例代码写的整个模块代码,对于在学LINUX设备驱动程序的朋友们如果正在看《LINUX设备驱动程序》这本书的话,可以参考一下这些代码。

以下还有一个“scull.h"头文件的内容:

#ifndef __SCULL_H_
#define __SCULL_H_

#include<linux/errno.h>
#include<asm/ioctl.h>
#include<linux/ioctl.h>


#define SCULL_IOC_MAGIC 'k'
#define SCULL_IOCRESET _IO(SCULL_IOC_MAGIC,0)

#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC,1,int)
#define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC,2,int)

#define SCULL_IOCTQUANTUM _IO(SCULL_IOC_MAGIC,3)
#define SCULL_IOCTQSET _IO(SCULL_IOC_MAGIC,4)
#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC,5,int)
#define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC,6,int) 
#define SCULL_IOCQQUANTUM _IO(SCULL_IOC_MAGIC,7)
#define SCULL_IOCQQSET _IO(SCULL_IOC_MAGIC,8)
#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC,9,int)
#define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10,int)
#define SCULL_IOCHQUANTUM _IO(SCULL_IOC_MAGIC,11)
#define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC,12)
#define SCULL_IOC_MAXNR 14

#endif

欢迎朋友指正。

posted @ 2013-02-19 15:59  printf_NSLog  阅读(274)  评论(0编辑  收藏  举报