您的位置:首页 > 运维架构 > Linux

linux驱动学习--第十二天:第六章 Linux 字符设备驱动(二) 之 globalmem 设备驱动

2013-06-16 00:41 543 查看


小结:

【问题一】

这一部分的代码,我参考了这个博客里面的源码http://blog.csdn.net/zimingjushi/article/details/6575777。
但是无法编译.KO文件,然后我又找到了这个博客,参考了里面的Makefile文件http://www.360doc.com/content/08/1204/14/36491_2051147.shtml
然后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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: