क्या लिनक्स पर प्रक्रियाओं के रूप में धागे लागू होते हैं?


65

मैं इस पुस्तक के माध्यम से जा रहा हूँ , एडवांस्ड लिनक्स प्रोग्रामिंग मार्क मिशेल, जेफरी ओल्डहम और एलेक्स सैमुअल द्वारा। यह 2001 से है, इसलिए थोड़ा पुराना है। लेकिन मुझे यह किसी भी तरह काफी अच्छा लगता है।

हालाँकि, मुझे एक बिंदु पर मिला जब यह खोल देता है कि मेरा लिनक्स शेल आउटपुट में क्या उत्पन्न करता है। पृष्ठ 92 (दर्शक में 116) पर, अध्याय 4.5 GNU / Linux थ्रेड कार्यान्वयन इस अनुच्छेद वाले पैराग्राफ से शुरू होता है:

GNU / Linux पर POSIX थ्रेड्स का कार्यान्वयन एक महत्वपूर्ण तरीके से कई अन्य UNIX जैसे सिस्टम पर थ्रेड कार्यान्वयन से भिन्न होता है: GNU / Linux पर, थ्रेड को प्रक्रियाओं के रूप में लागू किया जाता है।

यह एक मुख्य बिंदु की तरह लगता है और बाद में एक सी कोड के साथ सचित्र होता है। पुस्तक में आउटपुट है:

main thread pid is 14608
child thread pid is 14610

और मेरे Ubuntu 16.04 में यह है:

main thread pid is 3615
child thread pid is 3615

ps आउटपुट इसका समर्थन करता है।

मुझे लगता है कि 2001 और अब के बीच कुछ बदल गया होगा।

अगले पृष्ठ पर अगला उपचर्च, 4.5.1 सिग्नल हैंडलिंग, पिछले विवरण पर बनाता है:

संकेतों और थ्रेड्स के बीच बातचीत का व्यवहार एक यूनिक्स-जैसी प्रणाली से दूसरे में भिन्न होता है। जीएनयू / लिनक्स में, व्यवहार को इस तथ्य से निर्धारित किया जाता है कि थ्रेड को प्रक्रियाओं के रूप में लागू किया जाता है।

और ऐसा लग रहा है कि पुस्तक में बाद में यह और भी महत्वपूर्ण होगा। क्या कोई समझा सकता है कि यहाँ क्या हो रहा है?

मैंने देखा है कि क्या लिनक्स कर्नेल थ्रेड वास्तव में कर्नेल प्रक्रियाएं हैं? , लेकिन यह बहुत मदद नहीं करता है। मैं उलझन में हूं।

यह C कोड है:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* thread_function (void* arg)
{
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());
    /* Spin forever. */
    while (1);
    return NULL;
}

int main ()
{
    pthread_t thread;
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());
    pthread_create (&thread, NULL, &thread_function, NULL);
    /* Spin forever. */
    while (1);
    return 0;
}

1
मुझे आपकी उलझन का स्रोत नहीं मिला। थ्रेड्स को उनके माता-पिता के साथ पता स्थान साझा करने वाली प्रक्रियाओं के रूप में लागू किया जाता है।
जोहान मायरेन

2
@ JohanMyréen तो धागे के टुकड़े समान क्यों हैं?
टॉमस

आह, अब मैं देख रहा हूं। हां, वास्तव में कुछ बदल गया है। देखिए @ ilkachachu का जवाब।
जोहान मायरेन

5
थ्रेड्स को अभी भी प्रक्रियाओं के रूप में लागू किया जाता है - हालांकि अब getpidवह रिटर्न देता है जिसे थ्रेड ग्रुप आईडी कहा जाएगा और जिस प्रक्रिया का आपको उपयोग करने की आवश्यकता है उसके लिए एक यूनिक आईडी प्राप्त करना होगा gettid। हालांकि, कर्नेल के अलावा, अधिकांश लोग और उपकरण एक थ्रेड समूह को एक प्रक्रिया कहेंगे, और एक प्रक्रिया को अन्य सिस्टम के साथ संगतता के लिए एक थ्रेड कहेंगे।
user253751

