zoukankan      html  css  js  c++  java
  • 【驱动】linux驱动程序开发及环境搭建

    1.mystery引入

       1)设备驱动程序对外提供如下的功能
           1)设备初始化:对硬件设备进行初始化操作
           2)数据交换:数据交换包括由内核层向硬件层传送数据、从硬件层读取数据到内核层;
                         应用程序向设备文件传送数据、设备文件向应用程序回送数据
           3)设备请求与检测:检测各硬件设备的各种参数信息、错误信息
           4)设备释放:设备使用完后的资源释放
       2)驱动一般分为字符设备驱动、块设备驱动和网络设备驱动
           1)字符设备驱动:可以按字节操作的方式对设备文件进行存取,一般对应慢速设备,例如串口设备
           2)块设备驱动:是按数据块的方式对设备文件进行访问,一般对应高速设备,例如DMA
           3)网络设备驱动:是面向网卡设备,用于处理网络报文的发送与接收
       3)字符设备与块设备均可以通过访问文件的方式进行操作,二者唯一的不同的是Linux对于它们的数据管理方式的不同。
       4)应用程序对字符设备的I/O操作,会直接传送到内核驱动层,而块设备的操作,则是需要借助于中间的缓存区,以间接的方式进行数据交换。

     


    2.环境搭建及测试
       1)下载对应版本的内核源码包
       2)因为现在对内核还不是很熟,加上内核源码比较大,所以我先下一个内核的开发包
       3)终端:

    sudo yum install kernel-devel

       4)如图

     

       5)环境搭建好了,问题又来了。。uname -r 的结果和我系统内核版本不一样。。

       这里我直接用我系统的内核版本号作测试了,我的系统内核版本是3.6.10-2.fc17.i686

       6)第一个版本的Makefile文件如下:

    obj-m:=chardev.o
    KDIR:=/lib/modules/3.6.10-2.fc17.i686/build
    SRCPWD:=$(shell pwd)
    all:
        make -C $(KDIR) M=$(SRCPWD) modules
    clean:
        rm -rf chardev.o

       7)编译结果如图


    3.驱动验证
       1)设备安装
           当安装驱动时,又出现错误了,纠结。。错误:编译使用的内核和当前系统的内核不一样!
       2)反思
          1)这时我才想起,前断时间我更新了下系统,当时把系统内核升级到了3.6,但是无法进入系统,所以我直接把grub项的3.6内核的引导删掉了,现在打开grub查找错误
          2)grub中关于内核3.6开机引导项内容如下:

          3)看了这断代码,对升级后新内核无法进入系统的原因就明了了,我在想,为什么升级内核的时候没有制作initrd
          4)于是我退后一步,自己制作initrd,终端下:

    mkinitrd initrd-3.6.6 3.6.6

          (先切换到linux-3.6.6的上一级目录),由于系统升级内核时已经编译过内核镜像和内核模块了,并且也已经安装过内核模块了
          5)所以我要做的就是将initrd复制到boot目录下,然后再添加新的引导项
          6)在上图 echo 'Loading Fedora (3.6.10-2.fc17.i686)' 的下一行添加自己制作的initrd,代码:initrd/boot/initrd-3.6.10-2.fc17.i686.img
          7)重启电脑,OK,成功引导进行新内核,但是有很多地方不尽人意
             1)电脑需要重装显卡驱动,分辨率太低
             2)无法联网,需要重装网卡驱动
             3)无法挂载FAT格式的盘
             4)无法挂载NTFS格式的盘
          8)因此,我还是决定用3.3的内核,只是在3.6下作驱动程序测试


    4.驱动测试
       1)如图所示:

       2)驱动设备创建好后,编写一个程序验证下

       3)效果如图:

       4)这里出现OPEN错误和READ错误,但是却又读出了驱动函数的内容,表示驱动还是成功的,由于这个内核开始出现的不尽人意,也没有去调试这个错误的原因


    5.驱动源代码

    #include <linux/kernel.h>
    #include <linux/fs.h>                
    #include <linux/module.h>
    #include <asm/uaccess.h>             
    #include <linux/cdev.h>               
    static int char_read(struct file *filp,char __user *buffer,size_t,loff_t *);      
    static int char_open(struct inode *,struct file *);                                    
    static int char_write(struct file *filp,const char __user *buffer,size_t ,loff_t*);
    static int char_release(struct inode *,struct file *);                                 
    static int device_open_count;                   
    static int major;
    static const struct file_operations file_ops =
    {
        .read = char_read,
        .write = char_write,
        .open = char_open,
        .release = char_release,
    };
    static int __init char_init(void)
    {
        int value;
        major = 0;
        value = register_chrdev(major, "chardev", &file_ops);
        if (value < 0)
        {
            printk("无法注册设备");
            return value;
        }
        if (major == 0)
            major = value;
        return 0;
    }
    static int char_open(struct inode *inode,struct file *file)
    {
        if(device_open_count == 0)
            device_open_count++;
        else
        {
            printk("设备已经被打开
    ");
            return -1;
        }
        try_module_get(THIS_MODULE);
        return 0;
    }
    static int char_release(struct inode *inode,struct file *file)
    {
        device_open_count--;
        module_put(THIS_MODULE);
        return 0;
    }
    static int char_read(struct file *filp,char __user *buffer,size_t length,loff_t *offset)
    {
        if(length < 0)
            return -1;
        else if(length > 12)
            length = 12;
        if(copy_to_user(buffer,"Hello Linux!",length))
            return length;
        return -1;
    }
    static int char_write(struct file *filp,const char __user  *buffer,size_t length,loff_t *offset)
    {
        return 0;
    }
    static void __exit module_close(void)
    {
        unregister_chrdev(major, "chardev");
    }
    module_init(char_init);
    module_exit(module_close);

    6.Makefile源代码

    obj-m:=chardev.o
    KDIR:=/lib/modules/$(shell uname -r)/build
    SRCPWD:=$(shell pwd)
    all:
        make -C $(KDIR) M=$(SRCPWD) modules
    clean:
        rm -rf chardev.o

    7.测试程序源代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    int main(void)
    {
        int testdev;
        int i,rf=0;
        char buf[15];
        memset(buf, 0, sizeof(buf));
        testdev = open("/dev/chardev",O_RDWR);
        if ( testdev == -1 )
        {
            perror("open
    ");
            exit(0);
        }
        rf=read(testdev,buf,11);
        if(rf<0)
            perror("read error
    ");
        printf("R:%s
    ",buf);
        close(testdev);
        return 0;
    }

    本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1155153

  • 相关阅读:
    Python入门练习实例
    关于“华为”的大数据分析
    numpy 安装
    JDBC URL格式定制
    Tomcat下JDBC连接样例
    命令行模式(CMD)下mysql查询中文显示乱码问题
    JDBC mysql驱动
    模态框点击空白处不关闭
    js动态绑定click事件时function传参问题
    云计算对传统软件工程的影响
  • 原文地址:https://www.cnblogs.com/lcw/p/3159505.html
Copyright © 2011-2022 走看看