嵌入式 globalmem虚拟字符设备驱动雏形

原创 2013年12月02日 14:56:12

 

一、globalmem虚拟设备简介

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_t devno;

 

filp->private_data=globalmem_devp;

printk("inode->i_rdev=%dglobalmem->cdev->dev=%d\n",inode->i_ino,MAJOR(globalmem_devp->cdev.dev));

return 0;

}

 

intglobalmem_release(struct inode *inode,struct file*filp)

{

return 0;

}

 

static ssize_tglobalmem_read(struct file *filp,char __user *buf,size_tcount,loff_t *ppos)

{

unsigned long p = *ppos;

int ret = 0;

 

struct globalmem_dev *dev=filp->private_data;

 

if(p >= GLOBALMEM_SIZE - p)

return 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_tglobalmem_write(struct file *filp,const char __user *buf, size_tcount,loff_t *ppos)

{

unsigned long p = *ppos;

int ret = 0;

 

struct globalmem_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);

}

return ret;

}

 

static loff_tglobalmem_llseek(struct file *filp,loff_t offset,intorig)

{

loff_t ret;

switch (orig){

case 0:

if(offset < 0){

ret = -EINVAL;

break;

}

if((unsigned int)offset >GLOBALMEM_SIZE){

ret = -EINVAL;

break;

}

filp->f_pos= (unsignedint)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;

}

return ret;

}

 

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){

case MEM_CLEAR:

memset(dev->mem,0,GLOBALMEM_SIZE);

filp->f_pos= 0;

printk(KERN_INFO"globalmem id set tozero\n");

break;

default:

return -EINVAL;

}

return 0;

}

 

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)

{

int err,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)

{

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(result < 0)

return result;

 

globalmem_devp=kmalloc(sizeof(structglobalmem_dev),GFP_KERNEL);

if(!globalmem_devp){

result=-ENOMEM;

goto fail_malloc;

}

memset(globalmem_devp,0,sizeof(structglobalmem_dev));

globalmem_setup_cdev(globalmem_devp,0);

return 0;

fail_malloc:

unregister_chrdev_region(devno,1);

return result;

}

 

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()

{

int fd;

char buf[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");

return 0;

}

write(fd,buf,20);

close(fd);

fd =open("/dev/Mac",O_RDONLY);

if(fd < 0)

{

printf("open /dev/Mac error\n");

return 0;

}

 

read(fd,receve,20);

printf("buf:%s\n",receve);

ioctl(fd,MEM_CLEAR);

read(fd,receve,20);

printf("buf:%s\n",receve);

close(fd);

return 0;

}

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.执行应用程序即可看到效果。

嵌入式 <wbr>globalmem虚拟字符设备驱动雏形

相关文章推荐

关于虚拟字符设备驱动的学习笔记globalmem

1. linux设备驱动程序之简单字符设备驱动开发 2. 一个简单的Linux驱动程序和Makefile 3. “: asm/uaccess.h: 没有那个文件或目录”原因和解决办法 4. “错误: ...

globalmem虚拟字符设备驱动--字符驱动讲解(2)

1、什么是globalmem虚拟设备?? (1)、globalmem字符设备驱动中,分配一片内存大小为GLOBALMEM_SIZE(4K)的空间 (2)、提供对该片内存的读写、控制和定位函数 ...
  • quannii
  • quannii
  • 2013年01月16日 14:56
  • 3475

嵌入式学习笔记——字符设备驱动编写

开发环境:Ubuntu 12.04        开发板:龙芯1B开发板  内核版本是3.0.1            linux的外设可以分为三类:字符设备(character device)、...

LINUX—字符设备驱动之-globalmem

下面将以linux设备驱动开发详解上的globalmem设备驱动为例来详细分析字符设备驱动的过程。 #include //模块所需的大量符号和函数定义#include #include /...
  • califan
  • califan
  • 2011年02月25日 12:11
  • 416

嵌入式学习-驱动开发-lesson1-字符设备驱动模型

驱动模型分析 在Linux系统中,设备的类型非常繁多,如:字符设备,块设备,网络接口设备,USB设备,PCI设备,平台设备,混杂设备……,而设备类型不同,也意味着其对应的驱动程序模型不同,但是这些驱...

嵌入式学习-驱动开发-lesson2-LED字符设备驱动

一、设备控制1)设备控制应用函数在用户空间,主要是使用ioctl系统调用来控制设备。 int ioctl(int fd,unsigned long cmd,…) fd: 要控制的设备文件描述符 ...

编译及加载globalmem字符设备驱动出现的问题

刚学习Linux字符设备驱动,第一个globalmem程序,基本一边了解,一边抄写。写完后,make的时候出现如下问题: globalmem.c:99: 错误:程序中有游离的 ‘\343’ gl...

Linux字符设备驱动-globalmem驱动编译加载遇到的问题及解决办法

代码是直接复制《LINUX设备驱动开发详解》里面的(源代码见下面)。Makefile如下:obj-m := globalmem.o KERNELBUILD := /lib/modules/`uname...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 globalmem虚拟字符设备驱动雏形
举报原因:
原因补充:

(最多只允许输入30个字)