2012-02-27 10 views
9

मैं इस धारणा के तहत था कि flock(2) थ्रेड सुरक्षित है, मैंने हाल ही में कोड में मामले में भाग लिया है, जहां एकाधिक थ्रेड एक ही फ़ाइल पर लॉक प्राप्त करने में सक्षम हैं सभी सीपीआई झुंड का उपयोग कर विशेष ताला प्राप्त करने के उपयोग के साथ सिंक्रनाइज़। प्रक्रिया 25554 बहु-थ्रेडेड ऐप है जिसमें 20 थ्रेड हैं, उसी फ़ाइल में लॉक होने वाले धागे की संख्या भिन्न होती है जब डेडलॉक होता है। बहु थ्रेडेड ऐप testEvent फ़ाइल के लेखक हैं, जहां पुश फ़ाइल से पाठक था। दुर्भाग्यवश lsof एलडब्लूपी मूल्य मुद्रित नहीं करता है, इसलिए मुझे नहीं पता कि लॉक रखने वाले थ्रेड कौन से हैं। जब नीचे उल्लिखित स्थिति होती है तो pstack या strace द्वारा 25569 और 25554 पर कॉल के रूप में प्रदर्शित की गई प्रक्रिया और थ्रेड दोनों फ्लॉक कॉल पर फंस गए हैं। RHEL 4.x में इसे कैसे दूर किया जाए इस पर कोई सुझाव।एक ही समय में झुंड प्राप्त करने में सक्षम कई धागे

एक चीज जिसे मैं अपडेट करना चाहता था वह है कि झुंड हर समय गलत व्यवहार नहीं करता है, जब संदेशों की टीएक्स दर केवल 2 एमबीपीएस से अधिक होती है तो मैं झुंड के साथ इस डेडलॉक मुद्दे में आ जाता हूं, नीचे टीएक्स दर सब कुछ फाइल है। मैंने num_threads = 20, size_of_msg = 1000bytes निरंतर रखा है और केवल 10 संदेशों से 100 संदेशों तक टीएक्स प्रति सेकंड शुरू होने की संख्या में भिन्नता है जो 20 * 1000 * 100 = 2 एमबीपीएस है, जब मैं 150 की संदेशों को बढ़ाता हूं तो झुंड मुद्दा होता है।

मैं सिर्फ पूछना चाहता था कि फ्लॉकफाइल सी एपीआई के बारे में आपकी क्या राय है।

sudo lsof filename.txt 
    COMMAND  PID  USER  FD  TYPE  DEVICE  SIZE NODE  NAME 
    push   25569 root  11u  REG  253.4  1079 49266853 filename.txt 
    testEvent 25554 root  27uW  REG  253.4  1079 49266853 filename.txt 
    testEvent 25554 root  28uW  REG  253.4  1079 49266853 filename.txt 
    testEvent 25554 root  29uW  REG  253.4  1079 49266853 filename.txt 
    testEvent 25554 root  30uW  REG  253.4  1079 49266853 filename.txt 

बहु परीक्षण कार्यक्रम कि write_data_lib_func lib समारोह कॉल करेंगे।