ज़रुरी नहीं। एक प्रक्रिया का अपना स्मृति और फ़ाइल वर्णनकर्ता, यह एक धागा कभी नहीं कहा जाता है, ऐसा करने से हो सकता है है में अन्य प्रणालियों के साथ संगत।
रीयरियरपोस्ट

जवाबों:


50

मुझे लगता है कि clone(2)मैन पेज का यह हिस्सा अंतर को फिर से साफ कर सकता है। पीआईडी:

CLONE_THREAD (Linux 2.4.0-test8 के बाद से)
यदि CLONE_THREAD सेट किया गया है, तो बच्चे को कॉलिंग प्रक्रिया के समान थ्रेड समूह में रखा गया है।
थ्रेड समूह लिनक्स 2.4 में जोड़े गए एक फीचर में थ्रेड्स के एक सेट के पॉसिक्स थ्रेड्स धारणा का समर्थन करने के लिए थे जो एक एकल पीआईडी ​​को साझा करते हैं। आंतरिक रूप से, यह साझा पीआईडी ​​थ्रेड समूह के लिए तथाकथित थ्रेड ग्रुप आइडेंटिफायर (टीजीआईडी) है। लिनक्स 2.4 के बाद से, getpid (2) पर कॉल करने वाले का TGID वापस कर देता है।

"थ्रेड्स को प्रक्रियाओं के रूप में लागू किया जाता है" वाक्यांश थ्रेड्स के मुद्दे को संदर्भित करता है जिनके पास अतीत में अलग-अलग पीआईडी ​​थे। असल में, लिनक्स में मूल रूप से एक प्रक्रिया के भीतर थ्रेड्स नहीं थे, बस अलग-अलग प्रक्रियाएं (अलग पीआईडी ​​के साथ) जिसमें कुछ साझा संसाधन हो सकते थे, जैसे वर्चुअल मेमोरी या फ़ाइल डिस्क्रिप्टर। CLONE_THREADऔर प्रक्रिया आईडी (*) और थ्रेड आईडी के पृथक्करण से लिनक्स व्यवहार अन्य प्रणालियों की तरह दिखता है और इस अर्थ में POSIX आवश्यकताओं की तरह। यद्यपि तकनीकी रूप से ओएस में अभी भी थ्रेड और प्रक्रियाओं के लिए अलग-अलग कार्यान्वयन नहीं हैं।

सिग्नल हैंडलिंग पुराने कार्यान्वयन के साथ एक और समस्याग्रस्त क्षेत्र था, यह पेपर में अधिक विस्तार से वर्णित है @FooF उनके उत्तर में संदर्भित करता है ।

जैसा कि टिप्पणियों में उल्लेख किया गया है, लिनक्स 2.4 भी पुस्तक के रूप में उसी वर्ष 2001 में जारी किया गया था, इसलिए यह आश्चर्यजनक नहीं है कि खबर उस प्रिंट तक नहीं पहुंची।


2
वर्चुअल मेमोरी या फ़ाइल डिस्क्रिप्टर जैसे कुछ साझा संसाधनों के लिए अलग-अलग प्रक्रियाएँ हो सकती हैं। लिनक्स थ्रेड्स के काम करने के तरीके के बारे में अभी भी बहुत कुछ है, जिन मुद्दों का आप उल्लेख करते हैं, उन्हें साफ किया गया है। मैं कहूंगा कि कर्नेल "थ्रेड्स" या "प्रोसेस" में उपयोग की जाने वाली शेड्यूलिंग इकाइयों को कॉल करना वास्तव में अप्रासंगिक है। तथ्य यह है कि वे केवल "प्रक्रियाओं" कहे जाने वाले लिनक्स पर शुरू हुए, इसका मतलब यह नहीं है कि वे अब हैं।
एंड्रयू हेनले

