linux字符设备驱动课程设计报告Word格式文档下载.docx
《linux字符设备驱动课程设计报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《linux字符设备驱动课程设计报告Word格式文档下载.docx(22页珍藏版)》请在冰点文库上搜索。
③inode结构,提供了关于特殊设备文件/dev/mydev的信息。
各个结构的定义如下:
(1)file_operations结构:
staticconststructfile_operationsmy_fops={
.owner=THIS_MODULE,
.llseek=my_llseek,
.read=my_read,
.write=my_write,
.open=my_open,
.release=my_release,
.unlocked_ioctl=ioctl,
};
(2)file结构:
1)读
staticssize_tmy_read(structfile*filp,char__user*buf,size_tsize,loff_t*ppos)
2)写
staticssize_tmy_write(structfile*filp,constchar__user*buf,size_tsize,loff_t*ppos)
3)seek文件定位
staticloff_tmy_llseek(structfile*filp,loff_toffset,intwhence)
4)I\O控制
staticintioctl(structfile*file,unsignedintcmd,unsignedlongarg)
(3)inode结构:
1)打开
intmy_open(structinode*inode,structfile*filp)
2)释放
intmy_release(structinode*inode,structfile*filp)
、算法流程图:
四、系统测试与调试分析
系统测试
启动超级管理员模式并输入密码
命令:
sudosu
对源程序进行编译
make
加载驱动程序并查看
insmod和lsmod
显示主设备号
cat/proc/devices
创建节点并查看
mknod/dev/lydev550和cd/dev
编译测试程序
gcc–ot
运行测试函数
./t
进行打开设备操作
1
进行写操作并输入hello
2
进行读操作
3
进行I/O控制
4
进行释放设备操作
5
进行退出操作
6
卸载驱动程序
rmmodlydev
查看日志
dmesg
删除节点并查看
rmlydev和ls
调试分析
最开始的时候没有启用sudo模式,导致很多命令不能执行,启用模式的时候需要输入密码,但是输入密码的时候是不显示东西的以为出错,查阅资料之后才知道是应有的现象。
程序测试一遍之后再次测试很多命令不能执行,原因是第一次测试之后产生的各种文件没有删除,再次测试会显示已存在。
有一次测试程序,不能卸载驱动,用lsmod查看有两个进程使用,后来强制关机才能正常使用,原因不明,以后要加强学习。
五、程序清单
1.主程序
#include<
linux/>
asm/>
#include"
"
#defineSCULL_IOC_MAGIC'
k'
#defineSCULL_IOCRESET_IO(SCULL_IOC_MAGIC,0)
#defineSCULL_IOCSQUANTUM_IOW(SCULL_IOC_MAGIC,1,int)
#defineSCULL_IOCSQSET_IOW(SCULL_IOC_MAGIC,2,int)
#defineSCULL_IOCTQUANTUM_IO(SCULL_IOC_MAGIC,3)
#defineSCULL_IOCTQSET_IO(SCULL_IOC_MAGIC,4)
#defineSCULL_IOCGQUANTUM_IOR(SCULL_IOC_MAGIC,5,int)
#defineSCULL_IOCGQSET_IOR(SCULL_IOC_MAGIC,6,int)
#defineSCULL_IOCQQUANTUM_IO(SCULL_IOC_MAGIC,7)
#defineSCULL_IOCQQSET_IO(SCULL_IOC_MAGIC,8)
#defineSCULL_IOCXQUANTUM_IOWR(SCULL_IOC_MAGIC,9,int)
#defineSCULL_IOCXQSET_IOWR(SCULL_IOC_MAGIC,10,int)
#defineSCULL_IOCHQUANTUM_IO(SCULL_IOC_MAGIC,11)
#defineSCULL_IOCHQSET_IO(SCULL_IOC_MAGIC,12)
#defineSCULL_IOC_MAXNR14
staticintly_major=55;
module_param(ly_major,int,S_IRUGO);
structly_dev*ly_devp;
/*设备结构体指针*/
structcdevcdev;
staticintioctl(structfile*file,unsignedintcmd,unsignedlongarg);
/*文件打开函数*/
intly_open(structinode*inode,structfile*filp)
{
structly_dev*dev;
/*获取次设备号*/
intnum=MINOR(inode->
i_rdev);
if(num>
=MYDEV_NR_DEVS)
return-ENODEV;
dev=&
ly_devp[num];
/*将设备描述结构指针赋值给文件私有数据指针*/
filp->
private_data=dev;
return0;
}
/*文件释放函数*/
intly_release(structinode*inode,structfile*filp)
/*读函数*/
staticssize_tly_read(structfile*filp,char__user*buf,size_tsize,loff_t*ppos)
unsignedlongp=*ppos;
unsignedintcount=size;
intret=0;
structly_dev*dev=filp->
private_data;
/*获得设备结构体指针*/
/*判断读位置是否有效*/
if(p>
=MYDEV_SIZE)
if(count>
MYDEV_SIZE-p)
count=MYDEV_SIZE-p;
/*读数据到用户空间*/
if(copy_to_user(buf,(void*)(dev->
data+p),count))
{
ret=-EFAULT;
}
else
*ppos+=count;
ret=count;
printk(KERN_INFO"
read%dbytes(s)from%lx\n"
count,p);
returnret;
/*写函数*/
staticssize_tly_write(structfile*filp,constchar__user*buf,size_tsize,loff_t*ppos)
/*分析和获取有效的写长度*/
/*从用户空间写入数据*/
if(copy_from_user(dev->
data+p,buf,count))
written%dbytes(s)from%lx\n"
/*I\O控制函数*/
if(_IOC_TYPE(cmd)!
=SCULL_IOC_MAGIC)
return-EFAULT;
if(_IOC_NR(cmd)>
SCULL_IOC_MAXNR)
switch(cmd)
caseSCULL_IOCRESET:
printk("
SCULL_IOCRESET+%lx"
arg);
break;
caseSCULL_IOCSQUANTUM:
/*Set:
argpointstothevalue*/
SCULL_IOCSQUANTUM+%lx"
caseSCULL_IOCTQUANTUM:
/*Tell:
argisthevalue*/
SCULL_IOCTQUANTUM+%lx"
caseSCULL_IOCGQUANTUM:
/*Get:
argispointertoresult*/
SCULL_IOCGQUANTUM+%lx"
caseSCULL_IOCQQUANTUM:
/*Query:
returnit(it'
spositive)*/
SCULL_IOCQQUANTUM+%lx"
caseSCULL_IOCXQUANTUM:
/*eXchange:
useargaspointer*/
SCULL_IOCXQUANTUM+%lx"
caseSCULL_IOCHQUANTUM:
/*sHift:
likeTell+Query*/
SCULL_IOCHQUANTUM+%lx"
return0;
/*seek文件定位函数*/
staticloff_tly_llseek(structfile*filp,loff_toffset,intwhence)
loff_tnewpos;
switch(whence){
case0:
/*SEEK_SET*/
newpos=offset;
case1:
/*SEEK_CUR*/
newpos=filp->
f_pos+offset;
case2:
/*SEEK_END*/
newpos=MYDEV_SIZE-1+offset;
default:
/*can'
thappen*/
return-EINVAL;
if((newpos<
0)||(newpos>
MYDEV_SIZE))
f_pos=newpos;
returnnewpos;
/*文件操作结构体*/
staticconststructfile_operationsly_fops=
.llseek=ly_llseek,
.read=ly_read,
.write=ly_write,
.open=ly_open,
.release=ly_release,
/*设备驱动模块加载函数*/
staticintlydev_init(void)
intresult;
inti;
dev_tdevno=MKDEV(ly_major,0);
/*静态申请设备号*/
if(ly_major)
result=register_chrdev_region(devno,2,"
lydev"
);
else/*动态分配设备号*/
result=alloc_chrdev_region(&
devno,0,2,"
ly_major=MAJOR(devno);
if(result<
0)
returnresult;
/*初始化cdev结构*/
cdev_init(&
cdev,&
ly_fops);
=THIS_MODULE;
=&
ly_fops;
/*注册字符设备*/
cdev_add(&
cdev,MKDEV(ly_major,0),MYDEV_NR_DEVS);
/*为设备描述结构分配内存*/
ly_devp=kmalloc(MYDEV_NR_DEVS*sizeof(structly_dev),GFP_KERNEL);
if(!
ly_devp)/*申请失败*/
result=-ENOMEM;
gotofail_malloc;
memset(ly_devp,0,sizeof(structly_dev));
/*为设备分配内存*/
for(i=0;
i<
MYDEV_NR_DEVS;
i++)
ly_devp[i].size=MYDEV_SIZE;
ly_devp[i].data=kmalloc(MYDEV_SIZE,GFP_KERNEL);
memset(ly_devp[i].data,0,MYDEV_SIZE);
模块加载成功!
\n"
fail_malloc:
unregister_chrdev_region(devno,1);
/*模块卸载函数*/
staticvoidlydev_exit(void)
cdev_del(&
cdev);
/*注销设备*/
kfree(ly_devp);
/*释放设备结构体内存*/unregister_chrdev_region(MKDEV(ly_major,0),2);
/*释放设备号*/
模块卸载成功!
MODULE_LICENSE("
GPL"
module_init(lydev_init);
module_exit(lydev_exit);
2.测试程序
>
#include<
sys/>
#defineMAXBUF20
intmain()
inttestdev;
inti,flag=1,t,len=-1;
charsel;
charbuf[MAXBUF],tmp[MAXBUF];
printf("
1、打开设备\n2、写操作\n3、读操作\n4、I/O控制\n5、释放设备\n6、退出\n"
while
(1){
printf("
请输入要执行的操作:
sel=getchar();
getchar();
switch(sel){
case'
1'
:
testdev=open("
/dev/lydev"
O_RDWR);
if(testdev<
0){
设备打开失败\n"
break;
flag=0;
设备打开成功!
/*case'
2'
if(flag){
请先打开设备!
请输入写入的字符串:
gets(tmp);
len=strlen(tmp);
len=%d\n"
len);
t=write(testdev,tmp,len);
if(t<
0){
写操作失败!
%s字符串写入成功!
tmp);
case'
3'
if(len<
请先进行写操作!
t=read(testdev,buf,len);
读操作失败!
读操作成功!
结果为:
%s\n"
buf);
*/
continue;
请