当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]该实验是编写最简单的字符驱动程序,这里的设备也就是一段内存,实现简单的读写功能,并列出常用格式的Makefile以及驱动的加载和卸载脚本。读者可以熟悉字符设备驱动的整个编写流程。

11.7实验内容——test驱动1.实验目的

该实验是编写最简单的字符驱动程序,这里的设备也就是一段内存,实现简单的读写功能,并列出常用格式的Makefile以及驱动的加载和卸载脚本。读者可以熟悉字符设备驱动的整个编写流程。

2.实验内容

该实验要求实现对虚拟设备(一段内存)的打开、关闭、读写的操作,并要通过编写测试程序来测试虚拟设备及其驱动运行是否正常。

3.实验步骤

(1)编写代码。

这个简单的驱动程序的源代码如下所示:

/*test_drv.c*/

#include<linux/module.h>

#include<linux/init.h>

#include<linux/fs.h>

#include<linux/kernel.h>

#include<linux/slab.h>

#include<linux/types.h>

#include<linux/errno.h>

#include<linux/cdev.h>

#include<asm/uaccess.h>

#defineTEST_DEVICE_NAME"test_dev"

#defineBUFF_SZ1024

/*全局变量*/

staticstructcdevtest_dev;

unsignedintmajor=0;

staticchar*data=NULL;

/*读函数*/

staticssize_ttest_read(structfile*file,

char*buf,size_tcount,loff_t*f_pos)

{

intlen;

if(count<0)

{

return-EINVAL;

}

len=strlen(data);

count=(len>count)?count:len;

if(copy_to_user(buf,data,count))/*将内核缓冲的数据拷贝到用户空间*/

{

return-EFAULT;

}

returncount;

}

/*写函数*/

staticssize_ttest_write(structfile*file,constchar*buffer,

size_tcount,loff_t*f_pos)

{

if(count<0)

{

return-EINVAL;

}

memset(data,0,BUFF_SZ);

count=(BUFF_SZ>count)?count:BUFF_SZ;

if(copy_from_user(data,buffer,count))/*将用户缓冲的数据复制到内核空间*/

{

return-EFAULT;

}

returncount;

}

/*打开函数*/

staticinttest_open(structinode*inode,structfile*file)

{

printk("Thisisopenoperation\n");

/*分配并初始化缓冲区*/

data=(char*)kmalloc(sizeof(char)*BUFF_SZ,GFP_KERNEL);

if(!data)

{

return-ENOMEM;

}

memset(data,0,BUFF_SZ);

return0;

}

/*关闭函数*/

staticinttest_release(structinode*inode,structfile*file)

{

printk("Thisisreleaseoperation\n");

if(data)

{

kfree(data);/*释放缓冲区*/

data=NULL;/*防止出现野指针*/

}

return0;

}

/*创建、初始化字符设备,并且注册到系统*/

staticvoidtest_setup_cdev(structcdev*dev,intminor,

structfile_operations*fops)

{

interr,devno=MKDEV(major,minor);

cdev_init(dev,fops);

dev->owner=THIS_MODULE;

dev->ops=fops;

err=cdev_add(dev,devno,1);

if(err)

{

printk(KERN_NOTICE"Error%daddingtest%d",err,minor);

}

}

/*虚拟设备的file_operations结构*/

staticstructfile_operationstest_fops=

{

.owner=THIS_MODULE,

.read=test_read,

.write=test_write,

.open=test_open,

.release=test_release,

};

/*模块注册入口*/

intinit_module(void)

{

intresult;

dev_tdev=MKDEV(major,0);

if(major)

{/*静态注册一个设备,设备号先前指定好,并设定设备名,用cat/proc/devices来查看*/

result=register_chrdev_region(dev,1,TEST_DEVICE_NAME);

}

else

{

result=alloc_chrdev_region(&dev,0,1,TEST_DEVICE_NAME);

}

if(result<0)

{

printk(KERN_WARNING"Testdevice:unabletogetmajor%d\n",major);

returnresult;

}

test_setup_cdev(&test_dev,0,&test_fops);

printk("Themajorofthetestdeviceis%d\n",major);

return0;

}

/*卸载模块*/