@AndrewHenle, हाँ, थोड़ा संपादित किया। मुझे आशा है कि आपके विचार को पकड़ लेता है, हालांकि मैं शब्दों के साथ एक कठिन समय लगता है। (आगे बढ़ो और अगर आपको पसंद है तो उस हिस्से को संपादित करें।) मैं समझ गया हूं कि कुछ अन्य यूनिक्स-जैसे ओएस में थ्रेड्स बनाम प्रक्रियाओं का एक अधिक विशिष्ट पृथक्करण है, जिसमें लिनक्स केवल एक प्रकार की सेवा होने के अलावा एक अपवाद के रूप में है। दोनों कार्य। लेकिन मैं अन्य प्रणालियों के बारे में पर्याप्त नहीं जानता और सूत्रों के पास काम नहीं है, इसलिए कुछ भी कहना मुश्किल है।
इलकाचू

@tomas ध्यान दें कि यह उत्तर बताता है कि लिनक्स अब कैसे काम करता है। इलकाचु के संकेत के रूप में, इसने किताब लिखने के समय अलग तरह से काम किया। FooF का जवाब बताता है कि उस समय लिनक्स कैसे काम करता था।
गाइल्स

38

आप सही कह रहे हैं, "2001 और अब के बीच कुछ बदल गया होगा"। आप जिस पुस्तक को पढ़ रहे हैं, वह लिनक्स पर POSIX थ्रेड्स के पहले ऐतिहासिक कार्यान्वयन के अनुसार दुनिया का वर्णन करती है, जिसे LinuxThreads कहा जाता है ( कुछ के लिए विकिपीडिया लेख भी देखें )।

लिनक्स थ्रेड्स में POSIX मानक के साथ कुछ संगतता मुद्दे थे - उदाहरण के लिए धागे PID को साझा नहीं कर रहे हैं - और कुछ अन्य गंभीर समस्याएं। इन खामियों को ठीक करने के लिए, NPTL (Native POSIX Thread Library) नामक एक अन्य कार्यान्वयन को बेहतर POSIX अनुपालन तक पहुँचने के लिए Red Hat द्वारा Spearheaded किया गया था ताकि बेहतर POSIX अनुपालन तक पहुँच सके और IBM द्वारा एक और प्रतिस्पर्धात्मक कार्यान्वयन परियोजना (NGPT) कहा जाता है। नेक्स्ट जनरेशन पोज़िक्स थ्रेड्स "), NPTL पर विकिपीडिया लेख देखें )। clone(2)सिस्टम कॉल में जोड़े गए अतिरिक्त झंडे (विशेष रूप से CLONE_THREADजो उसके उत्तर@ikkkachu में बताते हैं ) संभवतः कर्नेल संशोधनों का सबसे स्पष्ट हिस्सा है। कार्य का उपयोगकर्ता स्थान भाग अंततः GNU C लाइब्रेरी में शामिल किया गया।

अभी भी कुछ एम्बेडेड लिनक्स SDK पुराने LinuxThreads कार्यान्वयन का उपयोग करते हैं क्योंकि वे LibC के छोटे मेमोरी फ़ुटप्रिंट संस्करण का उपयोग कर रहे हैं, जिसे uClibc (जिसे ibClibc भी कहा जाता है) कहा जाता है , और इसे GNU LibC से NPTL स्पेस लागू करने से पहले काफी वर्षों तक लिया गया था और मान लिया गया था। डिफ़ॉल्ट POSIX थ्रेडिंग कार्यान्वयन, जैसा कि आम तौर पर बोलते हुए ये विशेष प्लेटफॉर्म बिजली की गति के साथ नवीनतम फैशन का पालन करने का प्रयास नहीं करते हैं। यह ध्यान देने से देखा जा सकता है कि वास्तव में उन प्लेटफार्मों पर विभिन्न थ्रेड्स के लिए PIDs भी POSIX मानक निर्दिष्टियों के विपरीत अलग-अलग हैं - ठीक उसी तरह जैसे आप जिस पुस्तक का वर्णन पढ़ रहे हैं। असल में एक बार आपने फोन कियाpthread_create(), आपने अचानक गड़बड़ी को दूर रखने के लिए अतिरिक्त प्रक्रिया को एक से तीन तक बढ़ा दिया था क्योंकि अतिरिक्त प्रक्रिया की आवश्यकता थी।

लिनक्स pthreads (7) मैनुअल पेज दोनों के बीच अंतर का एक व्यापक और दिलचस्प अवलोकन प्रदान करता है। एक और ज्ञानवर्धक, हालांकि आउट-ऑफ-डेट, मतभेदों का वर्णन एनपीटीएल के डिजाइन के बारे में उलरिच डेपर और इंगो मोलनार का यह पत्र है।

