【0004】字符设备驱动之globalmem_v0.1

  1 /************************************
  2 *filename    :_001_globalmem.c
  3 *func        :a character program
  4 *bookpages:code_list 6.17 (page:164)
  5 *versions    :v0.1
  6 ************************************/
  7 #include <linux/module.h>
  8 #include <linux/fs.h>
  9 #include <linux/init.h>
 10 #include <linux/cdev.h>
 11 #include <linux/slab.h>
 12 #include <linux/uaccess.h>
 13 
 14 #define MEMSIZE 100
 15 #define GLOBALMEM_MAJOR 230
 16 #define MEM_CLEAR 0x1
 17 
 18 int  globalmem_major = GLOBALMEM_MAJOR;
 19 struct globalmem_cdev{
 20     struct cdev;
 21     char mem[MEMSIZE];
 22 
 23 };
 24 
 25 struct globalmem_cdev globalmem;
 26 
 27 
 28 static int globalmem_open (struct inode *inode, struct file *filep)
 29 {    
 30     filep->private_data = globalmem;
 31     return 0;
 32 
 33 }
 34 
 35 static int globalmem_release (struct inode * inode, struct file * filep)
 36 {
 37     return 0;
 38 }
 39 
 40 static long globalmem_unlocked_ioctl (struct file * filep, unsigned int cmd, unsigned long arg)
 41 {
 42     struct globalmem_cdev *dev = filep->private_data;
 43 
 44     switch(cmd){
 45     case MEM_CLEAR:
 46         memset(dev->mem, 0 , MEMSIZE );
 47         printk(KERN_INFO "globalmem is set to zero\n");
 48         break;
 49     default:
 50         return -EINVAL;
 51 
 52 
 53     }
 54 
 55     return 0;
 56 }
 57 
 58 static ssize_t globalmem_read (struct file * filep, char __user * buf, size_t size, loff_t * ppos)
 59 {
 60     unsigned long p = *ppos;
 61     unsigned int count = size;
 62     int ret = 0;
 63      struct globalmem_cdev *dev = filep->private_data;
 64 
 65      if (p >= MEMSIZE)
 66          return 0;
 67 
 68      if (count > MEMSIZE - p)
 69          count = MEMSIZE -p;
 70 
 71      if (copy_to_user(buf, dev->mem + p, count)){
 72         ret = -EFAULT;
 73      } else {
 74         *ppos += count;
 75         ret = count;
 76 
 77         printk(KERN_INFO " read %u bytes(s) form %lu\n    ", count ,p);
 78      }
 79      
 80     return ret;
 81 }
 82 static ssize_t globalmem_write (struct file *filep, const char __user  buf *, size_t size, loff_t *ppos)
 83 {
 84     unsigned long p = *ppos;
 85     unsigned int count = size;
 86     int ret = 0;
 87     struct globalmem_cdev  *dev = filep->private_data;
 88 
 89     if ( p >= MEMSIZE)
 90         return 0;
 91 
 92     if (count > MEMSIZE - p)
 93         count = MEMSIZE -p;
 94 
 95     if (copy_from_user(dev->mem + p, buf, count)){
 96         ret = -EFAULT;
 97     } else {
 98         *ppos += count;
 99         ret = count;
100 
101         printk(KERN_INFO "written %u bytes(s) from %lu \n", count ,p);
102     }
103     
104     return ret;
105 }
106 
107 static loff_t globalmem_llseek (struct file *filep, loff_t offset, int orig)
108 {
109     loff_t ret =0;
110     switch(orig){
111     case 0:
112         if (offset < 0){
113             ret = -EINVAL;
114             break;
115         }
116 
117         if ((unsigned int ) offset > MEMSIZE){
118             ret = -EINVAL;
119             break;
120         }
121 
122         filep->f_ops = (unsigned int )offset;
123         ret = filep->f_ops;
124         break;
125     case 1:
126         if ((filep->f_ops + offset) > MEMSIZE){
127             ret = -EINVAL;
128             break;
129         }
130 
131         if ((filep->f_pos + offset) < 0){
132             ret = -EINVAL;
133             break;
134         }
135 
136         filep->f_ops += offset;
137         ret = filep->f_ops;
138         break;
139 
140     default:
141             ret = -EINVAL;
142             break;
143     }
144     
145     return ret;
146 }
147 
148 static int globalmem_mmap (struct file *, struct vm_area_struct *)
149 {
150     return 0;
151 }
152 
153 static void globalmem_setup_cdev(struct globalmem_cdev *dev,int index)
154 {
155     int err,devno = MKDEV(globalmem_major,index);
156     cdev_init(dev->cdev,&globalmem_ops);
157     dev->cdev.owner    = THIS_MODULE;
158     err = cdev_add(&dev,devno,1);
159     if (err)
160         printk(KERN_NOTICE "ERR %d adding globalmem %d",err,index);
161 }
162 
163 
164 
165 
166 
167 static struct file_operations globalmem_ops = {
168     .owner    = THIS_MODULE,
169     .read    = globalmem_read,
170     .write    = globalmem_write,
171     .llseek    = globalmem_llseek,
172     .unlocked_ioctl    =globalmem_unlocked_ioctl,
173     .open    = globalmem_open,
174     .release    = globalmem_release,
175 };
176 
177 
178 
179 
180 
181 
182 
183 static int __init globalmem_init(void)
184 {
185     int ret;
186     dev_t devno = MKDEV(globalmem_major,0);
187     if (globalmem_major){
188         ret = register_chrdev_region(devno,1,"globalmem");
189     }else{
190         ret = alloc_chrdev_region(&devno,0,1,"globalmem");
191         globalmem_major = MAJOR(devno);
192     }
193 
194     if (ret < 0)
195         return ret;
196 
197     globalmem = kzalloc(sizeof(struct globalmem_cdev),GFP_KERNEL);
198     if (!globalmem){
199         ret = -ENOMEM;
200         goto fail_alloc;
201     }
202 
203     globalmem_setup_cdev(globalmem,0);
204     return 0;
205     
206 fail_alloc:
207     unregister_chrdev_region(devno,1);
208     return ret;
209 }
210 
211 static void __exit globalmem_exit(void)
212 {
213     cdev_del(&globalmem->cdev);
214     kfree(globalmem);
215     unregister_chrdev_region(MKDEV(globalmem_major,0),1)
216 
217 }
218 
219 module_init(globalmem_init);
220 module_exit(globalmem_exit);
221 
222 MODULE_LICENSE("GPL v2");
223 MODULE_AUTHOR("OzTaking");
224 MODULE_DESCRIPTION("a character program");

 

posted @ 2017-04-27 17:24  OzTaking  阅读(284)  评论(0)    收藏  举报