驱动程序中数据竞争检测方法及装置与流程

文档序号:17925636发布日期:2019-06-15 00:23阅读:279来源:国知局
驱动程序中数据竞争检测方法及装置与流程

本发明实施例属于计算机操作装置与程序分析技术领域,更具体地,涉及一种驱动程序中数据竞争检测方法及装置。



背景技术:

现代操作装置普遍采用并发编程来最大化多核机器的利用率,提高装置程序的性能。驱动程序也大量使用这种并发性来高效地进行计算机装置内核和硬件的通信。

但是,程序的并发执行会带来大量的不确定性,因此驱动程序中也存在一些难以发现的调试和修复的并发问题,如数据竞争。数据竞争发生在多个线程没有采用同步操作的条件下,同时访问同一个内存地址,并且其中至少有一个线程是执行写操作时。数据竞争会导致程序的数据和执行顺序变得不确定,进而导致严重的问题,如空指针解引用、释放后重用等。

现有的一些用于检测内核态驱动程序中数据竞争的方法主要分为两类,即一类是静态检测方法,另一类是动态检测方法。其中,静态检测方法由于缺少驱动真实的运行信息通常具有较高的误报率。动态检测方法主要基于采样或锁集合来实现的。基于采样方法的效果严重依赖于采样的频率,如果采样频率过高,则性能开销大;如果采样频率过低,则容易漏掉许多真实的数据竞争。传统的基于锁集合的方法假设所有的共享变量的访问都可能被并发执行,因此需要加锁进行访问。如果对共享变量的访问未加锁,则报告一个数据竞争。但是,实际上并不是所有对共享变量的访问都会并发,如初始化操作不会和之后的访问并发。因此,传统的基于锁集合方法的准确性也比较低。同时,传统的动态方法通常需要在运行时记录细粒度的信息并进行一些推理,带来了较大的运行时开销,这对于硬件设备的正常运行造成了一定的影响。



技术实现要素:

为克服上述现有的驱动程序中数据竞争的检测方法性能开销大且检测不准确的问题或者至少部分地解决上述问题,本发明实施例提供一种驱动程序中数据竞争检测方法及装置。

根据本发明实施例的第一方面,提供一种驱动程序中数据竞争检测方法,包括:

当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;

从所述共享变量访问中获取至少含有一个锁的共享变量访问,将至少含有一个锁的所述共享变量访问作为潜在竞争访问;

将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

根据本发明实施例第二方面提供一种驱动程序中数据竞争检测装置,包括:

获取模块,用于当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;

选择模块,用于从所述共享变量访问中获取至少含有一个锁的共享变量访问,将至少含有一个锁的所述共享变量访问作为潜在竞争访问;

检测模块,用于将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

根据本发明实施例的第三个方面,还提供一种电子设备,包括:

至少一个处理器;以及

与所述处理器通信连接的至少一个存储器,其中:

所述存储器存储有可被所述处理器执行的程序指令,所述处理器调用所述程序指令能够执行第一方面的各种可能的实现方式中任一种可能的实现方式所提供的驱动程序中数据竞争检测方法。

根据本发明实施例的第四个方面,还提供一种非暂态计算机可读存储介质,所述非暂态计算机可读存储介质存储计算机指令,所述计算机指令使所述计算机执行第一方面的各种可能的实现方式中任一种可能的实现方式所提供的驱动程序中数据竞争检测方法。

本发明实施例提供一种驱动程序中数据竞争检测方法及装置,该方法通过在待检测驱动程序运行时记录函数级并发信息和共享变量访问,利用至少被一个锁保护的条件,推测和过滤出可能发生数据竞争的潜在竞争访问,根据任一潜在竞争访问与任一共享变量访问的调用栈组合,通过判断调用栈组合在函数调用路径组合中是否存在,从而确定两个访问是否会并发,从而自动检测驱动程序中的数据竞争,并且实现了较高的准确度和较低的性能开销。

附图说明

为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作一简单地介绍,显而易见地,下面描述中的附图是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。

图1为本发明实施例提供的驱动程序中数据竞争检测方法整体流程示意图;

图2为本发明实施例提供的驱动程序中数据竞争检测装置整体结构示意图;

图3为本发明实施例提供的电子设备整体结构示意图。

