globalmem设备代码分析

来源:互联网 发布:cydia软件源闪退ios9 编辑:程序博客网 时间:2024/06/05 14:40

驱动程序代码:

#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<linux/slab.h>          
#include<linux/kdev_t.h>  
#include<linux/device.h>  
#include <asm/io.h>  
#include<asm/system.h>  
#include<asm/uaccess.h>  
   
#define DEVICE_NAME   "globalmem"  
#define GLOBALMEM_SIZE         0x1000/*全局内存最大4K字节*/  
#define MEM_CLEAR 0x1/*清0全局内存*/  
#define GLOBALMEM_MAJOR 241/*预设的globalmem的主设备号*/  
   
static int globalmem_major = GLOBALMEM_MAJOR;  




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


struct globalmem_dev *globalmem_devp; /*设备结构体指针*/  
   
static struct class *globalmem0_class;  
static struct class *globalmem1_class;  


   


/*文件打开函数*/  
int globalmem_open(struct inode *inode, struct file *filp)  
{  
/*将设备结构体指针赋值给文件私有数据指针*/  
struct globalmem_dev *dev;  


dev = container_of(inode->i_cdev,struct globalmem_dev,cdev);   
filp->private_data = dev;   
return 0;  
}  










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








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







   
/*读函数*/  
static ssize_t globalmem_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 globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/  

/*分析和获取有效的写长度*/  
if (p >= GLOBALMEM_SIZE)  
return count ?  - ENXIO: 0;  
if (count > GLOBALMEM_SIZE - p)  
count = GLOBALMEM_SIZE - p;  

/*内核空间->用户空间*/  
if (copy_to_user(buf, (void*)(dev->mem +p), count))  
{  
ret = - EFAULT;  
}  
else  
{  
*ppos += count;  
ret = count;  

printk(KERN_INFO "read %d bytes(s)from %d\n", count, p);  
}  
return ret;  
}  






   
/*写函数*/  
static ssize_t globalmem_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 globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/  

/*分析和获取有效的写长度*/  
if (p >= GLOBALMEM_SIZE)  
return count ?  - ENXIO: 0;  
if (count > GLOBALMEM_SIZE - p)  
count = GLOBALMEM_SIZE - p;  

/*用户空间->内核空间*/  
if (copy_from_user(dev->mem + p, buf,count))  
ret = - EFAULT;  
else  
{  
*ppos += count;  
ret = count;  
printk(KERN_INFO "written %d bytes(s)from %d\n", count, p);  
}  

return ret;  
}  
   
   
   
   
/* seek文件定位函数 */  
static loff_t globalmem_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 >GLOBALMEM_SIZE)  
{  
ret = - EINVAL;  
break;  
}  
filp->f_pos = (unsigned int)offset;  
ret = filp->f_pos;  
break;  