void* sendMessage(void *arg) { 

int* numOfMessagesPerSecond = (int*) arg; 
std::cout <<" Executing p thread id " << pthread_self() << std::endl; 
while(!terminateTest) { 
    Record *er1 = Record::create(); 
    er1.setDate("some data"); 

    for(int i = 0 ; i <=*numOfMessagesPerSecond ; i++){ 
    ec = _write_data_lib_func(*er1); 
    if(ec != SUCCESS) { 
     std::cout << "write was not successful" << std::endl; 

    } 

    } 
    delete er1; 
    sleep(1); 
} 

return NULL; 

उपरोक्त विधि परीक्षण के मुख्य कार्य में pthreads में कहा जाएगा।

for (i=0; i<_numThreads ; ++i) { 
    rc = pthread_create(&threads[i], NULL, sendMessage, (void *)&_num_msgs); 
    assert(0 == rc); 

}

यहाँ लेखक/पाठक स्रोत, मालिकाना कारणों मैं बस में कटौती करने और पेस्ट, लेखक स्रोत एक प्रक्रिया

int write_data_lib_func(Record * rec) {  
if(fd == -1) { 
    fd = open(fn,O_RDWR| O_CREAT | O_APPEND, 0666); 
} 
if (fd >= 0) { 
    /* some code */ 

    if(flock(fd, LOCK_EX) < 0) { 
    print "some error message"; 
    } 
    else { 
    if(maxfilesize) { 
     off_t len = lseek (fd,0,SEEK_END); 
     ... 
     ... 
     ftruncate(fd,0); 
     ... 
     lseek(fd,0,SEEK_SET); 
    } /* end of max spool size */ 
    if(writev(fd,rec) < 0) { 
    print "some error message" ; 
    } 

    if(flock(fd,LOCK_UN) < 0) { 
    print some error message; 
    } 
में एक से अधिक थ्रेड पहुँचा होगा नहीं करना चाहता था की वजह से है

चीजों के पाठक पक्ष में कोई धागे के साथ एक डेमॉन प्रक्रिया है।

int readData() { 
    while(true) { 
     if(fd == -1) { 
     fd= open (filename,O_RDWR); 
     } 
     if(flock (fd, LOCK_EX) < 0) { 
     print "some error message"; 
     break; 
     } 
     if(n = read(fd,readBuf,readBufSize)) < 0) { 
     print "some error message" ; 
     break; 
     } 
     if(off < n) { 
     if (off <= 0 && n > 0) { 
      corrupt_file = true; 
     } 
     if (lseek(fd, off-n, SEEK_CUR) < 0) { 
      print "some error message"; 
     } 
     if(corrupt_spool) { 
      if (ftruncate(fd,0) < 0) { 
      print "some error message"; 
      break; 
      } 
     } 
     } 
     if(flock(fd, LOCK_UN) < 0) 
     print some error message ; 
     } 
    }  
} 
+0

क्या आप 'फ़्लॉक' नामक कोड पोस्ट कर सकते हैं? एक [सरल] (http://sscce.org) परीक्षण कार्यक्रम अच्छा होगा। – phihag

+0

AFAIK, सलाहकार ताले स्थिरता की गारंटी नहीं देते हैं। http://www.gsp.com/cgi-bin/man.cgi?section=2&topic=flock – zengr

उत्तर

8

flock(2) के रूप में दर्ज है, "अगर एक असंगत ताला एक और प्रक्रिया के द्वारा आयोजित किया जाता है अवरुद्ध" और साथ "झुंड द्वारा बनाई ताले() एक खुली फ़ाइल तालिका प्रविष्टि के साथ जुड़े रहे", तो यह उम्मीद की जानी चाहिए कि flock-उसी प्रक्रिया के कई धागे से ताले ताले संपर्क नहीं करते हैं। (flock दस्तावेज़ीकरण धागे का उल्लेख नहीं करते हैं)।

इसलिए, समाधान आपके लिए आसान होना चाहिए: प्रत्येक pthread_mutex_t प्रत्येक flock-फ़ाइल फ़ाइल डिस्क्रिप्टर को संबद्ध करें, और कॉल को उस म्यूटेक्स के साथ flock पर सुरक्षित रखें। यदि आप रीड बनाम लिखना लॉक करना चाहते हैं तो आप pthread_rwlock_t का भी उपयोग कर सकते हैं।

+0

?? स्रोत कोड कहां है ??? –

+0

मैंने अब स्रोत जोड़ा है। आपके उत्तर के लिए धन्यवाद – user1235176

+0

मुझे यकीन है एक ही पंक्ति में सोच रहा था झुंड के साथ एक म्युटेक्स संबद्ध करने के लिए, क्या परेशान कर रहा था मुझे झुंड (2) fcntl (2) के शीर्ष पर बैठता था, और fcntl (2) lockf (2) का दावा किया धागा सुरक्षित, तो यह मुझे आश्चर्यचकित था कि यह नहीं है। – user1235176

2

झुंड के लिए लिनक्स आदमी पेज (2) से:

झुंड द्वारा बनाई ताले() एक खुली फ़ाइल तालिका प्रविष्टि के साथ जुड़े रहे हैं। इसका मतलब है कि डुप्लिकेट फ़ाइल वर्णनकर्ता (, के द्वारा बनाई गई उदाहरण के लिए, कांटा (2) या dup (2)) एक ही ताला का उल्लेख है, और इस ताला संशोधित या इन वर्णनकर्ता के किसी भी उपयोग जारी किया जा सकता। इसके अलावा, ताला इन डुप्लिकेट वर्णनकर्ता में से किसी पर कोई स्पष्ट LOCK_UN आपरेशन द्वारा जारी की है या तो, या जब ऐसे सभी वर्णनकर्ता बंद कर दिए गए।

इसके अलावा,, झुंड ताले नहीं 'ढेर' होते हैं, इसलिए यदि आप एक ताला आप पहले से ही पकड़ पाने की कोशिश, झुंड कॉल एक NOOP कि ब्लॉक किए बिना और किसी भी तरह से ताला राज्य बदले बिना तुरंत वापस लौट है ।

एक प्रक्रिया शेयर फ़ाइल वर्णनकर्ता भीतर धागे के बाद से, आप फ़ाइल अलग धागे से कई बार झुंड कर सकते हैं, और यह ब्लॉक नहीं, के रूप में लॉक पहले से आयोजित किया जाता है।

झुंड (2) पर नोट से

इसके अलावा:

झुंड() और fcntl (2) ताले काँटेदार प्रक्रियाओं के संबंध में और dup के साथ अलग अलग अर्थ विज्ञान है (2)। प्रणाली है कि झुंड() को लागू fcntl (2) का उपयोग करते हुए, झुंड के शब्दों() उन इस मैनुअल पेज में वर्णित से अलग होगा।

+0

यह सही क्रिस नहीं है यदि आप मेरे lsof आउटपुट को देखते हैं तो फाइल डिस्क्रिप्टर प्रत्येक थ्रेड के लिए अद्वितीय होते हैं। – user1235176

+2

एक प्रक्रिया शेयर फ़ाइल वर्णनकर्ताओं के भीतर थ्रेड। देखें http://stackoverflow.com/questions/6223776/threads-and-file-descriptors EDIT ---- और मुझे लगता है कि हम में से अधिकांश जिन्होंने बहु-थ्रेडेड प्रोग्राम लिखे हैं, ने फ़ाइल को कोड लिखा है वर्णनकर्ताओं को धागे में साझा किया जाता है। –

+0

यह स्वीकार्य उत्तर होना चाहिए था ... –

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