Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316128
  • 博文数量: 101
  • 博客积分: 2428
  • 博客等级: 大尉
  • 技术积分: 1050
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-24 13:16
文章分类

全部博文(101)

文章存档

2012年(3)

2011年(90)

2010年(8)

分类: LINUX

2011-04-27 10:49:19

一个间的字符设备驱动是比较简单,并没有考虑太多的问题。。。。
套框架很容易去编写的。。。。。。
  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. #define GLOBALMEM_SIZE 0x100//全局内存大小4KB;
  13. #define MEM_CLEAR 0x1//清零全局内存
  14. #define GLOBALMEM_MAJOR 254 //预设的globalmem的主设备号
  15. static int globalmem_major=GLOBALMEM_MAJOR;
  16. struct globalmem_dev
  17. {
  18.  struct cdev cdev;//cdev结构体
  19.  unsigned char mem[GLOBALMEM_SIZE]; //全局内存
  20. };
  21. struct globalmem_dev *globalmem_devp;//设备结构体实例
  22. int globalmem_open(struct inode *inode,struct file *filp)
  23. {
  24.  //将设备结构体指针赋值给文件私有数据指针
  25.  filp->private_data=globalmem_devp;
  26.  return 0;
  27. }
  28. int globalmem_release(struct inode *inode,struct file *filp)
  29. {
  30.  return 0;
  31. }
  32. static ssize_t globalmem_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
  33. {
  34.  unsigned long p=*ppos;
  35.  unsigned int count=size;
  36.  int ret=0;
  37.  struct globalmem_dev *dev=filp->private_data;
  38.  //分析和获取有效的读长度
  39.  if(p>=GLOBALMEM_SIZE)
  40.   return count? -ENXIO:0;
  41.  if(count>GLOBALMEM_SIZE-p)
  42.   count=GLOBALMEM_SIZE-p;
  43.  //内核空间到用户空间
  44.  if (copy_to_user(buf,(void*)(dev->mem+p),count))
  45.  {
  46.   ret=-EFAULT;
  47.  }
  48.  else
  49.  {
  50.   *ppos+=count;
  51.   ret=count;
  52.   printk(KERN_INFO "read %d bytes from %d \n",count,p);
  53.  }
  54.  return ret;
  55. }
  56. static ssize_t globalmem_write(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
  57. {
  58.  unsigned long p=*ppos;
  59.  unsigned int count=size;
  60.  int ret=0;
  61.  struct globalmem_dev *dev=filp->private_data;//获得设备结构体指针
  62.  //分析和获取有效的读长度
  63.  if(p>=GLOBALMEM_SIZE)
  64.   return count? -ENXIO:0;
  65.  if(count>GLOBALMEM_SIZE-p)
  66.   count=GLOBALMEM_SIZE-p;
  67.  //用户空间到内核空间
  68.  if (copy_from_user(dev->mem+p,buf,count))
  69.  {
  70.   ret=-EFAULT;
  71.  }
  72.  else
  73.  {
  74.   *ppos+=count;
  75.   ret=count;
  76.   
  77.   printk(KERN_INFO "read %d bytes from %d \n",count,p);
  78.  }
  79.  return ret;

  80. }
  81. static loff_t globalmem_llseek(struct file *filp,loff_t offset,int orig)
  82. {
  83.  loff_t ret;
  84.  switch(orig)
  85.  {
  86.  case 0://从开头开始偏移
  87.   if (offset<0)
  88.   {
  89.    ret=-EINVAL;
  90.    break;
  91.   }
  92.   if ((unsigned int)offset>GLOBALMEM_SIZE)
  93.   {
  94.    ret=-EINVAL;
  95.    break;
  96.   }
  97.   filp->f_pos=(unsigned int)offset;
  98.   ret=filp->f_pos;
  99.   break;
  100.   case 1:
  101.    if ((filp->f_pos+offset)>GLOBALMEM_SIZE)
  102.    {
  103.     ret=-EINVAL;
  104.     break;
  105.    }
  106.    if ((filp->f_pos+offset)<0)
  107.    {
  108.     ret=-EINVAL;
  109.     break;
  110.    }
  111.    filp->f_pos+=offset;
  112.    ret=filp->f_pos;
  113.    break;
  114.  default:
  115.   ret=-EINVAL;
  116.  }
  117.  return ret;
  118. }
  119. static int globalmem_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)
  120. {
  121.  struct globalmem_dev *dev=filp->private_data;//获得设备结构体指针
  122.  switch (cmd)
  123.  {
  124.  case MEM_CLEAR:
  125.   memset(dev->mem,0,GLOBALMEM_SIZE);
  126.   printk(KERN_INFO "globalmem is set to zero\n");
  127.   break;
  128.  default:
  129.   return -EINVAL;//其他的命令不支持
  130.  }
  131.  return 0;
  132. }

  133. static const struct file_operations globalmem_fops=
  134. {
  135.  .owner=THIS_MODULE,
  136.  .llseek=globalmem_llseek,
  137.  .read=globalmem_read,
  138.  .write=globalmem_write,
  139.  .ioctl=globalmem_ioctl,
  140.  .open=globalmem_open,
  141.  .release=globalmem_release,
  142. };
  143. /* 初始化并添加cdev结构体*/
  144. static void globalmem_setup_cdev(struct globalmem_dev *dev,int index)
  145. {
  146.  int err,devno=MKDEV(globalmem_major,0);

  147.  cdev_init(&dev->cdev,&globalmem_fops);
  148.  dev->cdev.owner=THIS_MODULE;
  149.  dev->cdev.ops=&globalmem_fops;
  150.  err=cdev_add(&dev->cdev,devno,1);
  151.  if (err)
  152.  {
  153.   printk(KERN_NOTICE"Error %d adding globalmem",err);
  154.  }
  155. }
  156. int globalmem_init(void)
  157. {
  158.  int result;
  159.  dev_t devno=MKDEV(globalmem_major,0);//生产设备号
  160.  // 申请字符设备驱动区域
  161.  if (globalmem_major)
  162.  {
  163.   result=register_chrdev_region(devno,1,"globalmem");
  164.  }
  165.  else
  166.  {
  167.   result=alloc_chrdev_region(&devno,0,1,"globalmem");
  168.   globalmem_major=MAJOR(devno);
  169.  }
  170.  if (result<0)
  171.  {
  172.   return result;
  173.  }
  174.  //动态申请设备结构体内存
  175.  globalmem_devp=kmalloc(sizeof(struct globalmem_dev),GFP_KERNEL);
  176.  if (!globalmem_devp)
  177.  {
  178.   result=-ENOMEM;
  179.   goto fail_malloc;
  180.  }
  181.  memset(globalmem_devp,0,sizeof(struct globalmem_dev));

  182.  globalmem_setup_cdev(globalmem_devp,0);
  183.  return 0;
  184. fail_malloc:unregister_chrdev_region(devno,1);
  185.    return result;
  186. }
  187. void globalmem_exit(void)
  188. {
  189.  cdev_del(&globalmem_devp->cdev);//删除cdev结构
  190.  kfree(globalmem_devp);
  191.  unregister_chrdev_region(MKDEV(globalmem_major,0),1);//注销设备区域
  192. }
  193. MODULE_LICENSE("GPL");
  194. module_param(globalmem_major,int,S_IRUGO);
  195. module_init(globalmem_init);
  196. module_exit(globalmem_exit);

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