6410虚拟字符设备读写测试程序

View Code
  1 #include <linux/init.h>
  2 #include <linux/kernel.h>
  3 #include <linux/module.h>
  4 #include <linux/types.h>
  5 #include <linux/fs.h>
  6 #include <linux/errno.h>
  7 #include <linux/mm.h>
  8 #include <linux/sched.h>
  9 #include <linux/cdev.h>
 10 #include <linux/slab.h>
 11 #include <asm/io.h>
 12 #include <asm/uaccess.h>
 13 #include <asm/system.h>
 14 #include "memdev.h"//在头文件中定义了MEMDEV_SIZE=256,MEMDEV_NR=2,MEM_MAJOR=251;
 15 
 16 
 17 int    mem_major = MEM_MAJOR;
 18 
 19 module_param(mem_major, int , S_IWUSR);//用mem_major作为内核参数,随时可以改变设备号
 20 
 21 struct    cdev    cdev;
 22 struct    memdev    *memdevp;
 23 dev_t    dev_no;
 24 
 25 /*函数打开时调用*/
 26 int mem_open(struct inode *inode, struct file *file)
 27 {
 28     struct    memdev    *memdev;
 29     int    i = MINOR(inode->i_rdev);
 30     if(i > MEMDEV_NR)
 31         return -EFAULT;
 32     memdev    = &memdevp[i];
 33 
 34     file->private_data = memdev;//将设备指针保存在private_data里面,方便以后读写时取用;
 35     return 0;
 36     
 37 }
 38 
 39 int mem_release(struct inode *inode, struct file *file)
 40 {
 41     return 0;
 42 }
 43 /*读文件时调用该函数*/
 44 ssize_t    mem_read(struct file *file, char __user *buffer, size_t size, loff_t *pos)
 45 {
 46     struct memdev    *memdev;
 47     int    count = size;
 48     int    p = *pos;
 49     int    ret = 0;
 50 
 51     if(p > MEMDEV_SIZE)
 52         return    -EFAULT;
 53     if(count > MEMDEV_SIZE - p)
 54         count = MEMDEV_SIZE -p;
 55     
 56     memdev = file->private_data;
 57     ret = copy_to_user(buffer, memdev->data + p, count);//在内核空间中不能直接使用用户空间的指针。
 58     
 59     if(ret)
 60         return -ENOMEM;
 61     else{
 62         *pos += count;
 63         ret = count;
 64     }
 65 
 66     return ret;
 67 }
 68 /*写文件的时候调用该函数*/
 69 ssize_t mem_write(struct file *file, const char __user *buffer, size_t size, loff_t *pos)
 70 {
 71     struct memdev    *memdev;
 72     int    count = size;
 73     int    p = *pos;
 74     int ret = 0;
 75 
 76     if(p > MEMDEV_SIZE)
 77         return    -EFAULT;
 78     if(count > MEMDEV_SIZE - p)
 79         count = MEMDEV_SIZE - p;
 80 
 81     memdev    = file->private_data;//取出打开时,保存在private_data中的memdev指针;
 82     ret = copy_from_user(memdev->data + p , buffer, count);//用户空间指针,不能直接在内核空间使用;
 83     
 84     if(ret)
 85         return -ENOMEM;
 86     else{
 87         *pos += count;//更新文件读写指针位置;
 88         ret = count;
 89     }
 90 
 91     return ret;
 92 }
 93 
 94 loff_t    mem_llseek(struct file *file, loff_t off, int whence)
 95 {
 96     loff_t    newpos=0;
 97 
 98     switch(whence){
 99         case 0://seek_set
100             newpos = off;
101             break;
102         case 1://seek_cur
103             newpos = file->f_pos + off; //file_pos是文件原来的读写指针位置;
104             break;
105         case 2://seek_end
106             newpos = MEMDEV_SIZE -1 + off;
107             break;
108         default:
109             return -EFAULT;
110     }
111 
112     file->f_pos = newpos;//更新文件读写指针位置;
113     return newpos;
114 }
115 
116 /*定义一个mem_fops变量,并初始化它*/
117 struct file_operations  mem_fops = {
118     .owner = THIS_MODULE,//此语句必须;
119     .open = mem_open,
120     .llseek = mem_llseek,
121     .read = mem_read,
122     .write = mem_write,
123     .release = mem_release,
124 };
125 
126 
127 static int __init memdev_init(void)
128 {
129     dev_no = MKDEV(mem_major, 0);
130     int    result = 0;
131     int    i=0;
132 
133     if(mem_major){
134         result = register_chrdev_region(dev_no, MEMDEV_NR ,"memdev0");//当mem_major大于0的时候,使用静态分配设备号方式;    
135     }else{
136         result = alloc_chrdev_region(&dev_no, 0 ,MEMDEV_NR,"memdev0");//当mem_major为0的时候,选用动态分配设备号的方式
137         mem_major = MAJOR(dev_no);
138     }
139 
140     if(result != 0)
141         return -ENOMEM;
142 
143     cdev_init(&cdev, &mem_fops);//使用mem_fops初始化设备结构cdev;
144     cdev.owner = THIS_MODULE;//制定该设备结构的拥有者为THIS_MODULE;
145 
146     cdev_add(&cdev,dev_no,MEMDEV_NR);//使用设备号,以及设备结构,向内核注册设备;
147 
148     memdevp    = kmalloc(MEMDEV_NR * sizeof(struct memdev), GFP_KERNEL);//为虚拟的设备结构分配空间
149     if(!memdevp)
150         goto fail_malloc;
151     memset(memdevp , 0, MEMDEV_NR * sizeof(struct memdev));//初始化为0;
152 
153     for(i = 0; i < MEMDEV_NR; i++){
154         memdevp[i].size = MEMDEV_SIZE;
155         memdevp[i].data = kmalloc(MEMDEV_SIZE ,GFP_KERNEL);//为虚拟设备结构中的数据部分分配空间;
156         if(!(memdevp[i].data)){
157             goto    fail_malloc;
158         }
159         memset(memdevp[i].data , 0, MEMDEV_SIZE);
160     }
161     
162     return 0;
163 fail_malloc:
164     unregister_chrdev_region(dev_no, MEMDEV_NR);//当出错的时候,释放设备号;
165     return -ENOMEM;
166 }
167 
168 static void __exit memdev_exit(void)
169 {    
170     int i=0;
171     for(i=0;i < MEMDEV_NR; i++)
172         kfree(memdevp[i].data);//释放数据部分所占用的空间
173     kfree(memdevp);//释放设备结构所占用的空间;
174     unregister_chrdev_region(dev_no,MEMDEV_NR);//注销该设备号;
175     cdev_del(&cdev);//删除设备结构...
176 }
177 
178 MODULE_LICENSE("GPL");
179 MODULE_AUTHOR("rzchong");
180 
181 module_init(memdev_init);
182 module_exit(memdev_exit);

 

posted on 2012-07-01 11:00  小虫儿  阅读(204)  评论(0编辑  收藏  举报