linux字符设备驱动课程设计报告.docx

上传人:b****2 文档编号:3338252 上传时间:2023-05-05 格式:DOCX 页数:22 大小:287.31KB
下载 相关 举报
linux字符设备驱动课程设计报告.docx_第1页
第1页 / 共22页
linux字符设备驱动课程设计报告.docx_第2页
第2页 / 共22页
linux字符设备驱动课程设计报告.docx_第3页
第3页 / 共22页
linux字符设备驱动课程设计报告.docx_第4页
第4页 / 共22页
linux字符设备驱动课程设计报告.docx_第5页
第5页 / 共22页
linux字符设备驱动课程设计报告.docx_第6页
第6页 / 共22页
linux字符设备驱动课程设计报告.docx_第7页
第7页 / 共22页
linux字符设备驱动课程设计报告.docx_第8页
第8页 / 共22页
linux字符设备驱动课程设计报告.docx_第9页
第9页 / 共22页
linux字符设备驱动课程设计报告.docx_第10页
第10页 / 共22页
linux字符设备驱动课程设计报告.docx_第11页
第11页 / 共22页
linux字符设备驱动课程设计报告.docx_第12页
第12页 / 共22页
linux字符设备驱动课程设计报告.docx_第13页
第13页 / 共22页
linux字符设备驱动课程设计报告.docx_第14页
第14页 / 共22页
linux字符设备驱动课程设计报告.docx_第15页
第15页 / 共22页
linux字符设备驱动课程设计报告.docx_第16页
第16页 / 共22页
linux字符设备驱动课程设计报告.docx_第17页
第17页 / 共22页
linux字符设备驱动课程设计报告.docx_第18页
第18页 / 共22页
linux字符设备驱动课程设计报告.docx_第19页
第19页 / 共22页
linux字符设备驱动课程设计报告.docx_第20页
第20页 / 共22页
亲,该文档总共22页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

linux字符设备驱动课程设计报告.docx

《linux字符设备驱动课程设计报告.docx》由会员分享,可在线阅读,更多相关《linux字符设备驱动课程设计报告.docx(22页珍藏版)》请在冰点文库上搜索。

linux字符设备驱动课程设计报告.docx

linux字符设备驱动课程设计报告

一、课程设计目的

Linux系统的开源性使其在嵌入式系统的开发中得到了越来越广泛的应用,但其本身并没有对种类繁多的硬件设备都提供现成的驱动程序,特别是由于工程应用中的灵活性,其驱动程序更是难以统一,这时就需开发一套适合于自己产品的设备驱动。

对用户而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以像对其它文件一样对此设备文件进行操作。

通过这次课程设计可以了解linux的模块机制,懂得如何加载模块和卸载模块,进一步熟悉模块的相关操作。

加深对驱动程序定义和设计的了解,了解linux驱动的编写过程,提高自己的动手能力。

二、课程设计内容与要求

字符设备驱动程序

1、设计目的:

掌握设备驱动程序的编写、编译和装载、卸载方法,了解设备文件的创建,并知道如何编写测试程序测试自己的驱动程序是否能够正常工作

2、设计要求:

1)编写一个简单的字符设备驱动程序,该字符设备包括打开、读、写、I\O控制与释放五个基本操作。

2)编写一个测试程序,测试字符设备驱动程序的正确性。

3)要求在实验报告中列出Linux内核的版本与内核模块加载过程。

三、系统分析与设计

1、系统分析

系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。

设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。

设备驱动程序是内核的一部分,它完成以下的功能:

1、对设备初始化和释放;

2、把数据从内核传送到硬件和从硬件读取数据;

3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据;

4、检测和处理设备出现的错误。

字符设备提供给应用程序的是一个流控制接口,主要包括open、close(或release)、read、write、ioctl、poll和mmap等。

在系统中添加一个字符设备驱动程序,实际上就是给上述操作添加对应的代码。

对于字符设备和块设备,Linux内核对这些操作进行了统一的抽象,把它们定义在结构体file_operations中。

2、系统设计:

、模块设计:

 

 

数据结构说明

字符设备驱动主要应用了三种数据结构:

①file_operations结构,这是设备驱动程序所提供的一组用一个结构向系统进行说明的入口点;②file结构,主要用于与文件系统对应的设备驱动程序。

代表一个打开的文件,它由内核在open时创建,并传递给在该文件上进行操作的所有函数,直到碰到最后的close函数。

在文件的所有实例都被关闭之后,内核会释放这个数据结构;③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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

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

{

return0;

}

/*读函数*/

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)

return0;

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)