मैं आपको सलाह देता हूं कि किताब के उस हिस्से को भी गंभीरता से न लें। मैं इसके बजाय ब्यूटेनहोफ़ के प्रोग्रामिंग पॉसिक्स थ्रेड्स और पॉज़िक्स और लिनक्स मैनुअल पेजों के बारे में सलाह देता हूं। विषय पर कई ट्यूटोरियल गलत हैं।


22

(यूजरस्पेस) थ्रेड्स को लिनक्स पर इस तरह की प्रक्रियाओं के रूप में लागू नहीं किया जाता है, जिसमें उनका अपना निजी पता स्थान नहीं होता है, फिर भी वे मूल प्रक्रिया का पता स्थान साझा करते हैं।

हालाँकि, इन थ्रेड्स को कर्नेल प्रोसेस अकाउंटिंग सिस्टम का उपयोग करने के लिए लागू किया जाता है, इसलिए इन्हें अपनी थ्रेड आईडी (TID) आवंटित की जाती है, लेकिन इन्हें PID और 'थ्रेड ग्रुप ID' (TGID) को मूल प्रक्रिया के रूप में दिया जाता है - यह इसके विपरीत है। एक कांटा, जहां एक नया TGID और PID बनाया जाता है, और TID PID के समान होता है।

तो ऐसा प्रतीत होता है कि हाल की गुठली के पास एक अलग TID था जिसे क्वेर किया जा सकता है, यह वह है जो थ्रेड्स के लिए अलग है, मुख्य (प्रत्येक) थ्रेड_फंक्शन () में से प्रत्येक में यह दिखाने के लिए एक उपयुक्त कोड स्निपेट है:

    long tid = syscall(SYS_gettid);
    printf("%ld\n", tid);

तो इस के साथ पूरा कोड होगा:

#include <pthread.h>                                                                                                                                          
#include <stdio.h>                                                                                                                                            
#include <unistd.h>                                                                                                                                           
#include <syscall.h>                                                                                                                                          

void* thread_function (void* arg)                                                                                                                             
{                                                                                                                                                             
    long tid = syscall(SYS_gettid);                                                                                                                           
    printf("child thread TID is %ld\n", tid);                                                                                                                 
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());                                                                                            
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return NULL;                                                                                                                                              
}                                                                                                                                                             

int main ()                                                                                                                                                   
{                                                                                                                                               
    pthread_t thread;                                                                               
    long tid = syscall(SYS_gettid);     
    printf("main TID is %ld\n", tid);                                                                                             
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());                                                    
    pthread_create (&thread, NULL, &thread_function, NULL);                                           
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return 0;                                                                                                                                                 
} 

का एक उदाहरण आउटपुट देते हुए:

main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963

3
@ टोटमस ईनोनम सही है। उपेक्षा करें कि पुस्तक क्या कहती है, यह बहुत भ्रामक है। डनो को पता है कि लेखक किस विचार को व्यक्त करना चाहता था, लेकिन वह बुरी तरह विफल रहा। तो, लिनक्स में आपके पास कर्नेल थ्रेड्स और उपयोगकर्ता-स्थान थ्रेड्स हैं। कर्नेल थ्रेड्स अनिवार्य रूप से उपयोगकर्ता स्थान के बिना प्रक्रियाएं हैं। उपयोगकर्ता-स्थान थ्रेड सामान्य POSIX थ्रेड हैं। यूजर स्पेस प्रोसेस फाइल डिस्क्रिप्टर शेयर करते हैं, कोड सेगमेंट शेयर कर सकते हैं, लेकिन पूरी तरह से अलग वर्चुअल एड्रेस स्पेस में रहते हैं। यूजर स्पेस थ्रेड्स एक प्रोसेस शेयर कोड सेगमेंट, स्टैटिक मेमोरी और हीप (डायनामिक मेमोरी) के भीतर होते हैं, लेकिन अलग-अलग प्रोसेसर रजिस्टर और स्टैक होते हैं।
बोरिस बुर्कोव

8

