globalmem设备代码分析
驅動程序代碼:
#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; ?
}?
總結
以上是生活随笔為你收集整理的globalmem设备代码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cdev_alloc和cdev_init
- 下一篇: 在/sys目录下建立一个文件,并且实现信