嵌入式 globalmem虚拟字符设备驱动雏形
来源:互联网 发布:重大网络教育学院 编辑:程序博客网 时间:2024/05/19 06:51
globalmem意味着“全局内存”,在globalmem字符设备驱动中会分配一片大小GLOBALMEM_SIZE(4KB)的内存空间,并在驱动中提供了对这片内存的读写、控制和定位函数,用户空间的进程能通过Linux系统调用访问这片内存。该设备驱动仅仅是为了讲解问题的方便而凭空制造出来的设备。但他也有用处,由于globalmem可被两个或以上的进程同时访问,其中的全局内存可作为用户空间进程进行通信一种蹩脚的手段。
二、编写驱动代码
1.头文件globalmem.h
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <asm/dma.h>
#include <asm/delay.h>
#include <linux/delay.h>
#define GLOBALMEM_SIZE0x1000
#define MEM_CLEAR0x01
#define GLOBALMEM_MAJOR250
static intglobalmem_major = GLOBALMEM_MAJOR;
structglobalmem_dev{
struct cdev cdev;
unsigned char mem[GLOBALMEM_SIZE];
};
2.驱动代码globalmem.c
#include"globalmem.h"
struct globalmem_dev*globalmem_devp;
intglobalmem_open(struct inode *inode,struct file *filp)
{
dev_tdevno;
filp->private_data=globalmem_devp;
printk("inode->i_rdev=%dglobalmem->cdev->dev=%d\n",inode->i_ino,MAJOR(globalmem_devp->cdev.dev));
return0;
}
intglobalmem_release(struct inode *inode,struct file*filp)
{
return0;
}
static ssize_tglobalmem_read(struct file *filp,char __user *buf,size_tcount,loff_t *ppos)
{
unsignedlong p = *ppos;
intret = 0;
structglobalmem_dev *dev=filp->private_data;
if(p>= GLOBALMEM_SIZE - p)
return0;
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);
}
returnret;
}
static ssize_tglobalmem_write(struct file*filp,const char __user *buf, size_tcount,loff_t *ppos)
{
unsignedlong p = *ppos;
intret = 0;
structglobalmem_dev*dev=filp->private_data;
if(p>= GLOBALMEM_SIZE)
return 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);
}
returnret;
}
static loff_tglobalmem_llseek(struct file *filp,loff_t offset,intorig)
{
loff_tret;
switch(orig){
case0:
if(offset< 0){
ret= -EINVAL;
break;
}
if((unsignedint)offset >GLOBALMEM_SIZE){
ret= -EINVAL;
break;
}
filp->f_pos= (unsignedint)offset;
ret= filp->f_pos;
break;
case1:
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;
}
returnret;
}
static intglobalmem_ioctl(struct inode *inodep,struct file *filp,unsigned intcmd,unsigned long arg)
{
int ret;
struct globalmem_dev*dev=filp->private_data;
switch(cmd){
caseMEM_CLEAR:
memset(dev->mem,0,GLOBALMEM_SIZE);
filp->f_pos= 0;
printk(KERN_INFO"globalmem id set tozero\n");
break;
default:
return-EINVAL;
}
return0;
}
static const structfile_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 voidglobalmem_setup_cdev(struct globalmem_dev *dev,intindex)
{
interr,devno =MKDEV(globalmem_major,index);
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 addingglobalmem",err);
}
intglobalmem_init(void)
{
intresult;
dev_tdevno =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(result< 0)
returnresult;
globalmem_devp=kmalloc(sizeof(structglobalmem_dev),GFP_KERNEL);
if(!globalmem_devp){
result=-ENOMEM;
gotofail_malloc;
}
memset(globalmem_devp,0,sizeof(structglobalmem_dev));
globalmem_setup_cdev(globalmem_devp,0);
return0;
fail_malloc:
unregister_chrdev_region(devno,1);
returnresult;
}
voidglobalmem_exit(void)
{
cdev_del(&globalmem_devp->cdev);
kfree(globalmem_devp);
unregister_chrdev_region(MKDEV(globalmem_major,0),1);
}
MODULE_LICENSE("DualBSD/GPL");
module_param(globalmem_major,int,S_IRUGO);
module_init(globalmem_init);
module_exit(globalmem_exit);
MODULE_AUTHOR("Mac");
3.测试应用程序代码test.c
#include
#include
#include
#include
#include
#include
#include"test_cmd.h"
#include
int main()
{
intfd;
charbuf[20]="Welcome toChina",receve[20]={'\0'};
structioctl_data test_data={
.size=10,
.buf="123456789"
};
fd= open("/dev/Mac",O_WRONLY);
if(fd< 0)
{
printf("open/dev/Mac error\n");
return0;
}
write(fd,buf,20);
close(fd);
fd =open("/dev/Mac",O_RDONLY);
if(fd< 0)
{
printf("open/dev/Mac error\n");
return0;
}
read(fd,receve,20);
printf("buf:%s\n",receve);
ioctl(fd,MEM_CLEAR);
read(fd,receve,20);
printf("buf:%s\n",receve);
close(fd);
return0;
}
3.编写Makefile文件
ifneq($(KERNELRELEASE),)
obj-m:=mac_test.o
else
KDIR:=/lib/modules/2.6.28/build
all:
make -C $(KDIR) M=`pwd`modules
clean:
-rm -f *.markers *.order*.ko *.o *.mod.o *.mod.c *.symvers
#make -C $(KDIR) M=`pwd` modulesclean
endif
三、测试操作
1.在/dev目录下创建Mac设备文件:#mknod/dev/Mac c 250 0
2.make产生模块文件并加载上。使用gcc编译应用测试程序。
3.执行应用程序即可看到效果。
- 嵌入式 globalmem虚拟字符设备驱动雏形
- 虚拟设备字符驱动globalmem分析
- globalmem虚拟字符设备驱动--字符驱动讲解(2)
- 关于虚拟字符设备驱动的学习笔记globalmem
- 设备驱动-----字符驱动globalmem(cdev)
- linux 驱动-----字符设备globalmem驱动实现
- LINUX—字符设备驱动之-globalmem
- LINUX—字符设备驱动之-globalmem
- LINUX—字符设备驱动之-globalmem
- 标准字符设备驱动解析 globalmem.c
- Linux设备驱动入门----globalmem字符设备驱动
- Linux设备驱动入门----globalmem字符设备驱动
- Linux设备驱动程序学习(二)虚拟字符设备globalmem
- linux设备驱动--globalmem字符设备框架分析
- linux设备驱动--globalmem字符设备框架分析
- linux设备驱动--globalmem字符设备框架分析
- 嵌入式 globalmem设备驱动ioctl()函数的实现
- globalmem设备驱动
- 嵌入式 fstab文件详解
- centOS6.3安装tomcat
- 嵌入式 netperf2交叉编译
- 嵌入式 i2c总线
- 嵌入式 I2C总线协议
- 嵌入式 globalmem虚拟字符设备驱动雏形
- 嵌入式 linux下cdev详解
- 嵌入式 globalmem设备驱动ioctl()函数的实现
- linux的文本书写及命令
- 嵌入式 MII和RMII接口详介
- 嵌入式 实现逐行读取txt
- 嵌入式 A-LawPCM转换为wav格式
- 嵌入式 WAV格式常见的几种压缩形式(compression code)
- 嵌入式 WAV中包含G711文件头有关问题