Chinaunix首页 | 论坛 | 博客
  • 博客访问: 631112
  • 博文数量: 1008
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 5175
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-31 09:44
文章分类
文章存档

2012年(1008)

我的朋友

分类:

2012-08-01 11:29:08

  1. #ifndef _MEMDEV_H_
  2. #define _MEMDEV_H_

  3. #ifndef MEMDEV_MAJOR
  4. #define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/
  5. #endif

  6. #ifndef MEMDEV_NR_DEVS
  7. #define MEMDEV_NR_DEVS 2 /*设备数*/
  8. #endif

  9. #ifndef MEMDEV_SIZE
  10. #define MEMDEV_SIZE 4096
  11. #endif

  12. /*mem设备描述结构体*/
  13. struct mem_dev
  14. {
  15.   char *data;
  16.   unsigned long size;
  17.   struct semaphore sem; /* 定义信号量 */
  18. };

  19. #endif /* _MEMDEV_H_ */
  1. #include <linux/module.h>
  2. #include <linux/types.h>
  3. #include <linux/fs.h>
  4. #include <linux/errno.h>
  5. #include <linux/mm.h>
  6. #include <linux/sched.h>
  7. #include <linux/init.h>
  8. #include <linux/cdev.h>
  9. #include <asm/io.h>
  10. #include <asm/system.h>
  11. #include <asm/uaccess.h>

  12. #include "memdev.h"

  13. static int mem_major = MEMDEV_MAJOR;

  14. module_param(mem_major, int, S_IRUGO);

  15. struct mem_dev *mem_devp; /*设备结构体指针*/

  16. struct cdev cdev;

  17. /*文件打开函数*/
  18. int mem_open(struct inode *inode, struct file *filp)
  19. {
  20.     struct mem_dev *dev;
  21.     
  22.     /*获取次设备号*/
  23.     int num = MINOR(inode->i_rdev);

  24.     if (num >= MEMDEV_NR_DEVS)
  25.             return -ENODEV;
  26.     dev = &mem_devp[num];
  27.     
  28.     /*将设备描述结构指针赋值给文件私有数据指针*/
  29.     filp->private_data = dev;
  30.     
  31.     return 0;
  32. }

  33. /*文件释放函数*/
  34. int mem_release(struct inode *inode, struct file *filp)
  35. {
  36.   return 0;
  37. }

  38. /*读函数*/
  39. static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
  40. {
  41.   unsigned long p = *ppos;
  42.   unsigned int count = size;
  43.   int ret = 0;
  44.   struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/

  45.     /* 获取信号量 */
  46.   if (down_interruptible(&dev->sem))
  47.     return -ERESTARTSYS;
  48.             
  49.   /*判断读位置是否有效*/
  50.   if (p >= MEMDEV_SIZE)
  51.     return 0;
  52.   if (count > MEMDEV_SIZE - p)
  53.     count = MEMDEV_SIZE - p;

  54.   /*读数据到用户空间*/
  55.   if (copy_to_user(buf, (void*)(dev->data + p), count))
  56.   {
  57.     ret = - EFAULT;
  58.     goto out;
  59.   }
  60.   else
  61.   {
  62.     *ppos += count;
  63.     ret = count;
  64.     
  65.     printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
  66.   }
  67. out:
  68.     /* 释放信号量 */
  69.     up(&dev->sem);
  70.   return ret;
  71. }

  72. /*写函数*/
  73. static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
  74. {
  75.   unsigned long p = *ppos;
  76.   unsigned int count = size;
  77.   int ret = 0;
  78.   struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/


  79. /* 获取信号量 */
  80. if (down_interruptible(&dev->sem))
  81.    return -ERESTARTSYS;
  82.   /*分析和获取有效的写长度*/
  83.   if (p >= MEMDEV_SIZE)
  84.     return 0;
  85.   if (count > MEMDEV_SIZE - p)
  86.     count = MEMDEV_SIZE - p;
  87.     
  88.   /*从用户空间写入数据*/
  89.   if (copy_from_user(dev->data + p, buf, count)){
  90.     ret = - EFAULT;
  91.     goto out;
  92.   }
  93.   else
  94.   {
  95.     *ppos += count;
  96.     ret = count;
  97.     
  98.     printk(KERN_INFO "written %d bytes(s) from %d\n", count, p);
  99.   }
  100. out:
  101. /* 释放信号量 */
  102.   up(&dev->sem);
  103.   return ret;
  104. }

  105. /* seek文件定位函数 */
  106. static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
  107. {
  108.     loff_t newpos;

  109.     switch(whence) {
  110.       case 0: /* SEEK_SET */
  111.         newpos = offset;
  112.         break;

  113.       case 1: /* SEEK_CUR */
  114.         newpos = filp->f_pos + offset;
  115.         break;

  116.       case 2: /* SEEK_END */
  117.         newpos = MEMDEV_SIZE -1 + offset;
  118.         break;

  119.       default: /* can't happen */
  120.         return -EINVAL;
  121.     }
  122.     if ((newpos<0) || (newpos>MEMDEV_SIZE))
  123.         return -EINVAL;
  124.         
  125.     filp->f_pos = newpos;
  126.     return newpos;

  127. }

  128. /*文件操作结构体*/
  129. static const struct file_operations mem_fops =
  130. {
  131.   .owner = THIS_MODULE,
  132.   .llseek = mem_llseek,
  133.   .read = mem_read,
  134.   .write = mem_write,
  135.   .open = mem_open,
  136.   .release = mem_release,
  137. };

  138. /*设备驱动模块加载函数*/
  139. static int memdev_init(void)
  140. {
  141.   int result;
  142.   int i;

  143.   dev_t devno = MKDEV(mem_major, 0);

  144.   /* 静态申请设备号*/
  145.   if (mem_major)
  146.     result = register_chrdev_region(devno, 2, "memdev");
  147.   else /* 动态分配设备号 */
  148.   {
  149.     result = alloc_chrdev_region(&devno, 0, 2, "memdev");
  150.     mem_major = MAJOR(devno);
  151.   }
  152.   
  153.   if (result < 0)
  154.     return result;

  155.   /*初始化cdev结构*/
  156.   cdev_init(&cdev, &mem_fops);
  157.   cdev.owner = THIS_MODULE;
  158.   cdev.ops = &mem_fops;
  159.   
  160.   /* 注册字符设备 */
  161.   cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
  162.    
  163.   /* 为设备描述结构分配内存*/
  164.   mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);
  165.   if (!mem_devp) /*申请失败*/
  166.   {
  167.     result = - ENOMEM;
  168.     goto fail_malloc;
  169.   }
  170.   memset(mem_devp, 0, sizeof(struct mem_dev));
  171.   
  172.   /*为设备分配内存*/
  173.   for (i=0; i < MEMDEV_NR_DEVS; i++)
  174.   {
  175.         mem_devp[i].size = MEMDEV_SIZE;
  176.         mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
  177.         memset(mem_devp[i].data, 0, MEMDEV_SIZE);
  178.                 /* 初始化信号量 */
  179.         sema_init(&mem_devp[i].sem, 1);
  180.   }
  181.     
  182.   return 0;

  183.   fail_malloc:
  184.   unregister_chrdev_region(devno, 1);
  185.   
  186.   return result;
  187. }

  188. /*模块卸载函数*/
  189. static void memdev_exit(void)
  190. {
  191.   cdev_del(&cdev); /*注销设备*/
  192.   kfree(mem_devp); /*释放设备结构体内存*/
  193.   unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/
  194. }

  195. MODULE_AUTHOR("David Xie");
  196. MODULE_LICENSE("GPL");

  197. module_init(memdev_init);
  198. module_exit(memdev_exit);
  1. #include <stdio.h>

  2. int main()
  3. {
  4.     FILE *fp0 = NULL;
  5.     char Buf[4096];
  6.     
  7.     /*初始化Buf*/
  8.     strcpy(Buf,"Mem is char dev!");
  9.     printf("BUF: %s\n",Buf);
  10.     
  11.     /*打开设备文件*/
  12.     fp0 = fopen("/dev/memdev0","r+");
  13.     if (fp0 == NULL)
  14.     {
  15.         printf("Open Memdev0 Error!\n");
  16.         return -1;
  17.     }
  18.     
  19.     /*写入设备*/
  20.     fwrite(Buf, sizeof(Buf), 1, fp0);
  21.     
  22.     /*重新定位文件位置(思考没有该指令,会有何后果)*/
  23.     fseek(fp0,0,SEEK_SET);
  24.     
  25.     /*清除Buf*/
  26.     strcpy(Buf,"Buf is NULL!");
  27.     printf("BUF: %s\n",Buf);
  28.     
  29.     
  30.     /*读出设备*/
  31.     fread(Buf, sizeof(Buf), 1, fp0);
  32.     
  33.     /*检测结果*/
  34.     printf("BUF: %s\n",Buf);
  35.     
  36.     return 0;    

  37. }
阅读(179) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~