{

unsignedlongp=*ppos;

unsignedintcount=size;

intret=0;

structly_dev*dev=filp->private_data;/*获得设备结构体指针*/

/*分析和获取有效的写长度*/

if(p>=MYDEV_SIZE)

return0;

if(count>MYDEV_SIZE-p)

count=MYDEV_SIZE-p;

/*从用户空间写入数据*/

if(copy_from_user(dev->data+p,buf,count))

ret=-EFAULT;

else

{

*ppos+=count;

ret=count;

printk(KERN_INFO"written%dbytes(s)from%lx\n",count,p);

}

returnret;

}

/*I\O控制函数*/

staticintioctl(structfile*file,unsignedintcmd,unsignedlongarg)

{

if(_IOC_TYPE(cmd)!

=SCULL_IOC_MAGIC)

{

return-EFAULT;

}

if(_IOC_NR(cmd)>SCULL_IOC_MAXNR)

{

return-EFAULT;

}

switch(cmd)

{

caseSCULL_IOCRESET:

printk("SCULL_IOCRESET+%lx",arg);

break;

caseSCULL_IOCSQUANTUM:

/*Set:

argpointstothevalue*/

printk("SCULL_IOCSQUANTUM+%lx",arg);

break;

caseSCULL_IOCTQUANTUM:

/*Tell:

argisthevalue*/

printk("SCULL_IOCTQUANTUM+%lx",arg);

break;

caseSCULL_IOCGQUANTUM:

/*Get:

argispointertoresult*/

printk("SCULL_IOCGQUANTUM+%lx",arg);

break;

caseSCULL_IOCQQUANTUM:

/*Query:

returnit(it'spositive)*/

printk("SCULL_IOCQQUANTUM+%lx",arg);

break;

caseSCULL_IOCXQUANTUM:

/*eXchange:

useargaspointer*/

printk("SCULL_IOCXQUANTUM+%lx",arg);

break;

caseSCULL_IOCHQUANTUM:

/*sHift:

likeTell+Query*/

printk("SCULL_IOCHQUANTUM+%lx",arg);

break;

}

return0;

}

/*seek文件定位函数*/

staticloff_tly_llseek(structfile*filp,loff_toffset,intwhence)

{

loff_tnewpos;

switch(whence){

case0:

/*SEEK_SET*/

newpos=offset;

break;

case1:

/*SEEK_CUR*/

newpos=filp->f_pos+offset;

break;

case2:

/*SEEK_END*/

newpos=MYDEV_SIZE-1+offset;

break;

default:

/*can'thappen*/

return-EINVAL;

}

if((newpos<0)||(newpos>MYDEV_SIZE))

return-EINVAL;

filp->f_pos=newpos;

returnnewpos;

}

/*文件操作结构体*/

staticconststructfile_operationsly_fops=

{

.owner=THIS_MODULE,

.llseek=ly_llseek,

.read=ly_read,

.write=ly_write,

.open=ly_open,

.release=ly_release,

.unlocked_ioctl=ioctl,

};

/*设备驱动模块加载函数*/

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,"lydev");

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

{

ly_devp[i].size=MYDEV_SIZE;

ly_devp[i].data=kmalloc(MYDEV_SIZE,GFP_KERNEL);

memset(ly_devp[i].data,0,MYDEV_SIZE);

}

printk("模块加载成功!

\n");

return0;

fail_malloc:

unregister_chrdev_region(devno,1);

returnresult;

}

/*模块卸载函数*/

staticvoidlydev_exit(void)

{

cdev_del(&cdev);/*注销设备*/

kfree(ly_devp);/*释放设备结构体内存*/unregister_chrdev_region(MKDEV(ly_major,0),2);/*释放设备号*/

printk("模块卸载成功!

\n");

}

MODULE_LICENSE("GPL");

module_init(lydev_init);

module_exit(lydev_exit);

2.测试程序

#include<>

#include

#include<>

#include<>

#include

#include

#include<>

#include<>

#defineMAXBUF20

#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

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

printf("设备打开失败\n");

break;

}

flag=0;

printf("设备打开成功!

\n"

break;

/*case'2':

if(flag){

printf("请先打开设备!

\n");

break;

}

printf("请输入写入的字符串:

");

gets(tmp);

len=strlen(tmp);

printf("len=%d\n",len);

t=write(testdev,tmp,len);

if(t<0){

printf("写操作失败!

\n");

break;

}

printf("%s字符串写入成功!

\n",tmp);

break;

case'3':

if(flag){

printf("请先打开设备!

\n");

break;

}

if(len<0){

printf("请先进行写操作!

\n");

break;

}

t=read(testdev,buf,len);

if(t<0){

printf("读操作失败!

\n");

break;

}

printf("读操作成功!

结果为:

%s\n",buf);

break;*/

case'2':

if(flag){

printf("请先打开设备!

\n");

continue;

}

printf("请

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2