मूल रूप से, आपकी पुस्तक की जानकारी ऐतिहासिक रूप से सटीक है, क्योंकि लिनक्स पर थ्रेड्स के शर्मनाक खराब कार्यान्वयन इतिहास के कारण। मेरे द्वारा SO पर संबंधित प्रश्न का यह उत्तर आपके प्रश्न के उत्तर के रूप में भी कार्य करता है:

https://stackoverflow.com/questions/9154671/distinction-between-processes-and-threads-in-linux/9154725#9154725

ये सभी इस तथ्य से भ्रमित होते हैं कि कर्नेल डेवलपर्स ने मूल रूप से एक तर्कहीन और गलत दृष्टिकोण रखा था कि धागे को पूरी तरह से आदिम के रूप में कर्नेल प्रक्रियाओं का उपयोग करके उपयोगकर्तापेस में लागू किया जा सकता है, जब तक कि कर्नेल ने उन्हें मेमोरी और फ़ाइल डिस्क्रिप्टर बनाने का एक तरीका पेश किया। । यह POSIX थ्रेड्स के कुख्यात बुरे LinuxThreads कार्यान्वयन के लिए ले जाता है, जो कि एक मिथ्या नाम था क्योंकि इसने POSIX थ्रेड शब्दार्थों के समान दूरस्थ रूप से कुछ भी नहीं दिया था। आखिरकार LinuxThreads को NPTL द्वारा बदल दिया गया, लेकिन बहुत सी भ्रमित शब्दावली और गलतफहमी बनी हुई है।

एहसास करने वाली पहली और सबसे महत्वपूर्ण बात यह है कि "पीआईडी" का मतलब है कि कर्नेल स्पेस और यूजर स्पेस में अलग-अलग चीजें। कर्नेल जिसे पीआईडी ​​कहते हैं, वह वास्तव में कर्नेल-स्तरीय थ्रेड आईडी (जिसे अक्सर TID कहा जाता है) है, pthread_tजिसे भ्रमित न करने के लिए एक अलग पहचानकर्ता है। सिस्टम पर प्रत्येक थ्रेड, चाहे एक ही प्रक्रिया में या एक अलग से, एक अद्वितीय TID (या कर्नेल शब्दावली में "PID") है।

"प्रक्रिया" के POSIX अर्थ में PID को क्या माना जाता है, दूसरी ओर, कर्नेल में "थ्रेड ग्रुप ID" या "TGID" कहा जाता है। प्रत्येक प्रक्रिया में एक या एक से अधिक थ्रेड्स (कर्नेल प्रक्रियाएं) होती हैं, जिनमें से प्रत्येक का अपना TID (कर्नेल PID) होता है, लेकिन सभी एक ही TGID को साझा करते हैं, जो आरंभिक धागे के TID (कर्नेल PID) के बराबर होता है, जिसमें mainचलता है।

जब topआप थ्रेड्स दिखाते हैं, तो यह TID (कर्नेल PIDs) दिखा रहा है, PIDs (कर्नेल TGIDs) नहीं, और यही कारण है कि प्रत्येक थ्रेड का एक अलग है।

एनपीटीएल के आगमन के साथ, अधिकांश सिस्टम कॉल जो पीआईडी ​​तर्क लेते हैं या कॉलिंग प्रक्रिया पर कार्य करते हैं, उन्हें पीआईडी ​​को टीजीआईडी ​​के रूप में माना जाता है और पूरे "थ्रेड समूह" (पॉसिक्स प्रक्रिया) पर कार्य करता है।


8

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

जब आप लिनक्स एपीआई ( क्लोन () , फोर्क () और pthread_create () ) के बजाय सीधे उपयोग करते हैं , तो आपके पास यह परिभाषित करने में अधिक लचीलापन है कि संसाधनों को साझा करने या न साझा करने के लिए, और आप ऐसे कार्य बना सकते हैं जो न तो पूरी तरह से हैं प्रक्रिया और न ही पूरी तरह से एक धागा। यदि आप इन निम्न-स्तरीय कॉल का सीधे उपयोग करते हैं, तो एक नए TGID के साथ एक कार्य बनाना संभव है (इस प्रकार अधिकांश उपयोगकर्तालैंड टूल द्वारा एक प्रक्रिया के रूप में माना जाता है) जो वास्तव में अपने सभी संसाधनों को मूल कार्य, या इसके विपरीत, बनाने के लिए साझा करता है साझा TGID के साथ एक कार्य (इस प्रकार अधिकांश उपयोगकर्ता भूमि उपकरण द्वारा एक थ्रेड के रूप में माना जाता है) जो अपने मूल कार्य के साथ कोई संसाधन साझा नहीं करता है।