具体实施方式

为使本发明实施例的目的、技术方案和优点更加清楚,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。

在本发明的一个实施例中提供一种驱动程序中数据竞争检测方法,图1为本发明实施例提供的驱动程序中数据竞争检测方法整体流程示意图,该方法包括:s101,当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;

其中,待检测驱动程序为需要进行数据竞争检测的驱动程序。共享变量是指可以被多个进程访问的变量。共享变量访问是指共享变量的访问。并发执行是指待检测驱动程序中的多个程序段在执行的过程中,时间互相重叠,一个程序段执行没有结束,另一个程序段的执行已经开始。将并发执行的程序段中各自的函数调用路径进行组合,生成函数调用路径组合。例如,并发执行的两个程序段m和n,程序段m的函数调用路径为a-b-c,表示在函数a中调用函数b,在函数b中调用函数c;程序段n的函数调用路径为d-e-f,表示在函数d中调用函数e,在函数e中调用函数f。将这两个函数调用路径进行组合,即组合结果为(a-b-c,d-e-f)。所有函数调用路径组合的集合为path_set。

s102,从所述共享变量访问中获取至少含有一个锁的共享变量访问,将至少含有一个锁的所述共享变量访问作为潜在竞争访问;

在进行多线程编程时,多个线程若同时访问某个变量,可能会对变量数据造成破坏。因此在编程时使用锁对象,当一个线程取得锁时,获得共享变量的访问权,此时,进入阻塞状态,若其他线程申请访问这个变量,需等到这个线程释放这个锁。驱动程序中一般采用锁机制进行多线程间的同步控制。获取所有共享变量访问的上下文信息,所有共享变量访问的上下文信息的集合为ctx_set。根据所有共享变量访问的上下文信息,判断各共享变量访问中是否存在锁。当各共享变量访问中至少存在一个锁时,该共享变量访问的线程与其他线程之间很可能存在竞争,将该共享变量访问作为潜在竞争访问。所有潜在竞争访问的集合为pos_ctx_set。

s103,将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

从pos_ctx_set中选择任一潜在竞争访问,从ctx_set中选择任一共享变量访问。调用栈为访问共享变量时调用函数的顺序。例如潜在竞争访问为共享变量x访问,访问x时,x访问的调用栈为a-b-c,x位于函数c中。该共享变量访问为y访问,y访问的调用栈为d-e-f。调用栈组合为(a-b-c,d-e-f)。将该调用栈组合与函数调用路径进行比较,即判断该调用栈组合在函数调用路径中是否存在。根据判断结果确定待检测驱动程序是否存在数据竞争。如果存在,则若满足预先设定的条件,则确定待检测驱动程序存在数据竞争缺陷,生成数据竞争缺陷的报告。本实施例对预先设定的条件不进行限定。

本实施例通过在待检测驱动程序运行时记录函数级并发信息和共享变量访问,利用至少被一个锁保护的条件,推测和过滤出可能发生数据竞争的潜在竞争访问,根据任一潜在竞争访问与任一共享变量访问的调用栈组合,通过判断调用栈组合在函数调用路径组合中是否存在,从而确定两个访问是否会并发,从而自动检测驱动程序中的数据竞争,并且实现了较高的准确度和较低的性能开销。

在上述实施例的基础上,本实施例中当待检测驱动程序运行时,获取所述待检测驱动程序中共享变量访问和并发执行的函数调用路径组合的步骤之前还包括:使用clang编译器对所述待检测驱动程序的源代码进行编译,获取所述待检测驱动程序的中间字节码文件;使用llvm工具链在所述中间字节码文件中插入外部函数调用;使用所述clang编译器将插入外部函数调用后的所述中间字节码文件编译为汇编文件;使用gcc编译器将所述汇编文件和所述外部函数调用的定义文件进行编译,获取所述待检测驱动程序的可执行文件;相应地,当待检测驱动程序运行时,获取所述待检测驱动程序中共享变量访问的上下文信息和并发执行的函数调用路径组合的步骤具体包括:加载并运行所述可执行文件,并运行所述待检测驱动程序的工作负载;在所述可执行文件和所述工作负载运行的过程中,通过所述外部函数调用,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合。

