一个简单的字符设备驱动 (二)

2014-11-24 03:25:56 · 作者: · 浏览: 1
atic int
__init memdev_init(void)
{
int result;
int err;
int i;

/*申请设备号*/
dev_t devno = MKDEV(mem_major,0);

if(mem_major)
/*注意静态申请的dev_t参数和动态dev_t参数的区别*/
result = register_chrdev_region(devno,MEMDEV_NUM,"memdev");
else
{
result = alloc_chrdev_region(&devno,0,MEMDEV_NUM,"memdev");
mem_major = MAJOR(devno);
}
if(result<0)
{
printk("can not get major devno:%d\n",mem_major);
return result;
}

/*注册设备驱动*/
cdev_init(&mem_cdev,&mem_fops);/*初始化cdev结构*/

mem_cdev.owner = THIS_MODULE;

/*注册字符驱动设备*/
err = cdev_add(&mem_cdev,MKDEV(mem_major,0),MEMDEV_NUM);
if(err)
printk("addcdev faild,err is %d\n",err);

/*分配设备内存*/
mem_devp = kmalloc(MEMDEV_NUM*(sizeof(struct mem_dev)),GFP_KERNEL);
if(!mem_devp)
{
result = -ENOMEM;
goto fail_malloc;
}

memset(mem_devp,0,MEMDEV_NUM*(sizeof(struct mem_dev)));

for(i=0;i {
mem_devp[i].size = MEMDEV_SIZE;
mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);
memset(mem_devp[i].data,0,MEMDEV_SIZE);
// init_MUTEX(&mem_devp[i].sem); /*初始化互斥锁*/
sema_init(&mem_devp[i].sem,1);
}

return result;

fail_malloc:
unregister_chrdev_region(MKDEV(mem_major,0),MEMDEV_NUM);
return result;
}


/*设备驱动模型卸载函数*/
static void
memdev_exit(void)
{
cdev_del(&mem_cdev);
/*注意释放的设备号个数一定要和申请的设备号个数一致,否则会导致设备号资源流失*/
unregister_chrdev_region(MKDEV(mem_major,0),MEMDEV_NUM);
printk("memdev_exit\n");
}

module_init(memdev_init);
module_exit(memdev_exit);

MODULE_AUTHOR("BQL");
MODULE_LICENSE("GPL");

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include /*kmalloc头文件*/
#include/*信号量头文件*/

#define MEMDEV_MAJOR 251 /*预设的mem的主设备号*/
#define MEMDEV_NUM 2 /*设备数*/
#define MEMDEV_SIZE 1024 /*分配的内存大小*/

struct mem_dev
{
unsigned int size;
char *data;
struct semaphore sem;
};

static int mem_major = MEMDEV_MAJOR; /*预设的mem的主设备号*/
struct cdev mem_cdev;
struct mem_dev *mem_devp; /*设备结构体指针*/

/*文件打开函数*/
static int
mem_open(struct inode *inode,struct file *filp)
{
struct mem_dev *dev;
unsigned int num;
printk("mem_open.\n");

num= MINOR(inode->i_rdev); /*获得次设备号*/
if(num>(MEMDEV_NUM-1))
return -ENODEV;

dev = &mem_devp[num];
filp->private_data = dev; /*将设备结构保存为私有数据*/

return 0;
}

/*关闭时调用*/
static int
mem_release(struct inode *inode,struct file *filp)
{
printk("mem_release.\n");
return 0;
}

/*读函数*/
static ssize_t
mem_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
{
int ret = 0;
struct mem_dev *dev;
unsigned long p;
unsigned long count;

printk("mem_read.\n");

dev = filp->private_data; /*获得设备结构*/
count = size;
p = *ppos;

/*检查偏移量和数据大小的有效性*/
if(p > MEMDEV_SIZE)
return 0;
if(count >(MEMDEV_SIZE-p))
count = MEMDEV_SIZE - p;
if(down_interruptible(&dev->sem)) /*锁定互斥信号量*/
return -ERESTARTSYS;
/*读取数据到用户空间*/
if(copy_to_user(buf,dev->data+p,count))
{
ret = -EFAULT;
printk("copyfrom user failed\n");
}
else
{
*ppos +=count;
ret = count;
printk("read %d bytes from dev\n",count);
}
up(&dev->sem); /*解锁互斥信号量*/
return ret;
}

/*写函数*/
static ssize_t
mem_write(struct file *filp,const char __user