voidcleanup_module(void)

{

cdev_del(&test_dev);

unregister_chrdev_region(MKDEV(major,0),1);

printk("Testdeviceuninstalled\n");

}

(2)编译代码。

虚拟设备的驱动程序的Makefile如下所示:

ifeq($(KERNELRELEASE),)

KERNELDIR?=/lib/modules/$(shelluname-r)/build/*内核代码编译路径*/

PWD:=$(shellpwd)

modules:

$(MAKE)-C$(KERNELDIR)M=$(PWD)modules

modules_install:

$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_install

clean:

rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versions

.PHONY:modulesmodules_installclean

else

obj-m:=test_drv.o/*将生成的模块为test_drv.ko*/

endif

(3)加载和卸载模块。

通过下面两个脚本代码分别实现驱动模块的加载和卸载。

加载脚本test_drv_load如下所示:

#!/bin/sh

#驱动模块名称

module="test_drv"

#设备名称。在/proc/devices中出现

device="test_dev"

#设备文件的属性

mode="664"

group="david"

#删除已存在的设备节点

rm-f/dev/${device}

#加载驱动模块

/sbin/insmod-f./$module.ko$*||exit1

#查到创建设备的主设备号

major=`cat/proc/devices|awk"\\$2==\"$device\"{print\\$1}"`

#创建设备文件节点

mknod/dev/${device}c$major0

#设置设备文件属性

chgrp$group/dev/${device}

chmod$mode/dev/${device}

卸载脚本test_drv_unload如下所示:

#!/bin/sh

module="test_drv"

device="test_dev"

#卸载驱动模块

/sbin/rmmod$module$*||exit1

#删除设备文件

rm-f/dev/${device}

exit0

(6)编写测试代码。

最后一步是编写测试代码,也就是用户空间的程序,该程序调用设备驱动来测试驱动的运行是否正常。以下实例只实现了简单的读写功能,测试代码如下所示:

/*test.c*/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<sys/stat.h>

#include<sys/types.h>

#include<unistd.h>

#include<fcntl.h>

#defineTEST_DEVICE_FILENAME"/dev/test_dev"/*设备文件名*/

#defineBUFF_SZ1024/*缓冲大小*/

intmain()

{

intfd,nwrite,nread;

charbuff[BUFF_SZ];/*缓冲区*/

/*打开设备文件*/

fd=open(TEST_DEVICE_FILENAME,O_RDWR);

if(fd<0)

{

perror("open");

exit(1);

}

do

{

printf("Inputsomewordstokernel(enter'quit'toexit):");

memset(buff,0,BUFF_SZ);

if(fgets(buff,BUFF_SZ,stdin)==NULL)

{

perror("fgets");

break;

}

buff[strlen(buff)-1]='\0';

if(write(fd,buff,strlen(buff))<0)/*向设备写入数据*/

{

perror("write");

break;

}

if(read(fd,buff,BUFF_SZ)<0)/*从设备读取数据*/

{

perror("read");

break;

}

else

{

printf("Thereadstringisfromkernel:%s\n",buff);

}

}while(strncmp(buff,"quit",4));

close(fd);

exit(0);

}

4.实验结果

首先在虚拟设备驱动源码目录下编译并加载驱动模块。

$makeclean;make

$./test_drv_load

接下来,编译并运行测试程序

$gcc–otesttest.c

$./test

测试程序运行效果如下:

Inputsomewordstokernel(enter'quit'toexit):Hello,everybody!

Thereadstringisfromkernel:Hello,everybody!/*从内核读取的数据*/

Inputsomewordstokernel(enter'quit'toexit):Thisisasimpledriver

Thereadstringisfromkernel:Thisisasimpledriver

Inputsomewordstokernel(enter'quit'toexit):quit

Thereadstringisfromkernel:quit

最后,卸载驱动程序

$./test_drv_unload

通过dmesg命令可以查看内核打印的信息:

$dmesg|tail–n10

……

Themajorofthetestdeviceis250/*当加载模块时打印*/

Thisisopenoperation/*当打开设备时打印*/

Thisisreleaseoperation/*关闭设备时打印*/

Testdeviceuninstalled/*当卸载设备时打印*/

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