क्या आपने कभी मूर के नियम के बारे में सुना है जो अर्धचालक उद्योग को लगभग 60 वर्षों तक नियंत्रित करता है? क्या आप जानते हैं कि मूर का नियम कभी कानून नहीं था, बल्कि एक अवलोकन था? इस कानून से अपरिचित लोगों के लिए, इसे इस तरह व्यक्त किया जाता है।
मूर का नियम कहता है कि सघन एकीकृत परिपथों में ट्रांजिस्टर की संख्या हर दो साल में दोगुनी हो जाती है।
हालांकि नियम इलेक्ट्रॉनिक्स के संदर्भ में लिखा गया है, कंप्यूटर के दृष्टिकोण से, यह इंगित करता है कि कंप्यूटिंग शक्ति हर दो साल में दोगुनी हो जाएगी। एक चिप पर अनिवार्य रूप से कम्प्यूटेशनल शक्ति तेजी से बढ़ती है। क्या यह शानदार नहीं है?
आश्चर्यजनक बात यह है कि जब से यह अवलोकन किया गया है, तब से यह सच साबित हुआ है और अब इसे एक नियम के रूप में माना जाता है।
हालांकि, जैसा कि हम सभी जानते हैं, अच्छी चीजें हमेशा मुफ्त नहीं होती हैं। इस उदाहरण में, अधिक शक्तिशाली गणना अत्यधिक हीटिंग की कीमत पर थी। जब वे 2010 में पहुंचे, तो प्रोसेसर पास्ता पकाने के लिए पर्याप्त तापमान पर पहुंच गए। (इसे स्वयं अनुभव करने के लिए इस यूट्यूब वीडियो को देखें)।
इसके अतिरिक्त, जैसे-जैसे चिप पर ट्रांजिस्टर की संख्या बढ़ती गई, सामग्री की भौतिक सीमा तक पहुंचने लगी। इस बिंदु पर उप-परमाणु बल सक्रिय होने लगे, जिससे मूर के कानून प्रक्षेपवक्र को बनाए रखना चुनौतीपूर्ण हो गया।
ऐसा लगा जैसे अच्छे समय खत्म हो गए थे जहां कंप्यूटर हमेशा तेज होते जा रहे थे। लेकिन इंजीनियरों की अन्य योजनाएँ थीं। उन्होंने सिंगल सुपर पावरफुल कोर के बजाय कई शक्तिशाली कोर का उपयोग करना शुरू कर दिया।
हालाँकि इसने हार्डवेयर की समस्या को हल कर दिया होगा, लेकिन इसने सॉफ्टवेयर इंजीनियरों के लिए एक नई चुनौती पेश की। इंजीनियरों को ऐसे सॉफ़्टवेयर विकसित करने पड़े जो अब कंप्यूटर के पास मौजूद कई कोर का लाभ उठा सकें। नतीजतन, समवर्ती प्रोग्रामिंग, जिसे अक्सर समानांतर प्रोग्रामिंग के रूप में जाना जाता है, का जन्म हुआ। प्रोग्रामिंग के इस क्षेत्र में थ्रेड्स सुर्खियों में हैं। लेकिन धागों के बारे में बात करने से पहले हमें यह समझना चाहिए कि प्रक्रिया क्या है।
एक लिनक्स प्रक्रिया को एक प्रोग्राम के चल रहे उदाहरण के रूप में परिभाषित किया गया है।
इसलिए, प्रोग्राम को निष्पादित करते समय सिस्टम को कई मदों का ट्रैक रखना चाहिए, जिसमें स्टैक मेमोरी, सोर्स कोड और रजिस्टर शामिल हैं, अन्य बातों के अलावा। लिनक्स में, इन सभी चीजों के समुच्चय को एक प्रक्रिया के रूप में संदर्भित किया जाता है। लिनक्स प्रक्रियाओं की नींव पर बनाया गया है।
अपनी मशीन पर चल रही विभिन्न प्रक्रियाओं की जाँच करने के लिए आप निम्न कमांड को चलाने का प्रयास कर सकते हैं। यह सभी प्रक्रियाओं को उनकी प्रक्रिया आईडी के साथ चलाएगा।
$ ps
यहाँ एक नमूना स्नैपशॉट है।
डिफ़ॉल्ट रूप से, ऊपर दिया गया कमांड केवल उन प्रक्रियाओं को दिखाता है जो वर्तमान उपयोगकर्ता से जुड़ी हैं। सभी प्रक्रियाओं को सूचीबद्ध करने के लिए हम निम्नलिखित विकल्पों के साथ कमांड का उपयोग कर सकते हैं।
$ ps -aux
यहाँ एक नमूना स्नैपशॉट है।
इन अतिरिक्त विकल्पों को ps
कमांड में लागू करने से हमें कुछ अतिरिक्त जानकारी भी मिलती है। यहाँ विभिन्न झंडों का क्या अर्थ है -
a
सभी उपयोगकर्ताओं का प्रतिनिधित्व करता हैu
वर्तमान उपयोगकर्ता का प्रतिनिधित्व करते हैंx
टर्मिनल के बाहर निष्पादित प्रक्रिया को प्रदर्शित करता है
हम kill
कमांड का उपयोग करके कुछ प्रक्रियाओं को भी मार सकते हैं। यहां बताया गया है कि इसका उपयोग कैसे किया जाता है -
$ kill PID
यहां PID
वह प्रोसेस आईडी है जिसे हम ps
कमांड से प्राप्त कर सकते हैं। लिनक्स सिस्टम में प्रत्येक प्रक्रिया में एक अद्वितीय PID
होगा जिसका उपयोग इसे पहचानने के लिए किया जाता है। आप प्रक्रिया के PID
को खोजने के लिए pidof
कमांड का भी उपयोग कर सकते हैं।
$ pidof bash
जब आप कोई प्रोग्राम लॉन्च करते हैं या कमांड जारी करते हैं, तो एक प्रक्रिया बनती है। जब आप टर्मिनल से कमांड निष्पादित करते हैं, तो आप एक नई प्रक्रिया शुरू करते हैं। चूंकि इस नई प्रक्रिया को उत्पन्न करने के लिए टर्मिनल का उपयोग किया गया था, हम कहते हैं कि टर्मिनल प्रक्रिया ने नई कमांड प्रक्रिया शुरू की है। दूसरे शब्दों में, नई कमांड प्रक्रिया टर्मिनल प्रक्रिया की संतान है।
लिनक्स पारिस्थितिकी तंत्र में प्रत्येक प्रक्रिया की एक मूल प्रक्रिया होती है जिसने इसे बनाया है। किसी दिए गए PID
के साथ किसी प्रक्रिया की मूल प्रक्रिया की जाँच करने के लिए हम निम्न कमांड का उपयोग कर सकते हैं।
$ ps -o ppid= -p PID
लिनक्स में सभी प्रक्रियाएं, प्रत्यक्ष या अप्रत्यक्ष रूप से, पीआईडी 1 के साथ प्रक्रिया के बच्चे हैं। यह कोई संयोग नहीं है। PID 1 के साथ प्रक्रिया init प्रक्रिया है और बूट के समय सिस्टम द्वारा शुरू की गई सबसे पहली प्रक्रिया है। कोई भी बाद की प्रक्रिया इस प्रक्रिया के बच्चे के रूप में बनाई जाती है।
इस प्रकार हमारे पास प्रक्रियाओं के बीच इन संबंधों से निर्मित एक वृक्ष है। इसे प्रोसेस ट्री कहा जाता है।
Linux में प्रक्रियाएँ अत्यंत उपयोगी हैं, और हम उनके बिना नहीं रह सकते थे। लेकिन उनके लिए एक नुकसान है, या शायद बिल्कुल भी नुकसान नहीं है, लेकिन जिस तरह से वे काम करते हैं। एक प्रक्रिया भारी है। जब भी कोई नई प्रक्रिया शुरू की जाती है तो डेटा, मेमोरी और वेरिएबल्स को स्थानांतरित कर दिया जाता है। समान प्रोग्राम चलाने वाली प्रत्येक प्रक्रिया के पास स्रोत कोड की अपनी प्रति होगी। नतीजतन, बड़ी संख्या में प्रक्रियाओं को जन्म देना एक स्मार्ट विचार नहीं है।
हालाँकि, क्योंकि प्रक्रियाएं एक ही समय में कई अनुरोधों को पूरा करने के लिए एक तंत्र हैं, हम इस अप्रिय सच्चाई से विवश हैं। हम केवल समवर्ती उपयोगकर्ताओं की एक छोटी संख्या की सेवा कर सकते हैं जिनमें बहुत कुछ समान है क्योंकि हम केवल अपने सिस्टम में सीमित संख्या में प्रक्रियाओं को लॉन्च कर सकते हैं। एक वेब सर्वर पर विचार करें जिसे कई समवर्ती उपयोगकर्ताओं की सेवा करनी है। प्रत्येक उपयोगकर्ता के लिए एक नई प्रक्रिया बनाना एक महंगा ऑपरेशन है। नतीजतन, हम प्रक्रिया से कुछ कम खर्चीला चाहते हैं। यहां धागे चलन में आते हैं।
धागे सिर्फ हल्की प्रक्रियाएं हैं। एक थ्रेड अपनी मूल प्रक्रिया और उसके द्वारा बनाए गए किसी भी थ्रेड के साथ मेमोरी साझा करता है। इस साझा स्मृति के कारण, नए धागे पैदा करना कम खर्चीला है। यह तेजी से थ्रेड संचार और संदर्भ स्विचिंग का अतिरिक्त लाभ प्रदान करता है। थ्रेड्स का उपयोग करते हुए, एक प्रक्रिया एक साथ कई कार्य कर सकती है।
प्रक्रियाओं की संख्या की तुलना में, हम बड़ी संख्या में धागे उत्पन्न कर सकते हैं। कई कोर मशीनों पर, इन थ्रेड्स को समानांतर में निष्पादित किया जाता है। जब कई प्रक्रियाओं को उत्पन्न करने या सभी कार्यों को क्रमिक रूप से करने का विरोध किया जाता है, तो यह कार्यक्रम के समग्र प्रदर्शन में सुधार करता है।
आइए अपना पहला धागा शुरू करने का प्रयास करें। यह ध्यान रखना महत्वपूर्ण है कि हम बैश के साथ नए धागे शुरू नहीं कर सकते। बैश कमांड का उपयोग केवल सबप्रोसेस बनाने के लिए किया जा सकता है। तो, हम जो करेंगे वह एक सी कोड लिख रहा है जो दो धागे लॉन्च करता है। फिर, बैश का उपयोग करके, हम इस सी कोड को सबप्रोसेस के रूप में निष्पादित करेंगे। फिर, इस नई प्रक्रिया से दो थ्रेड बनाए जाएंगे।
आइए कुछ कोड पर अपना हाथ रखना शुरू करें। एक नई फाइल बनाएं और उसे नाम दें threads.c
। आगे बढ़ें और इसे अपने किसी भी पसंदीदा IDE में खोलें।
आवश्यक हेडर फ़ाइलों को आयात करने के लिए पहला कदम है।
#include <pthread.h> #include <stdio.h>
हम दो धागे बनाएंगे, प्रत्येक एक ही फ़ंक्शन को निष्पादित करेगा लेकिन विभिन्न मापदंडों के साथ। चलिए उस फंक्शन को लिखते हैं।
void* print_multiple_messages(void* ptr) { char* message = (char*) ptr; for(int i=0; i<1000; ++i) { printf("%s \n", message); } }
जैसा कि आप देख सकते हैं, यह फ़ंक्शन कुछ भी बड़ा नहीं करता है। यह एक संदेश को एक इनपुट पैरामीटर के रूप में लेता है और एक हजार बार प्रिंट करता है।
आइए अब मुख्य कार्य लिखें।
int main() { // Continue writing from here }
प्रक्रियाओं की तरह, थ्रेड्स में भी आईडी होते हैं जिनका उपयोग उन्हें विशिष्ट रूप से पहचानने के लिए किया जाता है। इन आईडी को होल्ड करने के लिए दो वेरिएबल बनाएं।
pthread_t thread1, thread2;
हम प्रत्येक थ्रेड के लिए अलग-अलग संदेशों का उपयोग करेंगे। अलग-अलग संदेशों को रखने के लिए दो स्ट्रिंग्स (कैरेक्टर ऐरे) बनाएं।
char* message1 = "Thread 1"; char* message2 = "Thread 2";
अगला कदम दो धागे बनाना है। हम ऐसा करने के लिए pthread_create
विधि का उपयोग करेंगे।
pthread_create(&thread1, NULL, print_multiple_messages, (void*) message1); pthread_create(&thread2, NULL, print_multiple_messages, (void*) message2);
इससे दो नए सूत्र शुरू होंगे। आइए हम अपनी मुख्य प्रक्रिया को तब तक प्रतीक्षा करने का निर्देश दें जब तक कि दो धागे अपना काम पूरा नहीं कर लेते।
pthread_join(thread1, NULL); pthread_join(thread2, NULL);
और यही है। कोड संकलित करें और इसे निष्पादित करें। आप देखेंगे कि दो धागों के संदेश मिश्रित होंगे। इससे पता चलता है कि उन्हें समानांतर में निष्पादित किया जा रहा है।
बधाई हो आपने अभी-अभी अपना पहला सूत्र बनाया है।
तो, इस लेख में, हमने थ्रेड्स और प्रक्रियाओं के बारे में बात की। ये लिनक्स की कुछ सबसे आकर्षक विशेषताएं हैं, और इनमें महारत हासिल करना महत्वपूर्ण है। यह हार्डवेयर-जागरूक सॉफ़्टवेयर के विकास और हमारे निपटान में संसाधनों के कुशल उपयोग को सक्षम बनाता है।
यहां, हम इस लेख का निष्कर्ष निकालेंगे। हमने आपको जाने के लिए पर्याप्त विवरण में जाने का प्रयास किया, लेकिन ऐसा नहीं है। इसलिए और सीखते रहें। अगर आपको सामग्री अच्छी लगी हो, तो आप टिप्पणी करना और/या इमोशन करना चाहेंगे।
सीखने का आनंद लें!