2010-08-05 17 views
5

मैं reading की आवश्यकता के बारे में आवश्यकता है कि यदि ओपनएसएसएल बहु-थ्रेडेड एप्लिकेशन में उपयोग किया जाता है, तो आपको OpenSSL के साथ थ्रेड पहचान फ़ंक्शन (और एक म्यूटेक्स सृजन फ़ंक्शन) पंजीकृत करना होगा। (ओपनएसएसएल और मल्टी-थ्रेड्स

static unsigned long id_function(void){ 
    return (unsigned long)pthread_self(); 
} 

pthread_self) एक pthread_t देता है, और यह लिनक्स पर काम करता है के बाद से pthread_t बस है:

लिनक्स पर जो OpenSSL द्वारा प्रदान उदाहरण के अनुसार, एक धागा सामान्य रूप से इस तरह एक समारोह के पंजीकरण के द्वारा पहचाना जाता है हस्ताक्षर किए गए लंबे समय का एक टाइपिफ।

विंडोज pthreads, FreeBSD, और अन्य ऑपरेटिंग सिस्टम पर, pthread_t एक struct है, निम्नलिखित संरचना के साथ:

struct { 
    void * p;     /* Pointer to actual object */ 
    unsigned int x;    /* Extra information - reuse count etc */ 
} 

यह केवल एक अहस्ताक्षरित लंबे में ढाला नहीं जा सकता है, और जब मैं करने की कोशिश इसलिए, यह एक संकलन त्रुटि फेंकता है। मैंने शून्य * पी लेने और एक हस्ताक्षरित लंबे समय तक कास्टिंग करने की कोशिश की, सिद्धांत पर कि स्मृति सूचक सुसंगत और धागे में अद्वितीय होना चाहिए, लेकिन यह मेरे प्रोग्राम को बहुत दुर्घटनाग्रस्त होने का कारण बनता है।

विंडोज़ पर्थ्रेड या फ्रीबीएसडी या किसी अन्य ऑपरेटिंग सिस्टम का उपयोग करते समय ओपनएसएसएल के साथ थ्रेड पहचान फ़ंक्शन के रूप में मैं पंजीकरण कैसे कर सकता हूं?

इसके अलावा, एक अतिरिक्त प्रश्न के रूप में:
किसी को भी इस भी अगर OpenSSL में संकलित और क्यूटी साथ प्रयोग किया जाता है किया जाना चाहिए अगर पता है, और यदि हां कैसे OpenSSL साथ QThreads रजिस्टर करने के लिए? आश्चर्य की बात है, मुझे क्यूटी के दस्तावेज में जवाब नहीं मिल रहा है।

+2

ठीक है, ऐसा लगता है कि OpenSSL तो की @ # $% एक टुकड़ा है। अगर मैं एक (सिंगल थ्रेडेड) ऐप लिखता हूं जो कुछ कार्य के लिए ओपनएसएसएल का उपयोग करता है, और कोई लाइब्रेरी (डीएलएल) लिखता है जो किसी अन्य कार्य के लिए ओपनएसएसएल का उपयोग करता है - यह कैसे एक दूसरे के बारे में जानना चाहिए ये दो पूरी तरह से असंबंधित घटक हैं अस्तित्व - इस बिंदु पर कि उनमें से एक (एकल धागे होने के बावजूद) को इस थ्रेडिंग कार्यक्षमता प्रदान करने की आवश्यकता है। –

उत्तर

1

मैं केवल क्यूटी भाग का जवाब दे सकता हूं। QThread::currentThreadId(), या यहां तक ​​कि QThread::currentThread() का उपयोग करें क्योंकि सूचक मान अद्वितीय होना चाहिए।

+0

मुझे नहीं लगता कि currentThreadId() दस्तावेज़ीकरण में चेतावनियों के आधार पर काम करेगा। वर्तमान थ्रेड के लिए, क्या आप मेमोरी पॉइंटर को लंबे समय तक डालने का सुझाव दे रहे हैं? इसके अलावा, मैं इसे लेता हूं इसका मतलब है कि आपको क्यूटी अनुप्रयोगों में भी यह सब सामान करना है? – Nantucket

+0

हां, मैं इसका सुझाव दे रहा हूं। यह बदसूरत है, लेकिन मुझे कोई और रास्ता नहीं दिख रहा है। –

1

OpenSSL डॉक में आप जुड़े हुए से:

threadid_func(CRYPTO_THREADID *id) आईडी में वर्तमान में क्रियान्वित थ्रेड पहचानकर्ता रिकॉर्ड करने के लिए की जरूरत है। इस कॉलबैक के कार्यान्वयन को सीधे आईडी में भरना नहीं चाहिए, लेकिन CRYPTO_THREADID_set_numeric() का उपयोग करना चाहिए यदि थ्रेड आईडी संख्यात्मक हैं, या CRYPTO_THREADID_set_pointer() यदि वे पॉइंटर-आधारित हैं। यदि एप्लिकेशन CRYPTO_THREADID_set_callback() का उपयोग करके इस तरह के कॉलबैक को पंजीकृत नहीं करता है, तो एक डिफ़ॉल्ट कार्यान्वयन का उपयोग किया जाता है - विंडोज और बीओएस पर यह सिस्टम के डिफ़ॉल्ट थ्रेड को पहचानने वाले एपीआई का उपयोग करता है, और अन्य सभी प्लेटफॉर्म पर यह इरनो के पते का उपयोग करता है। उत्तरार्द्ध थ्रेड-सुरक्षा के लिए संतोषजनक है अगर केवल तभी प्लेटफ़ॉर्म में थ्रेड-स्थानीय त्रुटि संख्या सुविधा हो।

