zoukankan      html  css  js  c++  java
  • 2018-2019-1 20165207 20165209 20165215 实验四 外设驱动程序设计

    2018-2019-1 20165207 20165209 20165215 实验四 外设驱动程序设计

    实验内容和要求

    • 1.外设驱动程序设计-1
      学习资源中全课中的“hqyj.嵌入式Linux应用程序开发标准教程.pdf”中的第十一章
      提交康奈尔笔记的照片(可以多张)

    • 2.外设驱动程序设计-2
      在Ubuntu完成资源中全课中的“hqyj.嵌入式Linux应用程序开发标准教程.pdf”中的第十一章的test试验
      提交编译,加载模块,卸载模块,测试运行的截图(要多张,全屏,体现学号信息)

    实验步骤

    (一)康奈尔笔记

    (二) 在Ubuntu完成资源中全课中的“hqyj.嵌入式Linux应用程序开发标准教程.pdf”中的第十一章的test试验

    • 按照书上要求,建立驱动代码源程序

         /*test_drv.c*/
        #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>
        #define TEST_DEVICE_NAME "test_dev"
        #define BUFF_SZ 1024
        static struct cdev test_dev;
        unsigned int major = 0;
        static char *data = NULL;
        static ssize_t test_read(struct file *file, char *buf, size_t count, loff_t *f_pos)
        {
            int len;
            if (count < 0)
            {
                return -EINVAL;
            }
            len = strlen(data);
            count = (len > count)?count:len;
            if (copy_to_user(buf, data, count))
            {
                return -EFAULT;
            }
            return count;
        }
        static ssize_t test_write(struct file *file, const char *buffer, size_t count, 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;
            }
            return count;
        }
        static int test_open(struct inode *inode, struct file *file)
        {
            printk("This is open operation.
      ");
            data = (char*)kmalloc(sizeof(char) * BUFF_SZ, GFP_KERNEL);
            if (!data)
            {
                return -ENOMEM;
            }
            return 0;
        }
        static int test_release(struct inode *inode, struct file *file)
        {
            printk("This is release operation.
      ");
            if (data)
            {
                kfree(data);
                data = NULL;
            }
            return 0;
        }
        static void test_setup_cdev(struct cdev *dev, int minor, struct file_operation *fops)
        {
            int err, 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 %d adding test %d", err, minor);
            }
        }
        static struct file_operations test_fops =
        {
            .owner = THIS_MODULE,
            .read = test_read,
            .write = test_write,
            .open = test_open,
            .release = test_release,
        };
        int init_module(void)
        {
            int result;
            dev_t dev = MKDEV(major, 0);
            if (major)
            {
                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 "Test device: unable to get major %d
      ",major);
                return result;
            }
            test_setup_cdev(&test_dev, 0, &test_fops);
            printk("The major of the test device is %d
      ", major);
            return 0;
        }
        void cleanup_module(void)
        {
            cdev_del(&test_dev);
            unregister_chrdev_region(MKDEV(major, 0), 1);
            printk("Test device uninstalled.
      ");
        }
      
    • Makefile文件

              ifeq ($(KERNELRELEASE),)
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)
        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: modules modules_install clean
        else
            obj-m := test_drv.o
        endif
      
    • 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 $* || exit 1
        # 查到创建设备的主设备号
        major='cat /proc/devices | awk "\$2=="$device" {print \$1}"'
        # 创建设备文件节点
        mknod /dev/${device} c $major 0
        # 设备文件属性
        chgrp $group /dev/${device}
        chomd $mode /dev/${device}
      
    • test_drv_unload脚本

        # !/bin/sh
        module="test_drv"
        device="test_dev"
        # 卸载驱动模块
        /sbin/rmmod $module $* || exit 1
        # 删除设备文件
        rm -f /dev/${device}
        exit 0
      
    • 测试代码test.c

            /* 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>
        #define     TEST_DEVICE_FILENAME        "/dev/test_dev"
        #define     BUFF_SZ             1024
      
        int main()
        {
            int fd, nwrite, nread;
            char buff[BUFF_SZ];
            fd = open(TEST_DEVICE_FILENAME, O_RDWR);
            if (fd < 0)
            {
                perror("open");
                exit(1);
            }
            do
            {
                printf("Input some words to kernel(enter 'quit' to exit):");
                memset(buff, 0, BUFF_SZ);
                if (fgets(buff, BUFF_SZ, stdin) == NULL)
                {
                    perror("fgets");
                    break;
                }
                buff[strlen(buff) - 1] = '';
                if (write(fd, buff, strlen(buff)) < 0)
                {
                    perror("write");
                    break;
                }
                if (read(fd, buff, BUFF_SZ) < 0)
                {
                    perror("read");
                    break;
                }
                else
                {
                    printf("The read string is from kernel:%s
      ", buff);
                }
            } while(strncmp(buff, "quit", 4));
            close(fd);
            exit(0);
        }
      
    • 编译test.c

    • 加载脚本chmod +x test_drv_load

    • 运行脚本./test_drv_load

    • 运行testsudo ./test

    • 卸载脚本chmod +x test_drv_unload

    • 运行脚本./test_drv_unload

    • 运行结果

    实验中的问题及解决过程

    • 问题1:无法在自己的虚拟机上运行成功

    • 解决办法:内核版本问题,用老师给的虚拟机。

    • 问题2:运行Makefile时报错(如下图)

    • 解决办法:输入make clean;make代替make

    • 问题3:运行脚本出现错insmod: error inserting './test_drv.ko': -1 File exists

    • 解决办法:删除之前运行的全部文件,重启电脑;还可以参考链接

    新学到的知识

    • 如何通过文件属性查看设备及其分类
    • 嵌入式系统属于是一个用于控制、监视或者辅助操作机器和设备的装置
    • 学习字符设备驱动编程
    • 了解分配设备号、设备注册、内核操作的相关函数的使用方法
  • 相关阅读:
    hive与hbase整合
    待重写
    hive DML
    【知识强化】第六章 总线 6.1 总线概述
    【知识强化】第五章 中央处理器 5.1 CPU的功能和基本结构
    【知识强化】第四章 指令系统 4.3 CISC和RISC的基本概念
    【知识强化】第四章 指令系统 4.2 指令寻址方式
    【知识强化】第四章 指令系统 4.1 指令格式
    【知识强化】第三章 存储系统 3.6 高速缓冲存储器
    【知识强化】第三章 存储系统 3.5 双口RAM和多模块存储器
  • 原文地址:https://www.cnblogs.com/tutu233/p/10032960.html
Copyright © 2011-2022 走看看