具体地,一般情况下,对待检测驱动程序进行编译时直接将其编译为可执行文件,为了对待检测驱动程序进行插桩,对修改待检测驱动程序的编译脚本,以将待检测驱动程序先编译为中间字节码文件。由于待检测驱动程序通常是以模块化的形式加载到内核中,因此可以使用llvm(lowlevelvirutalmachine,低级虚拟机)工具链对其进行单独编译和插桩,再加载到内核中运行。首先,使用llvm工具链将待检测驱动的源代码编译为中间字节码文件。然后,使用clang编译器将中间字节码文件编译为汇编文件,并对中间代码文件进行插桩,主要是在加锁函数、解锁函数、共享变量读写,以及函数的入口和出口等位置插入外部函数调用,从而使驱动在运行时调用相应的处理函数。最后使用gcc(gnucompilercollection,gnu编译器套件)编译器将汇编文件及外部函数调用的定位文件分别编译为可执行文件。其中gnu是一种由自由软件构成的类unix操作装置,该装置基于linux内核,目标在于建立一个完全相容于unix的自由软件环境。加载并运行待检测驱动程序的可执行文件,并运行与待检测驱动程序相关的工作负载,工作负载中包括功能性的指令。在可执行文件运行过程中,通过外部函数调用,记录共享变量访问、内存读写、并发执行的函数调用路径组合、锁集合和中断等信息,写入日志文件中。在运行结束后,根据数据竞争的特征对日志文件进行分析和过滤,检测出待检测驱动程序中的数据竞争,并生成报告。

在上述实施例的基础上,本实施例中获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合的步骤还包括:使用独立的线程记录所述共享变量访问和并发执行的函数调用路径组合;使用写文件缓存机制将所述共享变量访问和并发执行的函数调用路径组合写入日志文件中;使用哈希表对所述日志文件中共享变量访问和并发执行的函数调用路径组合进行去重。

具体地,为减少运行时的性能开销,本实施例使用独立线程记录信息,使用写文件缓存机制将运行时的信息写入日志文件,使用哈希表进行信息去重和过滤,从而提高了数据竞争检测的效率。

在上述各实施例的基础上,本实施例中获取所述待检测驱动程序中共享变量访问的步骤具体包括:将所述待检测驱动程序的各函数中所有指针类型的参数作为潜在共享变量;若所述待检测驱动程序中各函数体内指令的操作数为全局变量或指针类型的参数,则将所述指令的返回值作为所述潜在共享变量;将所述潜在共享变量的访问作为共享变量访问。

具体地,首先,通过插入的外部调用函数获得读写变量的信息,如变量的地址和长度、所在的函数、是读操作或写操作、读写内容、涉及的进程、访问变量时函数的调用顺序等,并将共享变量集合shared_set初始化为空。待检测驱动程序的各函数中指针类型的参数很可能为共享变量,将其作为潜在共享变量加入到共享变量集合shared_set中。接着对函数体内的每一个指令,循环判断其操作数是否为全局变量或指针类型的参数。如果是,则说明该指令的返回值很可能为共享变量,将其作为潜在共享变量加入到共享集合中。如果操作数在共享变量集合shared_set中且操作数所属的指令为读写内存操作,则记录下该指令的内存读写信息。

在上述各实施例的基础上,本实施例中获取所述待检测驱动程序中的并发执行的函数调用路径组合的步骤具体包括:若所述待检测驱动程序在并发执行的过程中出现中断,则从各函数调用路径中将中断期间的调用函数路径从各所述函数调用路径中删除,并将所述中断期间的调用函数路径记录为独立的调用栈;将与删除后的函数调用路径并发执行的函数调用路径进行组合,将与所述中断期间的调用函数路径并发执行的调用函数路径进行组合,将各所述组合结果作为所述并发执行的函数调用路径组合。

具体地,为了获取更准确的函数调用路径,本实施例中在并发执行的过程中出现中断时,将从并发执行的各函数调用路径中将中断期间调用的函数从各所述函数调用路径中删除。例如函数调用路径为a-b-p-q-c,其中在调用函数b后出现中断,中断期间调用函数路径为p-q,恢复正常后继续调用函数c,则将p-q从函数调用路径中删除,,得到正常情况下的函数调用路径a-b-c,并将函数路径p-q记录为独立的调用栈。将与a-b-c并发执行的函数路径进行组合,将与p-q并发执行的函数调用路径进行组合,将这两个组合结果分别作为并发执行的函数调用路径组合。即将当前线程和当前处于运行态线程的调用栈进行组合,获取并发执行的函数调用路径组合。