जैसा कि दिखाया गया है कि आपकी खुद की आईडी प्रदान करना वास्तव में केवल उपयोगी है यदि आप OpenSSL के डिफ़ॉल्ट कार्यान्वयन से बेहतर आईडी प्रदान कर सकते हैं।

आईडी प्रदान करने का एकमात्र असफल-सुरक्षित तरीका, जब आप नहीं जानते कि pthread_t एक सूचक या पूर्णांक है, तो थ्रेड-स्थानीय मान के रूप में संग्रहीत अपने स्वयं के प्रति-थ्रेड आईडी को बनाए रखना है।

5

मैं बस यह कोड यहां डालूंगा। यह पैनसिया नहीं है, क्योंकि यह फ्रीबीएसडी से निपटता नहीं है, लेकिन ज्यादातर मामलों में यह सहायक होता है जब आपको विंडोज़ का समर्थन करना और डेबियन कहना है। बेशक, स्वच्छ समाधान हाल ही में पेश किए गए CRYPTO_THREADID_* परिवार के उपयोग को मानता है।(जानकारी देने के लिए, यह एक CRYPTO_THREADID_cmp कॉलबैक, जो pthread_equal मैप किया जा सकता है)

#include <pthread.h> 
#include <openssl/err.h> 

#if defined(WIN32) 
    #define MUTEX_TYPE   HANDLE 
    #define MUTEX_SETUP(x)  (x) = CreateMutex(NULL, FALSE, NULL) 
    #define MUTEX_CLEANUP(x)  CloseHandle(x) 
    #define MUTEX_LOCK(x)   WaitForSingleObject((x), INFINITE) 
    #define MUTEX_UNLOCK(x)  ReleaseMutex(x) 
    #define THREAD_ID    GetCurrentThreadId() 
#else 
    #define MUTEX_TYPE   pthread_mutex_t 
    #define MUTEX_SETUP(x)  pthread_mutex_init(&(x), NULL) 
    #define MUTEX_CLEANUP(x)  pthread_mutex_destroy(&(x)) 
    #define MUTEX_LOCK(x)   pthread_mutex_lock(&(x)) 
    #define MUTEX_UNLOCK(x)  pthread_mutex_unlock(&(x)) 
    #define THREAD_ID    pthread_self() 
#endif 

/* This array will store all of the mutexes available to OpenSSL. */ 
static MUTEX_TYPE *mutex_buf=NULL; 

static void locking_function(int mode, int n, const char * file, int line) 
{ 
    if (mode & CRYPTO_LOCK) 
     MUTEX_LOCK(mutex_buf[n]); 
    else 
     MUTEX_UNLOCK(mutex_buf[n]); 
} 

static unsigned long id_function(void) 
{ 
    return ((unsigned long)THREAD_ID); 
} 

int thread_setup(void) 
{ 
    int i; 

    mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE)); 
    if (!mutex_buf) 
     return 0; 
    for (i = 0; i < CRYPTO_num_locks(); i++) 
     MUTEX_SETUP(mutex_buf[i]); 
    CRYPTO_set_id_callback(id_function); 
    CRYPTO_set_locking_callback(locking_function); 
    return 1; 
} 

int thread_cleanup(void) 
{ 
    int i; 
    if (!mutex_buf) 
     return 0; 
    CRYPTO_set_id_callback(NULL); 
    CRYPTO_set_locking_callback(NULL); 
    for (i = 0; i < CRYPTO_num_locks(); i++) 
     MUTEX_CLEANUP(mutex_buf[i]); 
    free(mutex_buf); 
    mutex_buf = NULL; 
    return 1; 
} 
+0

अभी मैं अपने ओपनएसएसएल ऐप के साथ कई धागे का उपयोग करने में सक्षम होने के लिए काम कर रहा हूं। और मैं set_id कॉलबैक के बारे में कुछ और समझना चाहता हूं: ओपनएसएसएल दस्तावेज़ों में लिखा गया है कि अगर हम इस फ़ंक्शन को लागू नहीं करते हैं, तो एक डिफ़ॉल्ट कार्यान्वयन का उपयोग किया जाता है - क्या आप जानते हैं कि डिफ़ॉल्ट आईएमएन विंडो क्या है? क्या यह आपके कार्यान्वयन से अलग है? और क्या आप गतिशील ताले कॉलबैक के बारे में कुछ जानते हैं - क्या हमें इसे लागू करना है? धन्यवाद! – RRR

+0

@RRR मैं आपके सभी प्रश्नों को दूसरा करता हूं। डायनामिक लॉक एपीआई में काफी नए लगते हैं, और इंटरनेट पर ओपनएसएसएल के साथ थ्रेडिंग उदाहरण पुराने हैं। ऐसा लगता है कि इसे पीछे की संगतता को सक्षम करने के लिए अभी भी काम करना चाहिए, लेकिन डायनलॉक्स बेहतर प्रदर्शन जोड़ सकता है - यह मेरा झटका है। – Tosha

संबंधित मुद्दे