简单的一个字符设备驱动

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>/*包含内存管理两个核心函数*/
#include "memdev.h"

static int mem_major=MEM_MAJOR;

struct mem_dev *mem_devp; /*指向设备结构体的指针*/

/*文件打开函数*/
int mem_open(struct inode *inode,struct file *filp)
{
 filp->private_data=mem_devp;/*将设备结构体指针赋值给文件私有数据指针*/
 return 0;
}

/*文件释放函数*/
int mem_release(struct inode *inode,struct file *filp)
{
 return 0;
}

/*ioctl设备控制函数*/
static  int mem_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)
{
 struct mem_dev *dev=filp->private_data;/*获得设备结构体指针*/
 switch(cmd){
 case MEM_CLEAR:
  memset(dev->mem,0,MEM_SIZE);
  printk(KERN_INFO "mem is set to zero!\n");
  break;
 default:
  return -EINVAL;
    }
 return 0;
}

/*读函数*/
static ssize_t mem_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
{
 unsigned long p=*ppos;
 unsigned int count=size;
 int ret=0;
 struct mem_dev *dev=filp->private_data;/*获得设备结构体指针*/
 
 /*分析和获取有效的写长度*/
 if(p>=MEM_SIZE)
  return 0;
 if(count>MEM_SIZE-p)
 count=MEM_SIZE-p;
 
 /*内核空间--用户空间*/
 if(copy_to_user(buf,(void*)(dev->mem+p),count))/*完全复制成功返回0*/
 {
  ret=-EFAULT;
 }
 else
 {
  *ppos+=count;
  ret=count;
  printk(KERN_INFO "read %u bytes(s) from %lu\n",count,p);
 }
 return ret;
}

/*写函数*/
static ssize_t mem_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
{
 unsigned long p=*ppos;
 unsigned int count=size;
 int ret=0;
 struct mem_dev *dev=filp->private_data;/*获得设备结构体指针*/
 
 /*分析和获取有效的写长度*/
 if(p>=MEM_SIZE)
  return 0;
 if(count>MEM_SIZE-p)
  count=MEM_SIZE-p;
 
 /*用户空间--内核空间*/
 if(copy_from_user(dev->mem+p,buf,count))
  ret=-EFAULT;
 else{
  *ppos+=count;
  ret=count;
  printk(KERN_INFO "written %u bytes from %lu\n",count,p);
 }
 return ret;
}

/*seek文件定位函数*/
static loff_t mem_llseek(struct file *filp,loff_t offset,int orig)
{
 loff_t ret=0;
 switch(orig)
 {
  case 0:/*相对文件开始位置偏移*/
   if(offset<0)
   {
    ret=-EINVAL;
    break;
   }
   if((unsigned int)offset>MEM_SIZE)
   {
    ret=-EINVAL;
    break;
   }
  case 1:/*相对文件当前位置偏移*/
   if((filp->f_pos+offset)>MEM_SIZE)
   {
    ret=-EINVAL;
    break;
   }
   if((filp->f_pos+offset)<0)
   {
    ret=-EINVAL;
    break;
   }
   filp->f_pos+=offset;
   ret=filp->f_pos;
   break;
  default:
   ret=-EINVAL;
   break;
 }
 return ret;

}

/*文件操作结构体,对应的系统调用,实现赋值给函数指针*/
static const struct file_operations mem_fops =
{
  .owner = THIS_MODULE,
  .llseek = mem_llseek,
  .read = mem_read,
  .write = mem_write,
  .open = mem_open,
  .release = mem_release,
};

/*初始化并注册cdev*/
static void mem_setup_cdev(struct mem_dev *dev,int index)
{
 int err ,devno=MKDEV(mem_major,index);
 cdev_init(&dev->cdev,&mem_fops);/*建立cdev和file_operations之间的连接*/
 dev->cdev.owner=THIS_MODULE;
 err=cdev_add(&dev->cdev,devno,1);/*向系统添加一个cdev结构体*/
 if(err)
  printk(KERN_NOTICE"erro %d adding mem %d",err,index);
}

/*设备驱动模块加载函数*/
static int memdev_init(void)
{
 int result;
 dev_t devno=MKDEV(mem_major,0);
 /*申请设备号*/
 if(mem_major)
  result=register_chrdev_region(devno,1,"mem");
 else{/*动态申请设备号*/
  result=alloc_chrdev_region(&devno,0,1,"mem");
  mem_major=MAJOR(devno);
 }
 if(result<0)
  return result;
 
 /*分配cdev为设备结构体分配内存*/
 mem_devp=kmalloc(sizeof(struct mem_dev),GFP_KERNEL);
 {
  if(!mem_devp){/*申请失败*/
   result= -ENOMEM;
   goto fail_malloc;
  }
 }
 memset(mem_devp,0,sizeof(struct mem_dev));
 /*初始化并注册cdev*/
 mem_setup_cdev(mem_devp,0);
 return 0;
fail_malloc:
 unregister_chrdev_region(devno,1);
 return result;
}

/*设备模块卸载函数*/
static memdev_exit(void)
{
 cdev_del(&mem_devp->cdev);/*注销cdev*/
 kfree(mem_devp);/*释放设备结构体内存*/
 unregister_chrdev_region(MKDEV(mem_major,0),1);/*释放设备号*/
}

MODULE_AUTHOR("wanghy");
MODULE_LICENSE("GPL");
module_param(mem_major,int ,S_IRUGO);
module_init(memdev_init);
module_exit(memdev_exit);

 

#define MEM_SIZE 0x1000  /*全局内存最大4KB*/
#define MEM_CLEAR 0x1  /*清零全局内存*/
#define MEM_MAJOR 250  /*预设的主设备号*/

/*mem设备结构体*/
struct mem_dev{
 struct cdev cdev;  /*cdev结构体*/
 unsigned char mem[MEM_SIZE]; /*全局内存*/
};

 makefile编写

ifneq ($(KERNELRELEASE),)

obj-m := memdev.o

else
 
KDIR := /home/whyzl/linux-2.6.37.4
all:
 make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*

endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值