在上述各实施例的基础上,本实施例中根据判断结果确定所述待检测驱动程序是否存在数据竞争的步骤具体包括:若各所述调用栈组合在所述函数调用路径组合中存在,且所述任一潜在竞争访问和所述任一共享变量访问同时满足三个预设条件,则获知所述待检测驱动程序存在数据竞争;其中,第一个所述预设条件为是否访问同一内存地址;第二个所述预设条件为两个访问的锁集合交集为空;第三个所述预设条件为两个访问中至少一个访问为写操作。

具体地,将任一潜在竞争访问的调用栈和所有共享变量访问中任一共享变量访问的调用栈进行组合,若该调用栈组合在函数调用路径组合中存在,且满足预先设定的三个条件,则获知待检测驱动程序存在数据竞争。

在本发明的另一个实施例中提供一种驱动程序中数据竞争检测装置,该装置用于实现前述各实施例中的方法。因此,在前述驱动程序中数据竞争检测方法的各实施例中的描述和定义,可以用于本发明实施例中各个执行模块的理解。图2为本发明实施例提供的驱动程序中数据竞争检测装置整体结构示意图,该装置包括获取模块201、选择模块202和检测模块203;其中:

获取模块201用于当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;

其中,待检测驱动程序为需要进行数据竞争检测的驱动程序。共享变量是指可以被多个进程访问的变量。共享变量访问是指共享变量的访问。并发执行是指待检测驱动程序中的多个程序段在执行的过程中,时间互相重叠,一个程序段执行没有结束,另一个程序段的执行已经开始。获取模块201将并发执行的程序段中各自的函数调用路径进行组合,生成函数调用路径组合。所有函数调用路径组合的集合为path_set。

选择模块202用于从所述共享变量访问中获取至少含有一个锁的共享变量访问,将至少含有一个锁的所述共享变量访问作为潜在竞争访问;

在进行多线程编程时,多个线程若同时访问某个变量,可能会对变量数据造成破坏。因此在编程时使用锁对象,当一个线程取得锁时,获得共享变量的访问权,此时,进入阻塞状态,若其他线程申请访问这个变量,需等到这个线程释放这个锁。驱动程序中一般采用锁机制进行多线程间的同步控制。获取所有共享变量访问的上下文信息,共享变量访问的上下文信息为共享变量访问的环境信息,所有共享变量访问的上下文信息的集合为ctx_set。选择模块202根据各共享变量访问的上下文信息,判断各共享变量访问中是否存在锁。当各共享变量访问中至少存在一个锁时,该共享变量访问的线程与其他线程之间很可能存在竞争,将该共享变量访问作为潜在竞争访问。所有潜在竞争访问的集合为pos_ctx_set。

检测模块203用于将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

从pos_ctx_set中选择任一潜在竞争访问,从ctx_set中选择任一共享变量访问。调用栈为访问共享变量时调用函数的顺序。检测模块203将该调用栈组合与函数调用路径进行比较,即判断该调用栈组合在函数调用路径中是否存在。根据判断结果确定待检测驱动程序是否存在数据竞争。如果存在,则若满足预先设定的条件,则确定待检测驱动程序存在数据竞争缺陷,生成数据竞争缺陷的报告。本实施例对预先设定的条件不进行限定。

本实施例通过在待检测驱动程序运行时记录函数级并发信息和共享变量访问,利用至少被一个锁保护的条件,推测和过滤出可能发生数据竞争的潜在竞争访问,根据任一潜在竞争访问与任一共享变量访问的调用栈组合,通过判断调用栈组合在函数调用路径组合中是否存在,从而确定两个访问是否会并发,从而自动检测驱动程序中的数据竞争,并且实现了较高的准确度和较低的性能开销。