जबकि लिनक्स 2.4 TGID को लागू करता है, यह ज्यादातर संसाधन लेखांकन के लाभ के लिए है। कई उपयोगकर्ता और उपयोगकर्तास्पेस टूल एक साथ संबंधित कार्यों को समूह में सक्षम करने और उनके संसाधन उपयोग को एक साथ रिपोर्ट करने के लिए उपयोगी पाते हैं।

लिनक्स में कार्यों का कार्यान्वयन उपयोगकर्ताओं के उपकरणों द्वारा प्रस्तुत प्रक्रियाओं और थ्रेड्स विश्वदृष्टि की तुलना में बहुत अधिक तरल है।


कागज @FooF से जुड़ा हुआ जहां गिरी अलग संस्थाओं के रूप में प्रक्रियाओं और धागे (जैसे संकेत से निपटने और कार्यकारी ()) पर विचार करने के लिए किया अंकों की संख्या का वर्णन करता है, तो यह पढ़ने के बाद, मैं वास्तव में नहीं कह सकते हैं कि यह है कि "ऐसी कोई लिनक्स कर्नेल में प्रक्रियाएं या धागे के रूप में। "
इलकाचू

5

लिनस टॉर्वाल्ड्स ने 1996 में एक कर्नेल मेलिंग सूची पोस्ट में कहा था कि "थ्रेड्स और प्रोसेस दोनों को 'निष्पादन के संदर्भ' के रूप में माना जाता है, जो कि" उस CoE की सभी अवस्थाओं का सिर्फ एक समूह है .... जिसमें CPU जैसी चीजें शामिल हैं। राज्य, MMU राज्य, अनुमतियां, और विभिन्न संचार राज्य (खुली फाइलें, सिग्नल हैंडलर, आदि) "।

// simple program to create threads that simply sleep
// compile in debian jessie with apt-get install build-essential
// and then g++ -O4 -Wall -std=c++0x -pthread threads2.cpp -o threads2
#include <string>
#include <iostream>
#include <thread>
#include <chrono>

// how many seconds will the threads sleep for?
#define SLEEPTIME 100
// how many threads should I start?
#define NUM_THREADS 25

using namespace std;

// The function we want to execute on the new thread.
void threadSleeper(int threadid){
    // output what number thread we've created
    cout << "task: " << threadid << "\n";
    // take a nap and sleep for a while
    std::this_thread::sleep_for(std::chrono::seconds(SLEEPTIME));
}

void main(){
    // create an array of thread handles
    thread threadArr[NUM_THREADS];
    for(int i=0;i<NUM_THREADS;i++){
        // spawn the threads
        threadArr[i]=thread(threadSleeper, i);
    }
    for(int i=0;i<NUM_THREADS;i++){
        // wait for the threads to finish
        threadArr[i].join();
    }
    // program done
    cout << "Done\n";
    return;
}

जैसा कि आप देख सकते हैं कि यह कार्यक्रम एक साथ 25 थ्रेड्स फैलाएगा, जिनमें से प्रत्येक 100 सेकंड के लिए सोएगा और फिर से मुख्य कार्यक्रम में शामिल होगा। सभी 25 थ्रेड्स प्रोग्राम को रिजेक्ट करने के बाद, प्रोग्राम किया जाता है और बाहर निकल जाएगा।

