当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]该实验是编写最简单的字符驱动程序,这里的设备也就是一段内存,实现简单的读写功能,并列出常用格式的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/*当卸载设备时打印*/

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

Windows Embedded Compact 7(简称WinCE)是一种专为嵌入式系统设计的操作系统,具有体积小、效率高、可定制性强的特点。在WinCE中设置自动运行软件,通常是为了满足设备在启动后自动执行特定任务的...

关键字: 嵌入式系统 软件 操作系统

今天,小编将在这篇文章中为大家带来Windows 11系统的有关报道,通过阅读这篇文章,大家可以对Windows 11系统具备清晰的认识,主要内容如下。

关键字: Windows 操作系统

全新随插即用方案简化虚拟化实时IIoT平台的设置

关键字: 计算机模块 IIoT 操作系统

目前,HarmonyOS NEXT星河预览版已经正式面向开发者开放申请,面向鸿蒙原生应用及元服务开发者提供的集成开发环境——DevEco Studio也迎来功能更细化的4.1版本。

关键字: HarmonyOS 操作系统

华为P40是一款备受关注的高端智能手机,搭载了华为自研的鸿蒙操作系统。鸿蒙系统作为华为自主研发的操作系统,具有高度的可定制性和扩展性,能够为用户带来全新的使用体验。本文将详细介绍华为P40鸿蒙系统的升级方法,帮助用户更好...

关键字: 华为P40 智能手机 操作系统

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机

Linux操作系统是一套免费使用和自由传播的类Unix操作系统,通常被称为GNU/Linux。它是由林纳斯·托瓦兹在1991年首次发布的,并基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Lin...

关键字: Linux 操作系统

华为鸿蒙系统作为华为推出的全新一代操作系统,自发布以来备受关注。本文将对华为鸿蒙系统的实际体验进行详细评测,旨在帮助读者了解该系统的优缺点。

关键字: 华为 鸿蒙系统 操作系统

随着华为鸿蒙OS系统的发布,越来越多的人开始关注这一全新的操作系统。鸿蒙OS系统的界面设计作为用户体验的重要组成部分,也备受关注。本文将详细介绍鸿蒙操作系统界面的设计理念、特点以及与其他系统的对比。

关键字: 华为鸿蒙 操作系统 界面设计
关闭
关闭