在上述实施例的基础上,本实施例中还包括编译模块,用于使用clang编译器对所述待检测驱动程序的源代码进行编译,获取所述待检测驱动程序的中间字节码文件;使用llvm工具链在所述中间字节码文件中插入外部函数调用;使用所述clang编译器将插入外部函数调用后的所述中间字节码文件编译为汇编文件;使用gcc编译器将所述汇编文件和所述外部函数的定义文件进行编译,获取所述待检测驱动程序的可执行文件;相应地,获取模块具体用于加载并运行所述可执行文件,并运行所述待检测驱动程序的工作负载;

在所述可执行文件和所述工作负载运行的过程中,通过所述外部函数调用,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合。

在上述实施例的基础上,本实施例中编译模块进一步用于:在所述中间字节码文件中的加锁函数、解锁函数、共享变量读写、函数入口和函数出口位置插入外部函数调用。

在上述实施例的基础上,本实施例中获取模块还用于:使用独立的线程记录所述共享变量访问和并发执行的函数调用路径组合;使用写文件缓存机制将所述共享变量访问和并发执行的函数调用路径组合写入日志文件中;使用哈希表对所述日志文件中共享变量访问和并发执行的函数调用路径组合进行去重。

在上述各实施例的基础上,本实施例中获取模块具体用于:将所述待检测驱动程序的各函数中所有指针类型的参数作为潜在共享变量;若所述待检测驱动程序中各函数体内指令的操作数为全局变量或或指针类型的参数,则将所述指令的返回值作为所述潜在共享变量;将所述潜在共享变量的访问作为共享变量访问。

在上述各实施例的基础上,本实施例中获取模块具体用于:若所述待检测驱动程序在并发执行的过程中出现中断,则从各函数调用路径中将中断期间的调用函数路径从各所述函数调用路径中删除,并将所述中断期间的调用函数路径记录为独立的调用栈;将与删除后的函数调用路径并发执行的调用函数路径进行组合,将与所述中断期间的调用函数路径并发执行的调用函数路径进行组合,将各所述组合结果作为所述并发执行的函数调用路径组合。

在上述各实施例的基础上,本实施例中检测模块具体用于:若各所述调用栈组合在所述函数调用路径组合中存在,且所述任一潜在竞争访问和所述任一共享变量访问同时满足三个预设条件,则获知所述待检测驱动程序存在数据竞争;其中,第一个所述预设条件为是否访问同一内存地址;第二个所述预设条件为锁集合的交集为空;第三个所述预设条件为至少一个为写操作。

本实施例提供一种电子设备,图3为本发明实施例提供的电子设备整体结构示意图,该设备包括:至少一个处理器301、至少一个存储器302和总线303;其中,

处理器301和存储器302通过总线303完成相互间的通信;

存储器302存储有可被处理器301执行的程序指令,处理器调用程序指令能够执行上述各方法实施例所提供的方法,例如包括:当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;从所述共享变量访问中获取至少含有一个锁的共享变量访问,将含有一个锁的所述共享变量访问作为潜在竞争访问;将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

本实施例提供一种非暂态计算机可读存储介质,非暂态计算机可读存储介质存储计算机指令,计算机指令使计算机执行上述各方法实施例所提供的方法,例如包括:当待检测驱动程序运行时,获取所述待检测驱动程序中的共享变量访问和并发执行的函数调用路径组合;从所述共享变量访问中获取至少含有一个锁的共享变量访问,将含有一个锁的所述共享变量访问作为潜在竞争访问;将任一所述潜在竞争访问的调用栈和所有所述共享变量访问中任一共享变量访问的调用栈进行组合,判断调用栈组合在所述函数调用路径组合中是否存在,根据判断结果确定所述待检测驱动程序是否存在数据竞争。

本领域普通技术人员可以理解:实现上述方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成,前述的程序可以存储于一计算机可读取存储介质中,该程序在执行时,执行包括上述方法实施例的步骤;而前述的存储介质包括:rom、ram、磁碟或者光盘等各种可以存储程序代码的介质。

以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本实施例方案的目的。本领域普通技术人员在不付出创造性的劳动的情况下,即可以理解并实施。

通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到各实施方式可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件。基于这样的理解,上述技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品可以存储在计算机可读存储介质中,如rom/ram、磁碟、光盘等,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行各个实施例或者实施例的某些部分所述的方法。

最后应说明的是:以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1