case 1:  /*相对文件当前位置偏移*/  
if ((filp->f_pos + offset) >GLOBALMEM_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 globalmem_fops =  
{  
.owner = THIS_MODULE,  
.llseek = globalmem_llseek,  
.read = globalmem_read,  
.write = globalmem_write,  
//.ioctl = globalmem_ioctl, 
.unlocked_ioctl = globalmem_ioctl,
.compat_ioctl = globalmem_ioctl,
.open = globalmem_open,  
.release = globalmem_release,  
};  
   
   
   
   
/*初始化并注册cdev*/  
static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)  
{  
int err, devno = MKDEV(globalmem_major,index);  

/*
cdev_init(&dev->cdev, &globalmem_fops);  
dev->cdev.owner = THIS_MODULE;  
dev->cdev.ops = &globalmem_fops; 
*/


cdev_init(&dev->cdev, &globalmem_fops);  
dev->cdev.owner = THIS_MODULE;  


err = cdev_add(&dev->cdev, devno, 1);  
if (err)  
printk(KERN_NOTICE "Error %d addingLED%d", err, index);  
}  






   
/*设备驱动模块加载函数*/  
int globalmem_init(void)  
{  
int result;  
dev_t devno = MKDEV(globalmem_major, 0);  

/* 申请设备号*/  
if (globalmem_major)  
result = register_chrdev_region(devno, 2,DEVICE_NAME);  
else /* 动态申请设备号 */  
{  
result = alloc_chrdev_region(&devno, 0,2, DEVICE_NAME);  
globalmem_major = MAJOR(devno);  
}   
if (result < 0)  
return result;  
     
/* 动态申请2个设备结构体的内存*/  
globalmem_devp = kmalloc(2*sizeof(struct globalmem_dev), GFP_KERNEL);  
if (!globalmem_devp)    /*申请失败*/  
{  
result = - ENOMEM;  
goto fail_malloc;  
}  
memset(globalmem_devp, 0, 2*sizeof(struct globalmem_dev));  


globalmem_setup_cdev(&globalmem_devp[0],0);  
globalmem_setup_cdev(&globalmem_devp[1],1);  
   
    //注册一个类,使mdev可以在/dev/下面建立设备节点   
    globalmem0_class =class_create(THIS_MODULE, "globalmem0");   
    if( IS_ERR(globalmem0_class) )   
    {   
        printk(KERN_NOTICE, "creatglobalmem0_class failed!");   
        return -1;   
    }   
   
    //创建一个设备节点,节点名字为globalmem0   
    device_create(globalmem0_class, NULL,MKDEV(globalmem_major, 0), NULL, "globalmem0");   
    printk(KERN_NOTICE, "globalmem0initialized!");   
   
    globalmem1_class =class_create(THIS_MODULE, "globalmem1");   
    if( IS_ERR(globalmem1_class) )   
    {   
        printk(KERN_NOTICE, "creatglobalmem1_class failed!");   
        return -1;   
    }   
   
    //创建一个设备节点,节点名字为globalmem1   
    device_create(globalmem1_class, NULL,MKDEV(globalmem_major, 1), NULL, "globalmem1");   
    printk(KERN_NOTICE, "globalmem1initialized!");   
   
return 0;  

fail_malloc: 
unregister_chrdev_region(devno,2);  
return result;  
}  






   
/*模块卸载函数*/  
void globalmem_exit(void)  
{  
cdev_del(&(globalmem_devp[0].cdev));    
cdev_del(&(globalmem_devp[1].cdev));   /*注销cdev*/  
kfree(globalmem_devp);     /*释放设备结构体内存*/  
unregister_chrdev_region(MKDEV(globalmem_major, 0), 2); /*释放设备号*/  
class_destroy(globalmem0_class);   
class_destroy(globalmem1_class);   
}  






   
MODULE_AUTHOR("SongBaohua");  
MODULE_LICENSE("GPL");  
//MODULE_LICENSE("DualBSD/GPL");  
   
module_param(globalmem_major,int, S_IRUGO);  
   
module_init(globalmem_init);  

module_exit(globalmem_exit); 







用户空间测试程序代码:

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
#include <unistd.h>  
#include<linux/fcntl.h>  
   
int main()  
{  
int fd;  
char buf1[]="testglobalmen data!";//写入memdev设备的内容  
char buf_read[4096]; //memdev设备的内容读入到该buf中  

if((fd=open("/dev/globalmem0",O_RDWR))==-1)//打开memdev设备  
{  
printf("open globalmem0 WRONG!\n");  
return 0;  
}  
   
int count = 0;  
while(count<=100)  
{  
printf("openglobalmem0 SUCCESS!\n");  
printf("buf is %s\n",buf1);  
write(fd,buf1,sizeof(buf1));//把buf中的内容写入memdev设备  
lseek(fd,0,SEEK_SET); //把文件指针重新定位到文件开始的位置  
read(fd,buf_read,sizeof(buf1));//把memdev设备中的内容读入到buf_read中  
printf("buf_read is %s\n",buf_read);  
count++;  
}  

close(fd);  
return 0;  













原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 支付宝密码错误被锁定怎么办 实名身份证的微信限额怎么办 工行网银登陆密码忘了怎么办 美亚买的东西坏了怎么办 海带宝转运到香港怎么办 海带宝转运仓库入库错误怎么办 三星s7edge密码忘了怎么办 ie网页被拦截了怎么办 手机打开百度网页弹出广告怎么办 网站策略服务已被禁用怎么办 谷歌浏览器打不开网页怎么办 mac用户名密码忘记了怎么办 苹果7网速太慢怎么办 ps中图片选不中怎么办 加装硬盘不显示怎么办 win10网络无权限访问怎么办 电脑装机时c盘隐藏怎么办 word不允许修改锁定了是怎么办 word文档只读不能编辑怎么办 word无法读取文档时怎么办 ps超出2g存不了怎么办 qq帐号不记得了怎么办 苹果手机wifi密码输错怎么办 qq搜索关键字屏蔽了怎么办 手机数据被屏蔽了怎么办 ea账号安全问题答案忘了怎么办 电脑用户账户密码忘记了怎么办 公司名字审核通过剩下怎么办 抖音一直在审核怎么办 平板电脑显示ipad已停用怎么办 违章车型与实际车型不符怎么办 网购与实物不符怎么办 内网ip地址丢失怎么办 转账户名写错了怎么办 工资卡开户写错公司名称怎么办 商标跟别人重了怎么办 不受信任的应用打不开怎么办 oppo手机安全证书过期怎么办 网站安全证书有问题怎么办 公章圆圈摔坏了怎么办 高风险办税人员怎么办