当前位置: 技术问答>linux和unix
操纵一块内存区的驱动函数
来源: 互联网 发布时间:2016-06-26
本文导语: 这是一个操纵一块内存区的驱动函数,当系统以调用ioctl函数国MEM_CLEAR和 MEM_SETSIZE时,就立刻卡住了 然后键盘上数字键盘的指示灯灭掉,另外两个指示灯不停的闪,不知道是怎么回事? mdri.h #ifndef _MDRI_H #define _MDRI_H...
这是一个操纵一块内存区的驱动函数,当系统以调用ioctl函数国MEM_CLEAR和 MEM_SETSIZE时,就立刻卡住了 然后键盘上数字键盘的指示灯灭掉,另外两个指示灯不停的闪,不知道是怎么回事?
mdri.h
mdri.c
mdri.h
#ifndef _MDRI_H
#define _MDRI_H
#include
#define MEM_CLEAR _IO('k',1)
#define MEM_RE _IO('k',2)
#define MEM_SETSIZE _IOW('k',3,unsigned long)
#endif
mdri.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mdri.h"
#define GLOBALMEM_SIZE 0x1000
#define GLOBALMEM_MAJOR 255
struct globalmem_dev
{
unsigned int count;
int size;
struct cdev cd;
unsigned char mem[GLOBALMEM_SIZE];
};
struct globalmem_dev *g_dev;
struct file_operations globalmem_fopes;
int globalmem_major=GLOBALMEM_MAJOR;
int globalmem_open(struct inode *inode,struct file *filp)
{
filp->private_data=g_dev;
g_dev->count++;
return 0;
}
int globalmem_release(struct inode *inode,struct file *filp)
{
if(g_dev->count>0)
g_dev->count--;
return 0;
}
int globalmem_ioctl(struct inode *inodep,
struct file *filp,unsigned int cmd,unsigned long arg)
{
int i;
//unsigned long karg;
int karg;
char c;
switch(cmd)
{
case MEM_CLEAR:
memset(g_dev->mem,0,g_dev->size);
g_dev->size=0;
printk(KERN_EMERG "MEM_CLEAR g_dev->size=%in",g_dev->size);
break;
case MEM_RE:
if(g_dev->count!=1)
return -1;
for(i=0;isize)/2;i++){
c=g_dev->mem[i];
g_dev->mem[i]=g_dev->mem[g_dev->size-i-1];
g_dev->mem[g_dev->size-i-1]=c;
}
printk(KERN_EMERG "MEM_RE g_dev->size=%in",g_dev->size);
break;
case MEM_SETSIZE:
if(access_ok(VERIFY_READ,&arg,sizeof(unsigned long)))
{
printk(KERN_EMERG "read arg error1n");
return -EFAULT;
}
if(get_user(karg,(__user int *)arg))
{
printk(KERN_EMERG "read arg error2n");
return -EFAULT;
}
if(kargGLOBALMEM_SIZE)
break;
g_dev->size=(int)karg;
printk(KERN_EMERG "MEM_SETSIZE g_dev->size=%i,karg=%in",g_dev->size,karg);
break;
default:
return - EINVAL;
}
return 0;
}
int globalmem_read(struct file *filp,char __user *buf,
size_t size,loff_t *ppos)
{
unsigned long pos=*ppos;
unsigned long count=size;
printk(KERN_INFO "readn");
printk("%cn",g_dev->mem[0]);
if(access_ok(VERIFY_WRITE,buf,count)==-EFAULT)
{
printk(KERN_INFO "read error1n");
return -EFAULT;
}
if(*ppos+count>g_dev->size)
count=g_dev->size-(*ppos);
if(copy_to_user(buf,(void*)(g_dev->mem+pos),count))
{
printk(KERN_INFO "read error2n");
return -EFAULT;
}
*ppos+=count;
printk("%sn",g_dev->mem);
printk(KERN_INFO "read overn");
return count;
}
int globalmem_write(struct file *filp,char __user *buf,
size_t size,loff_t *ppos)
{
printk(KERN_INFO "writen");
printk("%cn",g_dev->mem[0]);
if(g_dev->count!=1)
{
printk(KERN_INFO "write error:g_dev!=1n");
return -EFAULT;
}
unsigned long real_size;
if(size+(g_dev->size) > GLOBALMEM_SIZE)
real_size=GLOBALMEM_SIZE;
else
real_size=size;
if(copy_from_user((g_dev->mem)+g_dev->size,(void *)buf,real_size))
{
printk(KERN_INFO "write error 1n");
return -EFAULT;
}
g_dev->size+=real_size;
printk("%sn",g_dev->mem);
printk(KERN_INFO "write overn");
return real_size;
}
loff_t globalmem_llseek(struct file *filp,loff_t offset,int orig)
{
switch(orig)
{
case 0://from the begin of the file
if(offset GLOBALMEM_SIZE)
return -EFAULT;
filp->f_pos=(unsigned int)offset;
return offset;
case 1://from the current of the file
if(filp->f_pos+offset>GLOBALMEM_SIZE || filp->f_pos+offsetf_pos+=offset;
return filp->f_pos;
case 2://from the end of the file
if(offset>0 || offset+g_dev->sizef_pos=(unsigned int)(offset+g_dev->size);
return filp->f_pos;
default:
return -EFAULT;
}
}
static const struct file_operations globalmem_fops =
{
.owner = THIS_MODULE,
.llseek = globalmem_llseek,
.read = globalmem_read,
.write = globalmem_write,
.ioctl = globalmem_ioctl,
.open = globalmem_open,
.release = globalmem_release,
};
static void globalmem_setup_cdev(struct globalmem_dev *dev,int index)
{
int err,devno=MKDEV(GLOBALMEM_MAJOR,index);
cdev_init(&g_dev->cd,&globalmem_fops);
g_dev->cd.owner=THIS_MODULE;
g_dev->cd.ops=&globalmem_fops;
err=cdev_add(&g_dev->cd,devno,1);
if(err)
printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}
int globalmem_init(void)
{
int result;
dev_t devno=MKDEV(globalmem_major,0);
if(globalmem_major)
result=register_chrdev_region(devno,1,"globalmem");
else
{
result=alloc_chrdev_region(&devno,0,1,"globalmem");
globalmem_major=MAJOR(devno);
}
if(resultsize=0;
g_dev->count=0;
globalmem_setup_cdev(g_dev,0);
return 0;
}
void globalmem_exit(void)
{
cdev_del(&g_dev->cd);
kfree(g_dev);
unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);
}
MODULE_AUTHOR("BLACK & WHITE");
MODULE_LICENSE("Dual BSD/GPL");
module_param(globalmem_major, int, S_IRUGO);
module_init(globalmem_init);
module_exit(globalmem_exit);
|
#define GLOBALMEM_SIZE 0x1000
这里开的太大了,用
#define GLOBALMEM_SIZE 0x100
这里开的太大了,用
#define GLOBALMEM_SIZE 0x100
|
g_dev->size 赋值的语句好多条呢,难道都去掉?
|
楼主这个程序是Linux设备驱动开发入门与编程实践这本书中的,
这本书说实话,我感觉水平很一般,错误百出,
它给的globalmem驱动本身就有问题~
建议换一个例程学习~
这本书说实话,我感觉水平很一般,错误百出,
它给的globalmem驱动本身就有问题~
建议换一个例程学习~
|
友情帮顶,一起学习。
|
帮顶。
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。