XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
阅读:2622回复:6

Windows驱动编程基础教程(连载4)

楼主#
更多 发布于:2008-05-23 13:11
本文作者为楚狂人。有问题请联系QQ1619135,msn walled_river@hotmail.com

Windows驱动编程基础教程(2.3-2.4)

2.3 使用长长整型数据
    这里解释前面碰到的LARGE_INTEGER结构。与可能的误解不同,64位数据并非要在64位操作系统下才能使用。在VC中,64位数据的类型为__int64。定义写法如下:

    __int64 file_offset;

    上面之所以定义的变量名为file_offset,是因为文件中的偏移量是一种常见的要使用64位数据的情况。同时,文件的大小也是如此(回忆上一小节中定义的文件大小)。32位数据无符号整型只能表示到4GB。而众所周知,现在超过4GB的文件绝对不罕见了。但是实际上__int64这个类型在驱动开发中很少被使用。基本上被使用到的是一个共用体:LARGE_INTEGER。这个共用体定义如下:

    typedef __int64 LONGLONG;    
    typedef union _LARGE_INTEGER {
        struct {
            ULONG LowPart;
            LONG HighPart;
        };
        struct {
            ULONG LowPart;
            LONG HighPart;
        } u;
        LONGLONG QuadPart;
    } LARGE_INTEGER;

    这个共用体的方便之处在于,既可以很方便的得到高32位,低32位,也可以方便的得到整个64位。进行运算和比较的时候,使用QuadPart即可。

    LARGE_INTEGER a,b;
    a.QuadPart = 100;
    a.QuadPart *= 100;
    b.QuadPart = a.QuadPart;
    if(b.QuadPart > 1000)
    {
        KdPrint(“b.QuadPart < 1000, LowPart = %x HighPart = %x”, b.LowPart,b.HighPart);
    }
    
    上面这段代码演示了这种结构的一般用法。在实际编程中,会碰到大量的参数是LARGE_INTEGER类型的。

2.4使用自旋锁

    链表之类的结构总是涉及到恼人的多线程同步问题,这时候就必须使用锁。这里只介绍最简单的自选锁。
    有些读者可能疑惑锁存在的意义。这和多线程操作有关。在驱动开发的代码中,大多是存在于多线程执行环境的。就是说可能有几个线程在同时调用当前函数。
    这样一来,前文1.2.2中提及的追加链表节点函数就根本无法使用了。因为MyFileInforAppendNode这个函数只是简单的操作链表。如果两个线程同时调用这个函数来操作链表的话:注意这个函数操作的是一个全局变量链表。换句话说,无论有多少个线程同时执行,他们操作的都是同一个链表。这就可能发生,一个线程插入一个节点的同时,另一个线程也同时插入。他们都插入同一个链表节点的后边。这时链表就会发生问题。到底最后插入的是哪一个呢?要么一个丢失了。要么链表被损坏了。
    如下的代码初始化获取一个自选锁:

    KSPIN_LOCK my_spin_lock;
    KeInitializeSpinLock(&my_spin_lock);

    KeInitializeSpinLock这个函数没有返回值。下面的代码展示了如何使用这个SpinLock。在KeAcquireSpinLock和KeReleaseSpinLock之间的代码是只有单线程执行的。其他的线程会停留在KeAcquireSpinLock等候。直到KeReleaseSpinLock被调用。KIRQL是一个中断级。KeAcquireSpinLock会提高当前的中断级。但是目前忽略这个问题。中断级在后面讲述。
    
    KIRQL irql;
    KeAcquireSpinLock(&my_spin_lock,&irql);
    // To do something …
    KeReleaseSpinLock(&my_spin_lock,irql);
    
    初学者要注意的是,像下面写的这样的“加锁”代码是没有意义的,等于没加锁:
    
    void MySafeFunction()
    {
        KSPIN_LOCK my_spin_lock;
        KIRQL irql;
        KeInitializeSpinLock(&my_spin_lock);
        KeAcquireSpinLock(&my_spin_lock,&irql);
        // To do something …
        KeReleaseSpinLock(&my_spin_lock,irql);
    }

    原因是my_spin_lock在堆栈中。每个线程来执行的时候都会重新初始化一个锁。只有所有的线程共用一个锁,锁才有意义。所以,锁一般不会定义成局部变量。可以使用静态变量、全局变量,或者分配在堆中(见前面的1.2.1内存的分配与释放一节)。请读者自己写出正确的方法。
    LIST_ENTRY有一系列的操作。这些操作并不需要使用者自己调用获取与释放锁。只需要为每个链表定义并初始化一个锁即可:

    
    LIST_ENTRY        my_list_head;        // 链表头
    KSPIN_LOCK    my_list_lock;        // 链表的锁
    
    // 链表初始化函数
    void MyFileInforInilt()
    {
        InitializeListHead(&my_list_head);
        KeInitializeSpinLock(&my_list_lock);
    }

    链表一旦完成了初始化,之后的可以采用一系列加锁的操作来代替普通的操作。比如插入一个节点,普通的操作代码如下:

    InsertHeadList(&my_list_head, (PLIST_ENTRY)& my_file_infor);

    换成加锁的操作方式如下:

    ExInterlockedInsertHeadList(
        &my_list_head,
        (PLIST_ENTRY)& my_file_infor,
        &my_list_lock);

    注意不同之处在于,增加了一个KSPIN_LOCK的指针作为参数。在ExInterlockedInsertHeadList中,会自动的使用这个KSPIN_LOCK进行加锁。类似的还有一个加锁的Remove函数,用来移除一个节点,调用如下:

    my_file_infor = ExInterlockedRemoveHeadList (
        &my_list_head,
        &my_list_lock);

    这个函数从链表中移除第一个节点。并返回到my_file_infor中。

最新喜欢:

greenpeacegreenp...
cm007
驱动牛犊
驱动牛犊
  • 注册日期2007-10-31
  • 最后登录2009-11-04
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望38点
  • 贡献值0点
  • 好评度21点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-05-23 14:34
强烈支持!!!
microbe
驱动小牛
驱动小牛
  • 注册日期2007-12-10
  • 最后登录2011-01-17
  • 粉丝1
  • 关注0
  • 积分914分
  • 威望420点
  • 贡献值1点
  • 好评度88点
  • 原创分0分
  • 专家分1分
板凳#
发布于:2008-05-23 14:41
必顶!!
ptf_phoenix
驱动牛犊
驱动牛犊
  • 注册日期2008-03-03
  • 最后登录2008-06-19
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-05-23 22:00
强烈支持
mykgd
驱动牛犊
驱动牛犊
  • 注册日期2008-02-14
  • 最后登录2008-05-24
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-05-23 22:32
太高深了!!!! 顶!!!
bbb
hhyDriver
驱动小牛
驱动小牛
  • 注册日期2007-06-06
  • 最后登录2009-01-19
  • 粉丝0
  • 关注0
  • 积分154分
  • 威望150点
  • 贡献值0点
  • 好评度146点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-05-26 11:17
强烈建议出一本书
dt1985324
驱动牛犊
驱动牛犊
  • 注册日期2008-05-06
  • 最后登录2009-02-10
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望106点
  • 贡献值1点
  • 好评度20点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-05-30 16:10
找到了           顶起来   全力支持楚大大
游客

返回顶部