उपयोग करके topआप "थ्रेड्स 2" प्रोग्राम के 25 उदाहरण देख पाएंगे। लेकिन अपहरण उबाऊ। के उत्पादन ps auwxभी कम दिलचस्प है ... लेकिन ps -eLfथोड़े रोमांचक हो जाता है।

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
debian     689   687   689  0    1 14:52 ?        00:00:00 sshd: debian@pts/0  
debian     690   689   690  0    1 14:52 pts/0    00:00:00 -bash
debian    6217   690  6217  0    1 15:04 pts/0    00:00:00 screen
debian    6218  6217  6218  0    1 15:04 ?        00:00:00 SCREEN
debian    6219  6218  6219  0    1 15:04 pts/1    00:00:00 /bin/bash
debian    6226  6218  6226  0    1 15:04 pts/2    00:00:00 /bin/bash
debian    6232  6219  6232  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6233  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6234  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6235  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6236  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6237  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6238  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6239  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6240  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6241  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6242  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6243  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6244  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6245  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6246  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6247  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6248  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6249  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6250  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6251  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6252  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6253  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6254  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6255  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6256  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6257  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6260  6226  6260  0    1 15:04 pts/2    00:00:00 ps -eLf

आप यहां सभी 26 CoE देख सकते हैं जो thread2प्रोग्राम ने बनाया है। वे सभी एक ही प्रक्रिया आईडी (पीआईडी) और मूल प्रक्रिया आईडी (पीपीआईडी) साझा करते हैं, लेकिन प्रत्येक में एक अलग एलडब्ल्यूपी आईडी (हल्के वजन की प्रक्रिया) है, और एलडब्ल्यूपी (एनएलडब्ल्यूपी) की संख्या इंगित करती है कि 26 CoE हैं - मुख्य कार्यक्रम और 25 धागे इसके द्वारा पैदा हुए।


सही है, एक धागा सिर्फ एक हल्की प्रक्रिया है (LWP)
fpmurphy

3

जब लिनक्स प्रक्रियाओं की बात आती है और थ्रेड्स एक ही तरह के होते हैं । कहने के लिए है जो वे एक ही सिस्टम कॉल के साथ बनाया जाता: clone

यदि आप इसके बारे में सोचते हैं, तो धागे और प्रक्रियाओं के बीच का अंतर है जिसमें कर्नेल ऑब्जेक्ट को बच्चे और माता-पिता द्वारा साझा किया जाएगा। प्रक्रियाओं के लिए, यह बहुत अधिक नहीं है: खुली फाइल के विवरणकर्ता, मेमोरी सेगमेंट जो कि नहीं लिखे गए हैं, शायद कुछ अन्य जो मैं अपने सिर के ऊपर से नहीं सोच सकता हूं। धागे के लिए, बहुत अधिक वस्तुओं को साझा किया जाता है, लेकिन सभी नहीं।

लिनक्स में थ्रेड्स और ऑब्जेक्ट्स को जो बनाता है, वह unshareसिस्टम कॉल है। साझा किए जाने के बाद शुरू होने वाले कर्नेल ऑब्जेक्ट थ्रेड निर्माण के बाद अनसेंड हो सकते हैं। इसलिए, उदाहरण के लिए, आपके पास एक ही प्रक्रिया के दो थ्रेड्स हो सकते हैं, जिनमें अलग-अलग फ़ाइल डिस्क्रिप्टर स्पेस होता है (थ्रेड्स बनने के बाद फाइल डिस्क्रिप्टर के शेयरिंग को फिर से चालू करके)। आप इसे थ्रेड बनाकर, unshareदोनों थ्रेड्स में कॉल करके और फिर सभी फाइलों को बंद करके और दोनों थ्रेड्स में नई फाइल्स, पाइप्स या ऑब्जेक्ट्स को खोलकर खुद को टेस्ट कर सकते हैं । फिर अंदर देखें /proc/your_proc_fd/task/*/fdऔर आप देखेंगे कि प्रत्येक task(जिसे आपने एक धागे के रूप में बनाया है) की अलग-अलग fd होगी।

वास्तव में, नए थ्रेड्स और नई प्रक्रियाओं का निर्माण दोनों लाइब्रेरी रूटीन हैं, जो cloneनीचे की ओर कॉल करते हैं और निर्दिष्ट करते हैं कि कौन-सी कर्नेल नई-बनाई गई प्रक्रिया-थ्रेड-चीज़मजिग (यानी task) कॉलिंग प्रक्रिया / थ्रेड के साथ साझा करेगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.