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

  • 相关阅读:
    UVA1349 Optimal Bus Route Design 最优巴士路线设计
    POJ3565 Ants 蚂蚁(NEERC 2008)
    UVA1663 Purifying Machine 净化器
    UVa11996 Jewel Magic 魔法珠宝
    NEERC2003 Jurassic Remains 侏罗纪
    UVA11895 Honorary Tickets
    gdb调试coredump(使用篇)
    使用 MegaCLI 检测磁盘状态并更换磁盘
    员工直接坦诚直来直去 真性情
    山东浪潮超越3B4000申泰RM5120-L
  • 原文地址:https://www.cnblogs.com/lcw/p/3159505.html
Copyright © 2011-2022 走看看