简介
hyperscan是intel维护开发的一套正则匹配库,用于高性能的进行正则规则匹配;本文主要介绍hyperscan的编译安装和单测,另外包括多核情况下如何适配使用。
编译安装
- mkdir build
- cd build
- cmake --install-prefix=/usr/local/hyperscan/ -DBUILD_STATIC_AND_SHARED=ON -DFAT_RUNTIME=ON -DCMAKE_BUILD_TYPE=Release ../hs_src
- make -j8
- make install
编译参数说明:
- BUILD_STATIC_AND_SHARED 表示静态库和动态库都进行编译
- FAT_RUNTIME 表示编译通用兼容类型,可在更多硬件型号上运行使用
- CMAKE_BUILD_TYPE 表示编译的类型,Release为发布类型
Very Quick Start
-
Clone Hyperscan
cd <where-you-want-hyperscan-source> git clone git://github.com/intel/hyperscan
-
Configure Hyperscan
Ensure that you have the correct dependencies present, and then:
cd <where-you-want-to-build-hyperscan> mkdir <build-dir> cd <build-dir> cmake [-G <generator>] [options] <hyperscan-source-path>
-
Known working generators:
Unix Makefiles
— make-compatible makefiles (default on Linux/FreeBSD/Mac OS X)Ninja
— Ninja build files.Visual Studio 15 2017
— Visual Studio projects
-
Generators that might work include:
Xcode
— OS X Xcode projects.
-
-
Build Hyperscan
-
Depending on the generator used:
cmake --build .
— will build everythingmake -j<jobs>
— use makefiles in parallelninja
— use Ninja buildMsBuild.exe
— use Visual Studio MsBuild- etc.
-
-
Check Hyperscan
Run the Hyperscan unit tests:
bin/unit-hyperscan
单测
源码
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <hs/hs.h>
//打印
#define XFTEST_DBG(fmt, argc...) printf("[file:%s,line:%d,func:%s]" fmt, __FILE__, __LINE__, __FUNCTION__, ##argc)
#define XFTEST_ERR(fmt, argc...) printf("[file:%s,line:%d,func:%s]" fmt, __FILE__, __LINE__, __FUNCTION__, ##argc)
//正则匹配回调函数
static int eventHandler(unsigned int id, unsigned long long from,
unsigned long long to, unsigned int flags, void *ctx) {
id = id;
from = from;
to = to;
flags = flags;
printf("Match for pattern at offset %llu\n", to);
//set matched flag
*(int*)ctx = 1;
return 0;
}
static void
lib_hyperscan_module_test(void)
{
hs_database_t *database;
hs_compile_error_t *compile_err;
const char *pattern = "[f|F]ile";
//默认是大小写敏感的
if (hs_compile(pattern, HS_FLAG_DOTALL|HS_FLAG_CASELESS, HS_MODE_BLOCK, NULL, &database, &compile_err) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to compile pattern \"%s\": %s\n", pattern, compile_err->message);
hs_free_compile_error(compile_err);
return;
}
hs_scratch_t *scratch = NULL;
if (hs_alloc_scratch(database, &scratch) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to allocate scratch space. Exiting.\n");
hs_free_database(database);
return;
}
int hs_ret = 0;
char inputdata[64] = {0};
strcpy(inputdata, "file fIle");
//66, 69, 6c, 65, 20, 66 //file
if (hs_scan(database, inputdata, sizeof(inputdata), 0, scratch, eventHandler, &hs_ret) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to scan input buffer. Exiting.\n");
hs_free_scratch(scratch);
hs_free_database(database);
return;
}
if (hs_ret == 1) {
XFTEST_DBG("[hyperscan] [hs_scan] test success.\n");
} else {
XFTEST_ERR("[hyperscan] [hs_scan] test failed.\n");
}
hs_free_scratch(scratch);
hs_free_database(database);
}
int main()
{
lib_hyperscan_module_test();
}
编译运行
[xiaofeng@localhost test]$ gcc main.c -I /usr/local/hyperscan/include/ -L /usr/local/hyperscan/lib64/ -lstdc++ -lhs -lm
[xiaofeng@localhost test]$ ./a.out
Match for pattern at offset 4
Match for pattern at offset 9
[file:main.c,line:55,func:lib_hyperscan_module_test][hyperscan] [hs_scan] test success.
dpdk多核适配
将allocator系列函数的内存分配和释放函数,指定为dpdk中巨页内存的分配和释放函数,保证多核情况下内存访问正常,否则会段错误。
#include <rte_common.h>
#include <rte_malloc.h>
#include "hs/hs.h"
static
void *__hs_alloc(size_t size)
{
return rte_zmalloc("hs_mem_chunk", size, 64);
}
static
void __hs_free(void *ptr)
{
rte_free(ptr);
}
/**
* @brief - hyperscan allocator adapt fo multicore init.
* @void:
*
* return: 0 for success. otherwise -1.
*/
int dp_hs_allocator_init(void)
{
hs_set_allocator(__hs_alloc, __hs_free);
hs_set_database_allocator(__hs_alloc, __hs_free);
hs_set_misc_allocator(__hs_alloc, __hs_free);
hs_set_scratch_allocator(__hs_alloc, __hs_free);
hs_set_stream_allocator(__hs_alloc, __hs_free);
return 0;
}