2.6 कर्नेल लिनक्स पर कांटा बनाम क्लोन


37

कांटा और क्लोन के बारे में मुझे कुछ भ्रम है। मैंने देखा है कि:

  • कांटा प्रक्रियाओं के लिए है और क्लोन धागे के लिए है

  • कांटा सिर्फ क्लोन कहता है, क्लोन का उपयोग सभी प्रक्रियाओं और थ्रेड्स के लिए किया जाता है

क्या इनमें से कोई भी सटीक है? 2.6 लिनक्स कर्नेल के साथ इन 2 syscalls के बीच क्या अंतर है?

जवाबों:


52

fork()मूल UNIX सिस्टम कॉल था। इसका उपयोग केवल नई प्रक्रियाएँ बनाने के लिए किया जा सकता है, न कि धागे बनाने में। इसके अलावा, यह पोर्टेबल है।

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

चूंकि clone()सुपरसेट सिस्टम कॉल है, ग्लिब में fork()सिस्टम कॉल रैपर का कार्यान्वयन वास्तव में कॉल करता है clone(), लेकिन यह एक कार्यान्वयन विवरण है जिसके बारे में प्रोग्रामर को जानने की आवश्यकता नहीं है। fork()लिनक्स की कर्नेल में वास्तविक वास्तविक प्रणाली कॉल अभी भी मौजूद है, भले ही यह निरर्थक बन गया हो, क्योंकि प्रोग्राम जो बहुत पुराने संस्करणों का उपयोग करते हैं, या glibc के अलावा एक अन्य libc का उपयोग कर सकते हैं।

clone()pthread_create()थ्रेड बनाने के लिए POSIX फ़ंक्शन को कार्यान्वित करने के लिए भी उपयोग किया जाता है ।

पोर्टेबल कार्यक्रमों को कॉल करना चाहिए fork()और pthread_create(), नहीं clone()


2
posix_spawn एक और प्रासंगिक कार्य है - कुछ तरीकों से कांटा की तुलना में अधिक और कम पोर्टेबल दोनों।
रैंडम 832

10

ऐसा प्रतीत होता है कि clone()लिनक्स 2.6 में दो चीजें घूम रही हैं

एक सिस्टम कॉल है:

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

ऐसा करने से वर्णित "क्लोन ()" है man 2 clone

यदि आप उस आदमी पृष्ठ को पर्याप्त रूप से पढ़ते हैं, तो आप इसे देखेंगे:

It is actually a library function layered on top of the
underlying clone() system call.

जाहिर है, आप "लाइब्रेरी फ़ंक्शन" का उपयोग करके थ्रेडिंग को लागू करने वाले हैं, जो कि भ्रमवश पहचाने जाने वाले सिस्टम कॉल पर आधारित है।

मैंने एक छोटा कार्यक्रम लिखा:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
    pid_t cpid;
    switch (cpid = fork()) {
    case 0:   // Child process
        break;
    case -1:  // Error
        break;
    default:  // parent process
        break;
    }
    return 0;
}

इसके साथ संकलित: c99 -Wall -Wextraऔर यह strace -fदेखने के लिए भाग गया कि सिस्टम कॉलिंग वास्तव में क्या करती है। मुझे यह straceएक लिनक्स 2.6.18 मशीन (x86_64 CPU) पर मिला:

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

straceआउटपुट में कोई "कांटा" कॉल दिखाई नहीं देता है । आउटपुट में दिखाई जाने वाली clone()कॉल straceमें मैन-पेज-क्लोन से बहुत अलग तर्क होते हैं। child_stack=0जैसा कि पहले तर्क से अलग है int (*fn)(void *)

ऐसा प्रतीत होता है कि fork(2)सिस्टम कॉल को वास्तविक रूप में लागू किया जाता है clone(), ठीक उसी तरह जैसे "लाइब्रेरी फंक्शन" clone()को लागू किया जाता है। वास्तविक clone() मानव पेज क्लोन से तर्क का एक अलग सेट है।

सरल रूप से, आपके दोनों स्पष्ट रूप से विरोधाभासी बयान fork()और clone()सही हैं। शामिल "क्लोन" अलग है, यद्यपि।


9
"यह वास्तव में अंतर्निहित क्लोन () सिस्टम कॉल के शीर्ष पर एक लाइब्रेरी फ़ंक्शन है।" - सामान्य तौर पर, यह हर सिस्टम कॉल पर लागू होता है। प्रोग्रामर वास्तव में हमेशा lib में कार्यों को कॉल करते हैं जिन्हें सिस्टम कॉल के नाम पर रखा गया है। ऐसा इसलिए है क्योंकि सी से सीधे वास्तविक वास्तविक कॉल करने के लिए प्लेटफ़ॉर्म-विशिष्ट जादू की आवश्यकता होती है (आमतौर पर किसी प्रकार के सीपीयू जाल को मजबूर करके, आर्किटेक्चर एबीआई पर निर्भर करता है) और मशीन कोड को सबसे अच्छा छोड़ दिया जाता है जो कि एफबीआई को सौंप दिया जाता है।
सेलाडा

1
@ केलदा - हाँ, सहमत। यह सिर्फ इतना है कि man 2 cloneयह वाक्यांश उस तरह से है, जो मुझे लगा कि इस मुद्दे को भ्रमित कर रहा है, और प्रश्नकर्ता को एक अच्छा उत्तर प्राप्त करने से रोक रहा है।
ब्रूस एडिगर

2
मेरा मानना है कि मैनपेज साधन संकेत मिलता है कि तर्क सूची का cloneतर्क सूची अंतर्निहित प्रणाली कॉल द्वारा स्वीकार कर लिया से पुस्तकालय समारोह अलग है काफी हद तक। विशेष रूप से, सिस्टम कॉल हमेशा एक ही स्टैक पर दो बार लौटता है, जिस तरह से पारंपरिक forkकरता है; चाइल्ड स्टैक से संबंधित सभी तर्कों को यूजर स्पेस में सख्ती से हैंडल किया जाता है। उदाहरण के लिए देखें sourceware.org/git/?p=glibc.git/a=blob;f=sysdeps/unix/sysv/…
zwol

1
मैं आपके उत्तर को सर्वश्रेष्ठ उत्तर देना चाहता था क्योंकि यह चट्टान है, लेकिन मैं झुंड द्वारा बह गया था और पहले उत्तर के साथ गया था। वह प्रतिक्रिया समय के लिए अंक प्राप्त करता है। आपके व्याख्या के लिये धन्यवाद।
ग्रीग लेवेंटल

6

fork()सिस्टम कॉल में झंडे का एक विशेष सेट है clone()clone()सामान्य रूप से या तो एक "प्रक्रिया" या एक "थ्रेड" या यहां तक ​​कि अजीब चीजें बनाने के लिए पर्याप्त है जो प्रक्रियाओं और थ्रेड्स के बीच कहीं हैं (उदाहरण के लिए, अलग-अलग "प्रक्रियाएं" जो एक ही फाइल डिस्क्रिप्टर तालिका साझा करती हैं)।

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

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