linux设备驱动程序 字符设备驱动程序

先留个联系方式 ,有一起学习驱动程序的加qq295699450

字符设备驱动:

这篇比较恼火。加载成功,但是读不出来数据,有知道怎么回事的,留个言,一起讨论下:

数据结构

struct scull_mem{
      void *data;
      struct scull_mem *next;
};


 

struct scull_dev{
      struct cdev cdev;
      unsigned long size;
      struct scull_mem *data;
}*dev;


整个驱动程序代码如下:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/uaccess.h>

#define BUFFERSIZE 4096

ssize_t scull_read (struct file *filp,char __user* buf,size_t count,loff_t *offset);
ssize_t scull_write(struct file *filp,const char __user*buf,size_t count,loff_t *offset);
int scull_open(struct inode *inode,struct file *filp);
int scull_release(struct inode *inode,struct file *filp);

struct scull_mem{
      void *data;
      struct scull_mem *next;
};
struct scull_dev{
      struct cdev cdev;
      unsigned long size;
      struct scull_mem *data;
}*dev;
dev_t scull_dev_num=0;
int major,minor;
int cdev_registered=0;

void scull_trim(void)
{
      struct scull_mem *ptr,*tmp;
      for(ptr=dev->data;ptr!=NULL;ptr=tmp){
          tmp=ptr->next;
          if(ptr->data!=NULL){
              kfree(ptr->data);
          }
          kfree(ptr);
      }
      dev->data=NULL;
      dev->size=0;
}
int scull_open(struct inode *inode,struct file *filp)
{
      printk(KERN_ALERT "Scull is opened!\n");
      if((filp->f_flags&O_ACCMODE)==O_WRONLY)
          scull_trim();
      return 0;
}
int scull_release(struct inode *inode,struct file *filp)
{
      printk(KERN_ALERT "Scull is released!\n");
      return 0;
}
struct scull_mem * scull_follow(int item)
{
      struct scull_mem *tmp,*ptr=NULL;
      int times=item;
      for(tmp=dev->data;item-->=0;tmp=tmp->next){
          if(tmp==NULL){
              if((tmp=(struct scull_mem *)kmalloc(sizeof(struct scull_mem),GFP_KERNEL))==NULL)
                  return NULL;
              tmp->next=NULL;
              if((tmp->data=kmalloc(BUFFERSIZE,GFP_KERNEL))==NULL){
                  return NULL;
              }
              memset(tmp->data,0,BUFFERSIZE);
              if(times==0){
                  dev->data=tmp;
                  times++;
              }
          }
          ptr=tmp;
      }
      return ptr;
}
ssize_t scull_read (struct file *filp,char __user* buf,size_t count,loff_t *offset)
{
      ssize_t retval=0;
      size_t item,pos;
      struct scull_mem *ptr;
      item=*offset / BUFFERSIZE;
      pos=*offset % BUFFERSIZE;
      ptr=scull_follow(item);
      if(ptr==NULL||ptr->data==NULL){
          goto out;
      }
      if(*offset+count>dev->size)
          count=dev->size-*offset;
      count=count > (BUFFERSIZE-pos)? (BUFFERSIZE-pos):count;
      if(copy_to_user(buf,ptr->data+pos,count)){
          retval=-EFAULT;
          goto out;
      }
      *offset+=count;
      retval=count;   
out:
      return retval;
}
ssize_t scull_write(struct file *filp,const char __user*buf,size_t count,loff_t *offset)
{
      ssize_t retval=0;
      size_t item,pos;
      struct scull_mem *ptr;
      item=*offset / BUFFERSIZE;
      pos=*offset % BUFFERSIZE;
      ptr=scull_follow(item);
      if(ptr==NULL||ptr->data==NULL){
          goto out;
      }
      count=count > (BUFFERSIZE-pos)? (BUFFERSIZE-pos):count;
      if(copy_from_user(ptr->data+pos,buf,count)){
          retval=-EFAULT;
          goto out;
      }
      *offset+=count;
      retval=count;
      dev->size+=count;
out:
      return retval;

}
loff_t scull_llseek(struct file *filp,loff_t offset,int start)
{
      loff_t new;
      switch(start)
      {
          case 0:
              new=offset;
              break;
          case 1:
              new=filp->f_pos+offset;
              break;
          case 2:
              new=dev->size+offset;
              break;
          default:
              return -EINVAL;
      }
      if(new<0) return -EINVAL;
      filp->f_pos=new;
      return new;
}
struct file_operations scull_ops={
      .owner=THIS_MODULE,
      .open=scull_open,
      .read=scull_read,
      .write=scull_write,
      .release=scull_release,
      .llseek=scull_llseek,
      .unlocked_ioctl=NULL,
};
void cleanup(void)
{
      if(cdev_registered)
          cdev_del(&dev->cdev);
      if(dev!=NULL){
          scull_trim();
          kfree(dev);
      }
      if(scull_dev_num!=0)
          unregister_chrdev_region(scull_dev_num,1);
}
static int __init scull_init(void)
{
      int retval=0;
/*first,requset device number*/
      if((retval=alloc_chrdev_region(&scull_dev_num,0,1,"scull_jakilll"))<0)
          goto fail;
      major=MAJOR(scull_dev_num);
      minor=MINOR(scull_dev_num);
/*then alloc device structure*/
      if((dev=kmalloc(sizeof(struct scull_dev),GFP_KERNEL))==NULL){
          retval=-ENOMEM;
          goto fail;
      }
      dev->size=0;
      dev->data=NULL;
/*finally,register cdev*/
      cdev_init(&dev->cdev,&scull_ops);
      dev->cdev.owner=THIS_MODULE;
      dev->cdev.ops=&scull_ops;
      if((retval=cdev_add(&dev->cdev,scull_dev_num,1))<0)
          goto fail;
      cdev_registered=1;
      printk(KERN_ALERT "Scull inited ok!\n");
      return retval;
fail:
      cleanup();
      return retval;
}
static void __exit scull_exit(void)
{
      cleanup();
      printk(KERN_ALERT "Scull cleanuped!\n");
}
module_init(scull_init);
module_exit(scull_exit); 
MODULE_LICENSE("GPL");

初始化:

根据设备名使用alloc_chrdev_region()申请设备号,给scull_dev分配内存,使用cdev_init()初始化cdev设备,并初始化dev里面的各个成员,接着cdev_add()讲dev中的cdev添加到内核里面,初始化结束

卸载:

先从内核闪出sucll_dev->cdev结构,然后kfree  scull_dev结构,最后使用unregister_chrdev_region()卸载设备

就是如上流程,读写程序随便写

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值