20145201 20145227 《信息安全系统设计基础》实验四 内核驱动设计入门-模块方式驱动实验
20145201 20145227 《信息安全系统设计基础》实验四 内核驱动设计入门-模块方式驱动实验
北京电子科技学院(BESTI)
实 验 报 告
课程:信息安全系统设计基础 班级:1452
姓名: 鄢曼君 李子璇
学号: 20145227 20145201
成绩: 指导教师:娄嘉鹏 实验日期:2016.11.3
实验密级: 预习程度: 实验时间:10:00-12:30
仪器组次:1 必修/选修:必修 实验序号:04
实验名称:内核驱动设计入门-模块方式驱动实验
实验目的与要求:1.学习在LINUX下进行驱动设计的原理;2.掌握使用模块方式进行驱动开发调试的过程。
实验仪器:
名称 | 型号 | 数量 |
---|---|---|
arm | UP-TECH | 1 |
pc | Windows XP | 1 |
虚拟机 | redhat | 1 |
一、实验过程
1.首先,如同实验一(具体步骤如:实验一),建立实验箱、虚拟机Redhat、WinXP之间的连接,在linux系统中安装arm系统,并对01_demo文件夹中的.c文件进行交叉编译
2.编译驱动模块及测试程序
在 Makefile 中有两种编译方法,可以在本机上使用gcc 也可以使用交叉编译器进行编译,这次实验我们组采用交叉编译器进行编译。如下图:
3.测试驱动程序
我们组使用交叉编译器的话,不需要建立设备节点。
使用用测试程序来进行测试,结果如下图:
二、实验过程中遇到的问题以及解决方案。
1、问题:采用交叉编译器进行编译时出现erro1错误
解决:在/usr/src 下建立一个 linux 连接,使用下面的命令:
2、解决上面问题后,make还是仍然有问题
解决:进入01_demo文件夹中,对Makefilemakefile文件进行修改,使之与指导书上一样(修改的内容较碎,检查了两次才修改完整)
KERNELDIR = /usr/src/linux
#KERNELDIR = /arm2410cl/ kernel/linux-2.4.18-2410cl/
INCLUDEDIR = $(KERNELDIR)/include
#CROSS_COMPILE=armv41-unknown-linux-
AS =$(CROSS_COMPILE)as
LD =$(CROSS_COMPILE)ld
CC =$(CROSS_COMPILE)gcc
CPP =$(CC) -E
AR =$(CROSS_COMPILE)ar
NM =$(CROSS_COMPILE)nm
STRIP =$(CROSS_COMPILE)strip
OBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump
CFLAGS += -I..
CFLAGS += -Wall -O -D__KERNEL__ -DMODULE -I$(INCLUDEDIR)
TARGET = demo
OBJS = demo.o hello.o
SRC = demo.c hello.c
all: $(OBJS)
demo.o: demo.c
$(CC) -c $(CFLAGS) $^ -o $@
hello.o:hello.c
$(CC) -c $(CFLAGS) $^ -o $@
install:
install -d $(INSTALLDIR)
install -c $(TARGET).o $(INSTALLDIR)
clean:
rm -f *.o *~ core .depend
再make之后,不会出现erro。最后执行./testdemo,结果如下:
代码分析:
- test_demo.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>//其中定义了很多宏和比如open,close函数
#include <unistd.h>
#include <sys/ioctl.h>//ioctl函数的头文件
void showbuf(char *buf);
int MAX_LEN=32;
int main()
{
int fd;
int i;
char buf[255];
for(i=0; i<MAX_LEN; i++){//给数组元素依次赋值
buf[i]=i;
}
fd=open("/dev/demo",O_RDWR);//以既可以读又可以写的方式打开文件
if(fd < 0){
printf("####DEMO device open fail####\n");
return (-1);
}
printf("write %d bytes data to /dev/demo \n",MAX_LEN);
showbuf(buf);//先显示一下要写入什么,然后写入
write(fd,buf,MAX_LEN);
printf("Read %d bytes data from /dev/demo \n",MAX_LEN);
read(fd,buf,MAX_LEN);
showbuf(buf);//先读出来字符串到buf中,再显示
ioctl(fd,1,NULL);
ioctl(fd,4,NULL);
close(fd);
return 0;
}
void showbuf(char *buf)
{
int i,j=0;
for(i=0;i<MAX_LEN;i++){
if(i%4 ==0)
printf("\n%4d: ",j++);
printf("%4d ",buf[i]);
}
printf("\n*****************************************************\n");
}
代码中出现的函数都在demo.c代码中进行定义
- ioctl函数的定义:
static int demo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
printk("ioctl runing\n");
switch(cmd){
case 1:printk("runing command 1 \n");break;
case 2:printk("runing command 2 \n");break;
default:
printk("error cmd number\n");break;
}
return 0;
}
ioctl 方法主要用于对设备进行读写之外的其他控制,比如配置设备、进入或退出某种 操作模式,这些操作一般都无法通过read/write 文件操作来完成。