• Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是...

    Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。

    一、Linuxdevice driver 的概念

      系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 
      1。对设备初始化和释放。
      2。把数据从内核传送到硬件和从硬件读取数据。
      3。读取应用程序传送给设备文件的数据和回送应用程序请求的数据。
      4。检测和处理设备出现的错误。

      在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。
      已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。 
      最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。
      读/写时,它首先察看缓冲区的内容,如果缓冲区的数据 
      如何编写Linux操作系统下的设备驱动程序

      二、实例剖析

    我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。
    #define  __NO_VERSION__

    #include <linux/modules.h>

    #include <linux/version.h>

      charkernel_version [] = UTS_RELEASE;

      这一段定义了一些版本信息,虽然用处不是很大,但也必不可少。Johnsonm说所有的驱动程序的开头都要包含<linux/config.h>,一般来讲最好使用。 
      由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用,如 open,read,write,close…, 注意,不是fopen,fread,但是如何把系统调用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构: 
    struct file_operations

    {

    int (*seek)(struct inode * ,structfile *, off_t ,int);

    int(*read) (struct inode * ,struct file *, char ,int);

    int(*write) (struct inode * ,struct file *, off_t ,int);

    int(*readdir) (struct inode * ,struct file *, struct dirent * ,int);

    int(*select) (struct inode * ,struct file *, int ,select_table*);

    int(*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);

    int(*mmap) (struct inode * ,struct file *, struct vm_area_struct *);

    int(*open) (struct inode * ,struct file *);

    int(*release) (struct inode * ,struct file *);

    int(*fsync) (struct inode * ,struct file *);

    int(*fasync) (struct inode * ,struct file *,int);

    int(*check_media_change) (struct inode * ,struct file *);

    int(*revalidate) (dev_t dev);

    }


      这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域。 
      下面就开始写子程序。 
    #include <linux/types.h>

    #include<linux/fs.h>

    #include<linux/mm.h>

    #include<linux/errno.h>

    #include<asm/segment.h>

    unsignedint test_major = 0;

    staticint read_test(struct inode *node,struct file *file,char *buf,int count)

    {

    intleft;

    if(verify_area(VERIFY_WRITE,buf,count) == -EFAULT )

    return-EFAULT;

    for(left= count ; left > 0 ; left--)

    {

    __put_user(1,buf,1);

    buf++;

    }

    returncount;

    }


    这个函数是为read调用准备的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf 是read调用的一个参数。它是用户进程空间的一个地址。但是在read_test被调用时,系统进入核心态。所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。

    staticint write_tibet(struct inode *inode,struct file *file,const char *buf,int count)

    {

    returncount;

    }

     

    staticint open_tibet(struct inode *inode,struct file *file )

    {

    MOD_INC_USE_COUNT;

    return0;

    }

     

    staticvoid release_tibet(struct inode *inode,struct file *file )

    {

    MOD_DEC_USE_COUNT;

    }


      这几个函数都是空操作。实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。 
    struct file_operations test_fops = {

    NULL,

    read_test,

    write_test,

    NULL, /* test_readdir */

    NULL,

    NULL, /* test_ioctl */

    NULL, /* test_mmap */

    open_test,

    release_test,

    NULL, /* test_fsync */

    NULL, /* test_fasync */

    /*nothing more,fill with NULLs */

    }; 

      设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入内核。驱动程序可以按照两种方式编译。一种是编译进kernel,另一种是编译成模块(modules),如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。 
    int init_module(void)

    {

    intresult;

    result= register_chrdev(0,"test", &test_fops);

    if(result < 0) {

    printk(KERN_INFO"test: can't get major number\n");

    returnresult;

    }

    if(test_major == 0) test_major = result; /* dynamic */

    return0;

    }


      在用insmod命令将编译好的模块调入内存时,init_module 函数被调用。在这里,init_module只做了一件事,就是向系统的字符设备表登记了一个字符设备。register_chrdev需要三个参数,参数一是希望获得的设备号,如果是零的话,系统将选择一个没有被占用的设备号返回。参数二是设备文件名,参数三用来登记驱动程序实际执行操作的函数的指针。 
      如果登记成功,返回设备的主设备号,不成功,返回一个负值。 
    void cleanup_module(void)

    {

    unregister_chrdev(test_major,"test");

      在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test在系统字符设备表中占有的表项。 
      一个极其简单的字符设备可以说写好了,文件名就叫test.c吧。 
      下面编译 :
      $ gcc -O2 -DMODULE -D__KERNEL__ -c test.c

      得到文件test.o就是一个设备驱动程序。 
      如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后 
      ld  -r file1.o  file2.o  -o  modulename。

      驱动程序已经编译好了,现在把它安装到系统中去。 
      $ insmod  –f  test.o

    如果安装成功,在/proc/devices文件中就可以看到设备test,并可以看到它的主设备号。要卸载的话,运行 :
    $ rmmod test

      下一步要创建设备文件。 
      mknod /dev/test c majorminor

      c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。 
      用shell命令 
      $ cat /proc/devices

      就可以获得主设备号,可以把上面的命令行加入你的shell script中去。 
      minor是从设备号,设置成0就可以了。 
      我们现在可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。 
    #include <stdio.h>

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    main()

    {

    inttestdev;

    int i;

    charbuf[10];

    testdev= open("/dev/test",O_RDWR);

    if (testdev == -1 )

    {

    printf("Cann'topen file \n");

    exit(0);

    }

    read(testdev,buf,10);

    for (i= 0; i < 10;i++)

    printf("%d\n",buf[i]);

    close(testdev);

    }


      编译运行,看看是不是打印出全1 ? 
      以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,DMA,I/O port等问题。这些才是真正的难点。请看下节,实际情况的处理。 
    如何编写Linux操作系统下的设备驱动程序

    三、设备驱动程序中的一些具体问题

      1。 I/O Port。 
      和硬件打交道离不开I/O Port,老的ISA设备经常是占用实际的I/O端口,在linux下,操作系统没有对I/O口屏蔽,也就是说,任何驱动程序都可对任意的I/O口操作,这样就很容易引起混乱。每个驱动程序应该自己避免误用端口。 
      有两个重要的kernel函数可以保证驱动程序做到这一点。 
      1)check_region(int io_port, int off_set) 
      这个函数察看系统的I/O表,看是否有别的驱动程序占用某一段I/O口。 
      参数1:io端口的基地址, 
      参数2:io端口占用的范围。 
      返回值:0 没有占用, 非0,已经被占用。 
      2)request_region(int io_port, int off_set,char *devname) 
      如果这段I/O端口没有被占用,在我们的驱动程序中就可以使用它。在使用之前,必须向系统登记,以防止被其他程序占用。登记后,在/proc/ioports文件中可以看到你登记的io口。 
      参数1:io端口的基地址。 
      参数2:io端口占用的范围。 
      参数3:使用这段io地址的设备名。 
      在对I/O口登记后,就可以放心地用inb(), outb()之类的函来访问了。 
    在一些pci设备中,I/O端口被映射到一段内存中去,要访问这些端口就相当于访问一段内存。经常性的,我们要获得一块内存的物理地址。

      2。内存操作 
      在设备驱动程序中动态开辟内存,不是用malloc,而是kmalloc,或者用get_free_pages直接申请页。释放内存用的是kfree,或free_pages。 请注意,kmalloc等函数返回的是物理地址! 
      注意,kmalloc最大只能开辟128k-16,16个字节是被页描述符结构占用了。 
      内存映射的I/O口,寄存器或者是硬件设备的RAM(如显存)一般占用F0000000以上的地址空间。在驱动程序中不能直接访问,要通过kernel函数vremap获得重新映射以后的地址。 
      另外,很多硬件需要一块比较大的连续内存用作DMA传送。这块程序需要一直驻留在内存,不能被交换到文件中去。但是kmalloc最多只能开辟128k的内存。 
      这可以通过牺牲一些系统内存的方法来解决。 
      
      3。中断处理 
      同处理I/O端口一样,要使用一个中断,必须先向系统登记。 
    int request_irq(unsigned int irq ,void(*handle)(int,void *,struct pt_regs *),

    unsignedint long flags,const char *device); 
    复制代码
    irq: 是要申请的中断。 
    handle:中断处理函数指针。 
    flags:SA_INTERRUPT 请求一个快速中断,0 正常中断。 
    device:设备名。

      如果登记成功,返回0,这时在/proc/interrupts文件中可以看你请求的中断。

      4。一些常见的问题。 
      对硬件操作,有时时序很重要。但是如果用C语言写一些低级的硬件操作的话,gcc往往会对你的程序进行优化,这样时序会发生错误。如果用汇编写呢,gcc同样会对汇编代码进行优化,除非用volatile关键字修饰。最保险的办法是禁止优化。这当然只能对一部分你自己编写的代码。如果对所有的代码都不优化,你会发现驱动程序根本无法装载。这是因为在编译驱动程序时要用到gcc的一些扩展特性,而这些扩展特性必须在加了优化选项之后才能体现出来。

    展开全文
  • 如何学习LINUX驱动开发? Post By:2014-4-24 17:15:00  很多朋友认为Linux驱动开发学起来很难,如何学习linux驱动开发?下面笔者就说说我的学习经验吧。 1. 学会写简单的makefile 2. 编一...
    如何学习LINUX驱动开发?  发帖心情 Post
     By:2014-4-24 17:15:00 

    很多朋友认为Linux驱动开发学起来很难,如何学习linux驱动开发?下面笔者就说说我的学习经验吧。

    1. 学会写简单的makefile

    2. 编一应用程序,可以用makefile跑起来

    3. 学会写驱动的makefile

    4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod,rmmod. 在驱动的init函数里打印hello world,insmod后应该能够通过dmesg看到输出。

    5. 写一完整驱动, 加上read, write,ioctl, polling等各种函数的驱动实现。在ioctl里完成从用户空间向内核空间传递结构体的实现。

    6. 写一block驱动, 加上read,write,ioctl,poll等各种函数实现。

    7. 简单学习下内存管理, 这个是最难的,明白各种memory alloc的函数实现细节。这是linux开发的基本功。

    8. 学习锁机制的应用,这个不是最难的但是最容易犯错的,涉及到很多同步和并发的问题。

    9. 看内核中实际应用的驱动代码。你会发现最基本的你已经知道了,大的框架都是一样的,无非是read,write, ioctl等函数的实现,但里面包含了很多很多细小的实现细节是之前不知道的。这时候就要考虑到很多别的问题而不仅仅是基本功能的实现。

    展开全文
  • 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系....我们在学习驱动开发之前,一定要明白一个道理:术业有专攻,不要盲目跟风. [本内容适用环境及工具]  1>
    很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概也就3~4年时间.大多数人都认为会驱动开发的都是牛人,高手之类的.其实高手,牛人不是这样定义的.我们在学习驱动开发之前,一定要明白一个道理:术业有专攻,不要盲目跟风.

    [本内容适用环境及工具] 
    1> Windows系统下
    2> VC6.0以及VS2003版本以上
    3> Windows驱动开发包(DDK(老版本) WDK(新版本))
    4> 有能力着可以安装VMWare

    [本内容适用群体] 
    1> 具有C/C++语言基础的人
    2> 具备高中以上文化水平的逻辑思维

    [具备Windows系统理论书籍] 
    1> Windows核心编程
    2> Win32多线程程序设计
    3> 深入解析Windows操作系统
    4> Windows操作系统原理

    FAQ1:为什么需要[具备Windows系统理论书籍]这4本书? 
    答:驱动是Windows系统的一个重要的组成部分,深入Windows系统核心的一个体系,就因为驱动跟系统内核联系得十分紧密,所以涉及了不少系统的基础理论以及原理.因此在学习驱动开发之前必须先明白Windows系统的基础开发理论,Windows系统的运作原理,Windows系统的架构体系.那么我提供的上面4本书是目前市面上我认为最经典最全面的书籍了.

    [具备Windows驱动开发书籍] 
    1> Windows驱动开发详解
    2> Windows设备驱动程序WDF开发

    FAQ2:为什么需要[具备Windows驱动开发书籍]这2本书? 
    答:假设你对Windows系统的基础理论扎实了,也看完了所说的[Windows系统理论书籍]这4本书,而且你还从事开发过Windows程序或者大程序的经验者.那么你进入Windows驱动开发的时候,需要一本经典的驱动入门开发书籍即可正确入门.现在我提供了[Windows驱动开发书籍]这2本书完完全全针对Windows驱动开发入门而编写的书籍.当然我首要推荐<Windows驱动开发详解>这本书.本书的内容在目前来说,针对驱动开发的讲解时非常到位了.包含了驱动开发理论 配置 驱动体系 等等......是一本不可多得的好书.那么第2本,其实有点滥竽充数,但是他里面有少少涉及到WDF这个最新的驱动开发理论的讲解,大家也就凑合着吧.


    [具备Windows调试基础理论书籍] 
    1> 软件调试
    2> Windows用户态程序高效排错

    FAQ3:为什么需要[具备Windows调试基础理论书籍]这2本书? 
    答:在开发驱动的情况下,你少不了要调试驱动程序.那么如何调试驱动程序呢? Windows已为你考虑到这个问题了并开发了一套强有力的调试工具:Windbg .如何学习这个工具的调试呢?那么现在市面上只有这2本书针对Windbg讲解得还比较到位,至少针对调试命令的使用,已经用中文讲解了,大家可以通过2本书先大概了解Windbg的调试命令,然后再进一步进行GOOGLE搜索并深入学习.

    [驱动开发扩展书籍] 
    1> 寒江独钓-Windows内核安全编程
    2> Windows内核原理与实现
    3> Rootkit Windows内核安全防范

    FAQ4:为什么需要[驱动开发扩展书籍]这2本书? 
    答:熟话说:学无止境,驱动开发领域是一个很庞大的体系,这归根于驱动框架多样化而决定的.驱动包含了:文件驱动,磁盘驱动,显卡驱动,网络驱动,等等不同的种类,每一种类就是一个领域,你决定你的能力需要扩展到多方面,那么你可以考虑先我这里提供的这3本书来学习,通过阅读这3本书,你会发现驱动可以做很多你意想不到的事情.本人从事开发驱动将近4年,也仅仅涉及 文件驱动,磁盘驱动以及一些小型驱动而已.这些的学习我也仅仅是根据需求来进行选择性学习.每个人都有自己的能力极限,大家要量力而行. 
    展开全文
  • 1. 学会写简单的...4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod, rmmod. 在驱动的init函数里打印hello world, insmod后应该能够通过dmesg看到输出。 5. 写一完整驱动, 加上read, write,

    1. 学会写简单的makefile

    2. 编一应用程序,可以用makefile跑起来

    3. 学会写驱动的makefile

    4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod, rmmod. 在驱动的init函数里打印hello world, insmod后应该能够通过dmesg看到输出。

    5. 写一完整驱动, 加上read, write, ioctl, polling等各种函数的驱动实现。 在ioctl里完成从用户空间向内核空间传递结构体的实现。

    6. 写一block驱动, 加上read,write,ioctl,poll等各种函数实现。

    7. 简单学习下内存管理, 这个是最难的,明白各种memory alloc的函数实现细节。这是Linux开发的基本功。

    8. 学习锁机制的应用,这个不是最难的但是最容易犯错的,涉及到很多同步和并发的问题。

     9. 看内核中实际应用的驱动代码。 你会发现最基本的你已经知道了, 大的框架都是一样的, 无非是read, write, ioctl等函数的实现, 但里面包含了很多很多细小的实现细节是之前不知道的。 这时候就要考虑到很多别的问题而不仅仅是基本功能的实现。 推荐您看2.6.20中integrated的一个驱动 kvm, 记得是在driver/lguest下,很好玩的, 就是Linux下的虚拟机驱动, 代码不长,但功能强大。有能力的可以自己写一操作系统按照要求做成磁盘镜像加载到虚拟机中, 然后客户机可以有自己的4G虚拟地址空间。

    10. 看完驱动欢迎您进入Linux kernel学习中来。 最简单的方法,跟着ldd(Linux devive driver)做一遍。

          学习linux驱动开发是一个很漫长的过程,有的人能迎风破浪,有的人却只能知难而退,我也不知道自己是哪一种人,只是知道我现在从事的工作就是linux驱动的工作,而且工作不是很轻松,而且不是向我以前想象的那么简单,而我的理想与目标,可能会向后延期。但是我也很庆幸,因为我还来得及,知道自己以后的路应该怎么走。
    对于我个人能力,自认为还不是一个合格的工程师,就好像现在的人把工程师当作司机一样,满大街的都是工程师,没有几个能够和自己的称呼真正的对称,所以我也明白自己现在在做什么,应该做什么,我是一个一旦确定了目标,就会一直走下去,所以我现在唯一能做的就是努力,努力,再努力。好了,废话也不多说了。为了避免一些刚刚接触的人走弯路,我就把如何才能走入这样行业,而你应该具备什么知识,你应该怎样一步一步的走,等等介绍给大家,

    首先学习linux驱动开发(2.4和2.6),真本身就是一个非常笼统的概念,那好我们应该怎样去学习呢。
    1,首先你应该是一个计算机专业出身的学生,因为在上大学的时候,有好多基础课程(我们所说的垃圾课),都是驱动学习的非常重要的课程,所以我们要把那些基础学好,就是说我们在大学学习的每门课程都是有用的,想成为一个真正的高手,必须具备那些基础知识。比如说:C语言,汇编语言,数据结构,计算机系统结构,操作系统,微机原理,数点,模电,等等,总之要把这些学好,只有这样你才能迈进驱动的大门,而不是只是当一个修修补补的人(这句话只有做过驱动开发的人,能明白我说的意思)如果不是计算机专业的话,那你就慢慢补吧......

    2 接下来,我们应该把C语言学习到精通在精通。那应该怎样才能把C学习到精通在精通呢,好,你只要把这五本书搞懂了,就没有问题了。  
      1 The.C.Programming.Language.2nd.Edition
      2 C语言接口与实现--创建可重用软件的技术
      3 C陷阱与缺陷
      4 C语言参考手册第五版
      5 C专家编程

    3当你具备了以上内容,那你就可以学习linux了。好我也就把怎样去学习linux的过程介绍一下。首先你应该利用一段时间把基础学习一下,包括基本命令,服务的配置,文件系统的介绍。还有就是linux的操作,要达到熟练,简单的说就是把会用linux系统了。当然这只是一个开始,前段的学习不要超过两个月的时间,快的话一个月就够了。好了,重点学习的东西,vi,gcc,gdb,shell,makefile的学习和使用,编译一个简单的C程序。要知道C在不同环境下使用也是不一样的,所以我们不要在windows下练习,要一直在linux去做这些事情。这个学习的过程也得2个月的时间,我们要多学习一下makefile和shell,在这之前的学习要学的慢一点,打基础要牢靠一点。

    4 以上的内容你都掌握了,接下来就是真正的进入应用层的开发了。由于本人是从事网络开发的,所以我也只能给大家介绍一个怎么才能进入网络开发的行列。首先你应该好好的学习一下网络基础的东西,这也是非常重要的哦。包括,计算机网络基础,tcp/ip的学习等等,接下来你应该去买两本书,就是有关linux进程开发的和socket开发的书籍。这些学习的过程就漫长了。至少也得个半年的时间吧。
    好了,由于时间关系,今天先写在这里,下次会把驱动的真正学习介绍一下。不用急哦,因为这些也够你学一段时间咯。

    展开全文
  • 搞Windows驱动开发是一件痛苦的事情,特别是初学Windows驱动开发。有的人觉得Windows驱动开发就是把开发包WDK下载下来,然后只要掌握了C/C++语言,接下来无非就是类库调来调去,像调用MFC、QT之类的库那样,看着书和...
    搞Windows驱动开发是一件痛苦的事情,特别是初学Windows驱动开发。有的人觉得Windows驱动开发就是把开发包WDK下载下来,然后只要掌握了C/C++语言,接下来无非就是类库调来调去,像调用MFC、QT之类的库那样,看着书和MSDN上的文档来就行了。等真正接触以后才发现根本不是那么一回事,痛苦源于以下几点:
    

    痛苦一:中文资料太少
    讲Windows驱动开发的,无论是中文书籍还是网上的中文资料,都很少,手把手从零到精通的更是不用说了。仅有的少量中文资料,有的还比较旧,讲的是DDK、NT式驱动,新手拿着WDK8.1、WDK10面对Win8、Win10系统很难跟着学习,而且现在的WDK,在WDM上又出现了了WDF,而WDF又分KMDF(内核模式驱动)和UMDF(用户模式驱动),对于UMDF(用户模式驱动)中文资料就更少了。而且驱动开发不像应用开发,需要先对操作系统原理有一定了解,不然遇到“I/O管理器”、“输入输出请求包”、“软件中断”、“符号链接”、”派遣函数“等名词和概念都不知所云,是寸步难行的。

    解决方法:
    ①其实MSDN上已经提供了大量的文档和示例程序,对KMDF、UMDF等进行了详细的讲解,甚至还提供了手把手教你来的视频教程,可惜它们都是英文的,对于我等英语不好的程序员来说真是坐车不买票——白搭。最近越来越觉得英语不好是阻碍一个程序员进步最大的绊脚石,我们不谈什么算法,不谈什么数学功底了,首先要成为一个合格的码农,需要熟练使用各种编程语言和对应的各种工具库,而大部分的库都只有英文文档,不能流畅阅读这些文档的话,寸步难行。在成为了合格的码农,能熟练使用各种现成的工具库搭积木般的开发出应用程序后,才能去谈各种算法,各种数学知识的代入,才能去谈如何从一个码农升级为软件工程师。显然,当前摆在我面前最迫切的问题是如何成为一个合格的码农,先养活自己,再去考虑如何为社会主义做贡献,如何推动人类科技进步。学习英语确实应该赶快提上日程并立即执行、坚持执行了。英语好的人真的是把WDK拿来就像用MFC那样轻松,看着文档和示例程序,那些个API调来调去,一个完整的驱动程序就出来了。这不是吹牛,我之前在一家公司工作的时候,公司有个项目的一个模块需要在Ring0上实现,需要编写Windows内核驱动,然而公司里没有一个人会,于是老大将这个模块交给了他的一个朋友去做。他的这个朋友是中国人,在美国微软总部工作,英语水平怎么样就不用说了,总之人家以前从来没搞过驱动开发,看了文档和示例代码后,利用3天的业余时间就完成了这个模块,拿到了15K RMB的报酬,着实让人佩服,让人羡慕。真的,学好英语,不说“听说写”,只要能流畅阅读各种英文技术资料,完全是另一个世界,学什么、做什么都得心应手。
    MSDN上的驱动开发资料入口:https://msdn.microsoft.com/zh-cn/windows/hardware
    MSDN上手把手教你来的视频教程:https://msdn.microsoft.com/zh-cn/windows/hardware/gg454522

    ②抓住仅有的几本中文书籍,细细研读。关于Windows驱动开发的中文书籍大概有那么几本:
    Windows驱动开发技术详解》(强烈推荐先看这本)
    WindowsWDM设备驱动程序开发指南》(比较老了,2000年出版的,以win98、win2000为目标系统)
    Windows设备驱动程序WDF开发》(为数不多讲WDF的)
    《Windows 7设备驱动程序开发》(为数不多讲WDF的,且比较新,这本书的英文版是2010年出版的,中文译版是2012年出版的)
    《竹林蹊径:深入浅出windows驱动开发》
    《寒江独钓:Windows内核安全编程》
    《天书夜读:从汇编语言到Windows内核编程》
    《Windows内核安全与驱动开发》(是《天书夜读》和《寒江独钓》的合订本以及升级版)
    后面的这四本其实不太适合作为入门书籍,而适合作为进阶书籍,对一些基础的概念和原理的讲解没有《Windows驱动开发技术详解》那么多

    痛苦二:开发工具链不好用
    对于我等刚学编程时用的就是VisualStudio以及各种智能提示智能感知的插件,甚至还有代码生成器的辅助的程序员来说,习惯了VisualStudio傻瓜化的一切,代码可以自动生成,窗体应用程序可以拖控件,甚至连网页都能拖控件。很难接受只有文本编辑器和命令行工具的开发环境,很多时候连代码编辑器不能智能提示都无法忍受,更不说手动调用cl.exe link.exe,写起代码来就像有一万只蚂蚁在身上爬。
    在之前很长的一段时间里,VC6.0和VisualStudio里是没有创建驱动项目的选项的,更没有直接由IDE生成的HelloWorld,如果不想手动cl.exe link.exe,如果想在IDE中写代码,需要自己建一个空项目,然后手动配置编译器指令、链接器指令、包含目录、库目录等等,然后把书上的HelloWorld复制过来,然后可能还会遇到各种问题。生成好驱动程序文件后,还要手动拷贝到虚拟机中,借助工具或inf文件手动安装,然后要改系统配置,进入内核调试模式,然后要设置调试接口,比如使用COM串口调试的话要在虚拟机上设置,把COM串口映射到主机的命名管道,然后还不能在VC中调试,只能用Windbg来调试。总之每修改一下代码,需要手工进行很多步骤才能开始调试,非常麻烦。而且即便照着网上或书上的步骤来配置,在不同的环境下也会遇到各种奇怪的问题,搞起来颇为头疼。

    解决方法:
    ①有个名为VisualDDK的第三方软件,使得这个事情方便了很多。VisualDDK装好后会给VisualStudio安装一个插件,使得在VisualStudio中可以通过这个插件新建驱动项目,并且自带HelloWorld,然后把VisualDDK Monitor装到虚拟机中,两边配置一下,接下来只要在VisualStudio这边生成驱动文件,VisualDDK会自动传给虚拟机中的系统进行安装,并且可以直接在VisualStudio中下断点调试了。不过这个软件在安装和配置过程中,也需要不少步骤,有时候也会出现一些配置不对的问题,偶尔也略感头疼,且稳定性和兼容性不是非常好。此方式适用于VisualStudio2010及以下版本,WDK7.1及以下版本。对于更高的版本,不建议用VisualDDK,因为可以继续往下看,下面有更激动人心的办法。
    VS2010+VMWare8+VisualDDK1.5.6配置教程:http://techird.blog.163.com/blog/static/1215640362011112385241568/

    ②激动人心的就是,从VisualStudio2012开始,从WDK8.0开始,微软在里面整合了一套类似VisualDDK但比VisualDDK好用很多的工具。从那以后,开发Windows驱动程序就和开发Windows应用程序一样方便了,只需在虚拟机中安装一个EXE,然后在VisualStudio中输入它的IP、用户名、密码就OK了,接下来你只需新建一个WDK项目,点生成,VisualStudio会自动把驱动文件传给虚拟机中的系统并自动安装,然后点调试,就能在VisualStudio中单步调试了。是不是爽爆了,而且配置和设置都不复杂,MSDN上还有手把手教你配置的高清视频教程!
    具体可以看我写的另一篇文章:
    Win8.1+VS2013+WDK8.1+VirtualBox or VMware驱动开发环境配置》:http://blog.csdn.net/charlessimonyi/article/details/50904956

    痛苦三:没有库可用
    假如有一天老板叫你开发一个软件,允许你使用你擅长的任意一门语言,C/C++/C#/JAVA/Python等。但是附加了一个条件:不能使用任何第三方库,不能使用标准库!你有什么感想。What!标准库都不能用?那还写个毛。是的,没错,开发Windows驱动程序,几乎什么库都用不了,包括标准库。因为我们平时常用的第三方库或标准库,它的实现其实都是调用系统API,在Windows上调用的是Window API,即uer32.dll、kernel32.dll、gdi32.dll等等提供的API函数。但是这些API函数属于应用层API,无法在驱动程序中使用,因为驱动程序跑在内核层。所以只要一个库的实现上调用了系统API,就无法在驱动程序中使用。少数库还是可以使用的,比如math.h中的各种数值计算函数。不过仅剩的可用的库太少了,很多时候你都需要从新发明轮子。甚至连C语言中的malloc、free,C++中的new、delete,你都需要自己去实现。

    解决方法:
    ①自己发明轮子就自己发明轮子,虽然没有现成库可用,但有内核层下的系统API可用,很多和应用层的API很相似,你想要的功能基本都可以通过这些API实现。

    ②咬咬牙,把苦水往肚子里咽。搞驱动开发的人很少,苦尽甘(qian)来


    本文由CharlesSimonyi发表于CSDN博客:http://blog.csdn.net/charlessimonyi/article/details/50904854转载请注明出处

    展开全文
  • 学习驱动开发的步骤

    2014-05-15 15:13:02
    2.了解Linux内核的目录结构,尤其要熟悉kernel目录下的driver目录组织结构,这里一般存放内核中的驱动程序。 3.学会配置、编译Linux内核。 4.写一简单char驱动,Makefile编译通过,可以insmod,
  • 1. 分享Linux内核学习驱动开发的经验。 内核学习 Linux 内核功能越来越完善,如果没有充裕的时间,深入内核并不是很现实。所以建议先读一本内核的书, 第一遍是读,会读的很迷糊;之后反省一下,然后再浏览...
  • 对于从事Windows驱动开发的朋友,或者是对Windows内核感兴趣的朋友,以下几个BLOG值得经常看看!1,Kernel Mustard by Steve Dispensa link: http://kernelmustard.com/category/ddk/他以前的BLOG地址为:...
  • linux设备驱动开发,看起来是一份很高大上的职业,毕竟从事上层应用开发人员太多,而且门槛又不是特别高,而内核级开发从业人员要少得多,而且资料又较少。有许多刚刚接触到linux设备驱动开发的同仁会感觉非常困惑,...
  • 驱动技术引无数英雄竟折腰!
  • 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资 料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从 事驱动开发时间不长也不短,大概也就3~4年时间....
  • 前面我们学习I2C、USB、SD驱动时,有没有发现一个共性,就是在驱动开发时,每个驱动都分层三部分,由上到下分别是: 1、XXX 设备驱动 2、XXX 核心层 3、XXX 主机控制器驱动  而需要我们编写的主要是设备驱动...
  • [序言]  很多人都对驱动开发有兴趣,但往往找不到正确的学习方式....料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼....我们在学习驱动开发之前,一定要明白一个道 理:术
  • 本课程讲解Linux驱动程序开发基本知识,程序架构,字符设备编程,杂项设备编程,具体硬件模块驱动开发
  • 如何成为一名优秀的Android驱动程序员?参数如下要求: 一、Android驱动的基础知识 1.Android驱动是基于Linux驱动,强烈推荐阅读Linux Device Driver 3rd版,这本书讲了Linux下设备驱动的基础知识,要求反复细读。 2...
  • 希望能帮助进入学习驱动开发的同仁O(∩_∩)O~
  • 最近想了解一下驱动编程,首先要配置环境,按照, 我下载了 WDK(GRMWDK_EN_7600.ISO 和《windows驱动开发技术详解》书中的不同),我想都是向后兼容的,就配置完了 VC6 的环境,但是运行《windows驱动开发技术详解...
  • 本博实时更新《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)的最新进展。 目前已经完成稿件。 2015年8月9日,china-pub开始上线预售: ... 2015年8月20日,各路朋友报喜...
  • 本文主要介绍“如何入门Windows驱动开发”和“新手需要掌握哪些知识和动手技能”,大部分是本人探索Windows驱动开发近一月时间的经验之谈。大致包括如下几个方面: 1,开发工具、调试工具和调试手段; 2,Windows...
  • ARM+LINUX路线,主攻嵌入式Linux操作系统及其上应用软件开发目标: (1)掌握主流嵌入式微处理器的结构与原理(初步定为arm9) (2)必须掌握一个嵌入式操作系统 (初步定为uclinux或linux,版本待定) (3)必须...
1 2 3 4 5 ... 20
收藏数 232,436
精华内容 92,974