zoukankan      html  css  js  c++  java
  • 信息安全系统设计基础实验四:外设驱动程序设计 20145222黄亚奇 20145213祁玮

    北京电子科技学院(BESTI)

    实 验 报 告

    封 面

    课程:信息安全系统设计基础 班级:1452 姓名: 黄亚奇 祁玮

    学号: 20145222 20145213 成绩指导教师:娄嘉鹏 实验日期:2016.11.24

    实验密级预习程度实验时间:10:10-12:30 仪器组次:22 必修/选修:必修 实验序号:4

    实验名称: 外设驱动程序设计

    实验目的与要求
    1.在掌握基于 S3C2410 的 linux 开发环境的配置和使用的基础上进行交叉编译。
    2.理解驱动程序的一般设计方法。
    3.正确使用连接线等实验仪器,并注意保护实验箱。实验结束之后将实验箱送回。

    正文


    一、实验内容:

    本次实验建立在掌握嵌入式开发平台使用方法和配置方法的基础上,要求使用windows xp,linux(red hat),arm三个系统(即NFS方式);在linux系统中安装arm系统,然后对01_demo文件夹中的.c文件进行交叉编译。

    二、实验原理

    目的:驱动程序是应用程序和硬件之间的一个软件层,为(许多个)应用程序提供硬件的所有功能。为了处理并发的情况,还需要考虑互斥量和锁等机制。

    特点:应用程序一般有一个 main 函数,从头到尾执行一个任务;驱动程序却不同,它没有main函数,通过使用宏module_init(初始化函数名)。

    用法:将初始化函数加入内核全局初始化函数列表中,在内核初始化时执行驱动的初始化函数,从而完成驱动的初始化和注册,之后驱动便停止等待被应用软件调用。驱动程序中有一个宏moudule_exit(退出处理函数名)注册退出处理函数。它在驱动退出时被调用。

    主要代码
    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####
    ");
            return (-1);
        }
        printf("write %d bytes data to /dev/demo 
    ",MAX_LEN);
        showbuf(buf);//先显示一下要写入什么,然后写入
        write(fd,buf,MAX_LEN);
    
        printf("Read %d bytes data from /dev/demo 
    ",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("
    %4d: ",j++);
            printf("%4d ",buf[i]);
        }
        printf("
    *****************************************************
    ");
    }
    

    这段代码很简单,然而会出现一个疑问:write函数、read函数在哪里定义的?ioctl函数优势做什么的?于是我接下来查看了实验指导书的原理部分和demo.c代码。

    其实,上面这段代码中出现的函数都在demo.c代码中有了定义。比如,ioctl函数的定义(严格说来,驱动程序里定义的是方法):

    	static int demo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
    	{
    	    printk("ioctl runing
    ");
    	    switch(cmd){
    	        case 1:printk("runing command 1 
    ");break;
    	        case 2:printk("runing command 2 
    ");break;
    	        default:
    	            printk("error cmd number
    ");break;
    	    }
    	return 0;
    	}
    

    ioctl 方法主要用于对设备进行读写之外的其他控制,比如配置设备、进入或退出某种 操作模式,这些操作一般都无法通过read/write 文件操作来完成。

    三、实验过程&困难排查

    1. 配置实验箱

      同实验一中一样,配置实验环境
      连接arm开发板;
      建立超级终端;
      启动实验平台;
      修改windows xp系统的ip使得它与arm机的ip在同一网段;
      在red hat中安装arm编译器;
      配置环境变量。

    2. 进入01_demo文件夹中,尝试直接make进行自动编译。出现如下图所示的错误。

      按照指导书的提示,进行如下操作建立linux连接:

      	cd /usr/src/
      	ln -sf linux-2.4.20-8 linux
      	ls
      

      (结果)debug linux linux-2.4 linux-2.4.20-8 redhat
      然而,仍然出现上图的错误。

    3. 这时,尝试按照如下内容修改01_demo文件夹中的Makefile

      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
      
    4. 再次进行make之后,系统不再提示错误。然而少了最后对于testdemo.c的编译。于是,我们进行了手动编译。最后执行./testdemo.

    四、实验中遇到的疑惑和困难

    内核地址不正确导致调试不成功,使用命令“whereis”寻找到内核地址为:
    /usr/src/linux-headers-3.2.0-29-generic-pae/kernel # /lib/modules/$(shell uname -r)/build/

  • 相关阅读:
    sdibt 1251 进化树问题
    hdu 2014 位运算
    poj 3254 状态压缩dp
    hdu 5040bfs+优先队列 需要存状态
    zoj 3812 状压dp
    C++标准库:bitset 用法整理&&zoj 3812
    BZOJ 2572 高速公路
    BZOJ 1036 树的统计
    BZOJ 1035 Risk
    BZOJ 1034 泡泡堂
  • 原文地址:https://www.cnblogs.com/huangyaqi/p/6130612.html
Copyright © 2011-2022 走看看