我有一个巨大的代码(这是我的学校项目),我在其中使用 Openssl
。一切都很完美,直到我决定采用多线程。我选择 openmp
作为我的线程环境,因为它非常简单且易于学习(至少我需要的基础很简单)。
我的整个代码如下所示:
struct mystr[10];
omp_set_num_threads(10);
#pragma omp parallel
{
mystr[omp_get_thread_num()] = call_fun_which_uses_openssl();
}
CRYPTO_cleanup_all_ex_data();
我的 call_fun_which_uses_openssl
函数使用低级 openssls api 函数 (MD4((unsigned char*)&string, strlen(string), (unsigned char*)&digest);
MD4_CTX ctx
等)。我的函数使用 RSA、DSA...并且无法访问任何全局变量,它使用的每个变量都在 call_fun_which_uses_openssl 内声明,因此像我一样执行多线程应该保证这些变量保持私有(private)。虽然,我有时会遇到这段代码的段错误。我读到 CRYPTO_cleanup_all_ex_data
不是线程安全的(但由于内存泄漏我需要它),但我在并行区域之外使用它,对吧?当我删除 openmp
调用时,每次都会正常工作,因此多线程和 openssl
一定存在问题。有什么想法如何解决吗?
在我看来它应该可以工作,因为 call_fun_which_uses_openssl
的线程调用为每个线程创建自己的私有(private)变量,应该没有问题......请帮助:)
最佳答案
查看 OpenSSL 源代码树中的示例 openssl/crypto/threads/mttest.c
。基本上,您必须提供两个回调函数:
- 实现锁定和解锁的一个
- 返回唯一的线程 ID。
两者都可以使用 OpenMP 轻松实现:
omp_lock_t *locks;
// Locking callback
void openmp_locking_callback(int mode, int type, char *file, int line)
{
if (mode & CRYPTO_LOCK)
{
omp_set_lock(&locks[type]);
}
else
{
omp_unset_lock(&locks[type]);
}
}
// Thread ID callback
unsigned long openmp_thread_id(void)
{
return (unsigned long)omp_get_thread_num();
}
开始之前,必须初始化锁并设置回调:
void openmp_thread_setup(void)
{
int i;
locks = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(omp_lock_t));
for (i=0; i<CRYPTO_num_locks(); i++)
{
omp_init_lock(&locks[i]);
}
CRYPTO_set_id_callback((unsigned long (*)())openmp_thread_id);
CRYPTO_set_locking_callback((void (*)())openmp_locking_callback);
}
void openmp_thread_cleanup(void)
{
int i;
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for (i=0; i<CRYPTO_num_locks(); i++)
omp_destroy_lock(&locks[i]);
OPENSSL_free(locks);
}
您应该在程序中第一个并行区域之前的某个位置调用 openmp_thread_setup()
一次,并且应该在最后一个并行区域之后调用 openmp_thread_cleanup()
一次:
// Program start
openmp_thread_setup();
#pragma omp parallel
{
// Parallel OpenSSL calls are now data race free
}
#pragma omp parallel
{
// Parallel OpenSSL calls are now data race free
}
#pragma omp parallel
{
// Parallel OpenSSL calls are now data race free
}
openmp_thread_cleanup();
// Program should end now
关于c - 使用 OpenMP 和 OpenSSL 时的内存泄漏和段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22906207/