linux驱动学习--第十二天:第六章 Linux 字符设备驱动(二) 之 globalmem 设备驱动
2013-06-16 00:41
543 查看
小结:
【问题一】
这一部分的代码,我参考了这个博客里面的源码
但是无法编译.KO文件,然后我又找到了这个博客,参考了里面的Makefile文件
然后make成功,编译通过。
主要的问题是第一个博客里面的makefile文件中的
第二行
KERNELBUILD:=/lib/modules/`uname-r`/build
修改为
KERNELBUILD:=/lib/modules/$(shelluname-r)/build
红色字的部分不一样。
编译成功。
【问题二】
“insmodglobalmem.ko”这个命令使用的时候,提示无此命令。
然后查找得到需要root权限,并使用
/sbin/insmodglobalmem.ko
这样子就可以加载成功了。
通过cat/proc/devices命令
可以看到系统的设备号如下:
[root@localhostglobalmem]#cat/proc/devices
Characterdevices:
255globalmem
1mem
4/dev/vc/0
4tty
4ttyS
5/dev/tty
5/dev/console
5/dev/ptmx
6lp
7vcs
10misc
13input
14sound
29fb
116alsa
128ptm
136pts
180usb
189usb_device
216rfcomm
254pcmcia
Blockdevices:
1ramdisk
2fd
3ide0
9md
22ide1
253device-mapper
254mdp
255设备号已经添加成功。
下面附上我的Makefile文件
Makefile
obj-m:=globalmem.o
KERNELBUILD:=/lib/modules/$(shelluname-r)/build
default:
make-C$(KERNELBUILD)M=$(shellpwd)modules
clean:
rm-rf*.o.*.cmd*.ko*.mod.c.tmp_versions
修改后的驱动globalmem.c直接从别人那里拷贝的,但是已经可以正常编译通过,并可以加载成功。
/*======================================================================
Aglobalmemdriverasanexampleofchardevicedrivers
TheinitialdeveloperoftheoriginalcodeisBaohuaSong
<author@linuxdriver.cn>.AllRightsReserved.
======================================================================*/
#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<asm/io.h>
#include<asm/system.h>
#include<asm/uaccess.h>
////////增加此头文件//////////
#include<linux/slab.h>
////////////////////////////
#defineGLOBALMEM_SIZE 0x1000 /*全局内存最大4K字节*/
#defineMEM_CLEAR0x1/*清0全局内存*/
//#defineGLOBALMEM_MAJOR254/*预设的globalmem的主设备号*/
#defineGLOBALMEM_MAJOR255/*预设的globalmem的主设备号*/
staticglobalmem_major=GLOBALMEM_MAJOR;
/*globalmem设备结构体*/
structglobalmem_dev
{
structcdevcdev;/*cdev结构体*/
unsignedcharmem[GLOBALMEM_SIZE];/*全局内存*/
};
structglobalmem_dev*globalmem_devp;/*设备结构体指针*/
/*文件打开函数*/
intglobalmem_open(structinode*inode,structfile*filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data=globalmem_devp;
return0;
}
/*文件释放函数*/
intglobalmem_release(structinode*inode,structfile*filp)
{
return0;
}
/*ioctl设备控制函数*/
staticintglobalmem_ioctl(structinode*inodep,structfile*filp,unsigned
intcmd,unsignedlongarg)
{
structglobalmem_dev*dev=filp->private_data;/*获得设备结构体指针*/
switch(cmd)
{
caseMEM_CLEAR:
memset(dev->mem,0,GLOBALMEM_SIZE);
printk(KERN_INFO"globalmemissettozero/n");
break;
default:
return-EINVAL;
}
return0;
}
/*读函数*/
staticssize_tglobalmem_read(structfile*filp,char__user*buf,size_tsize,
loff_t*ppos)
{
unsignedlongp=*ppos;
unsignedintcount=size;
intret=0;
structglobalmem_dev*dev=filp->private_data;/*获得设备结构体指针*/
/*分析和获取有效的写长度*/
if(p>=GLOBALMEM_SIZE)
returncount?-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%dbytes(s)from%d/n",count,p);
}
returnret;
}
/*写函数*/
staticssize_tglobalmem_write(structfile*filp,constchar__user*buf,
size_tsize,loff_t*ppos)
{
unsignedlongp=*ppos;
unsignedintcount=size;
intret=0;
structglobalmem_dev*dev=filp->private_data;/*获得设备结构体指针*/
/*分析和获取有效的写长度*/
if(p>=GLOBALMEM_SIZE)
returncount?-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%dbytes(s)from%d/n",count,p);
}
returnret;
}
/*seek文件定位函数*/
staticloff_tglobalmem_llseek(structfile*filp,loff_toffset,intorig)
{
loff_tret=0;
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;
break;
}
returnret;
}
/*文件操作结构体*/
staticconststructfile_operationsglobalmem_fops=
{
.owner=THIS_MODULE,
.llseek=globalmem_llseek,
.read=globalmem_read,
.write=globalmem_write,
//.ioctl改为.compat_ioctl
.compat_ioctl=globalmem_ioctl,
.open=globalmem_open,
.release=globalmem_release,
};
/*初始化并注册cdev*/
staticvoidglobalmem_setup_cdev(structglobalmem_dev*dev,intindex)
{
interr,devno=MKDEV(globalmem_major,index);
cdev_init(&dev->cdev,&globalmem_fops);
dev->cdev.owner=THIS_MODULE;
dev->cdev.ops=&globalmem_fops;
err=cdev_add(&dev->cdev,devno,1);
if(err)
printk(KERN_NOTICE"Error%daddingLED%d",err,index);
}
/*设备驱动模块加载函数*/
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);/*注销cdev*/
kfree(globalmem_devp);/*释放设备结构体内存*/
unregister_chrdev_region(MKDEV(globalmem_major,0),1);/*释放设备号*/
}
MODULE_AUTHOR("SongBaohua");
MODULE_LICENSE("DualBSD/GPL");
module_param(globalmem_major,int,S_IRUGO);
module_init(globalmem_init);
module_exit(globalmem_exit);
相关文章推荐
- linux驱动学习--第十一天:第六章 Linux 字符设备驱动(一) 之 Linux 字符设备驱动结构
- linux设备驱动开发学习之旅--简单字符驱动实例globalmem
- Linux设备驱动开发学习(1)--字符设备驱动
- 基于mini6410的linux驱动学习总结(五 字符设备驱动程序实例分析(虚拟设备驱动))
- Linux驱动学习——简单字符设备
- Linux驱动入门学习(二):字符设备和块设备区别
- Linux驱动模型学习(二)---字符设备驱动模型之二---初窥字符设备驱动
- 基于mini6410的linux驱动学习总结(二 字符设备与块设备的区别)
- 嵌入式Linux驱动学习之路(十)字符设备驱动-my_led
- Linux驱动学习(二)——字符设备驱动程序入门 .
- [Linux驱动]字符设备驱动学习笔记(二)———实例
- Linux驱动学习(四)——高级字符设备驱动程序
- linux驱动学习之字符设备驱动模板
- Linux设备驱动程序学习笔记 高级字符驱动学习--阻塞型I/0
- 嵌入式linux学习笔记4之字符设备驱动
- Linux学习:LED字符设备驱动
- [Linux驱动]字符设备驱动学习笔记(一)
- [Linux驱动]字符设备驱动学习笔记(三)———高级
- Linux设备驱动开发详解-第6章字符设备驱动(二)-支持2个globalmem
- 《Linux4.0设备驱动开发详解》笔记--第六章:Linux字符设备驱动