২.6 কার্নেল লিনাক্সে কাঁটা বনাম ক্লোন


37

কাঁটাচামচ এবং ক্লোন সম্পর্কে আমার কিছু বিভ্রান্তি আছে। আমি এটি দেখেছি:

  • কাঁটাচামচ প্রক্রিয়াগুলির জন্য এবং ক্লোন থ্রেডগুলির জন্য

  • কাঁটাচামচ কেবল ক্লোনকে কল করে, ক্লোনটি সমস্ত প্রক্রিয়া এবং থ্রেডের জন্য ব্যবহৃত হয়

এই দুটি হয় সঠিক? ২.6 লিনাক্স কার্নেলের সাথে এই 2 টি স্কাইকালের মধ্যে পার্থক্য কী?

উত্তর:


52

fork()আসল ইউনিক্স সিস্টেম কল ছিল। এটি কেবল নতুন প্রসেস তৈরি করতে ব্যবহৃত হবে, থ্রেড নয় not এছাড়াও, এটি বহনযোগ্য।

লিনাক্সে, clone()একটি নতুন, বহুমুখী সিস্টেম কল যা ব্যবহারের একটি নতুন থ্রেড তৈরি করতে ব্যবহার করা যেতে পারে। পাস করা বিকল্পগুলির উপর নির্ভর করে, এক্সিকিউশনের নতুন থ্রেডটি ইউনিক্স প্রক্রিয়াটির শব্দার্থক, একটি পসিক্স থ্রেড, এর মধ্যে কিছু বা সম্পূর্ণ আলাদা (কোনও ভিন্ন ধারকের মতো) মেনে চলতে পারে। আপনি মেমরি, ফাইল বর্ণনাকারী, বিভিন্ন নেমস্পেস, সিগন্যাল হ্যান্ডলার ইত্যাদি ভাগ করে নেওয়া বা অনুলিপি করা হুকুম করে সমস্ত ধরণের বিকল্প নির্দিষ্ট করতে পারেন।

যেহেতু clone()সুপারসেট সিস্টেম কল তাই গলিবিতে সিস্টেম কল fork()র‌্যাপার বাস্তবায়ন কল করে clone(), তবে এটি এমন একটি বাস্তবায়ন বিশদ যা সম্পর্কে প্রোগ্রামারদের জানার প্রয়োজন নেই। fork()রিয়েলড্যান্ট হয়ে উঠলেও লিনাক্স কার্নেলে আসল রিয়েল সিস্টেম কলটি এখনও বিদ্যমান, কারণ যে প্রোগ্রামগুলিতে খুব বেশি পুরানো সংস্করণ libc বা glibc এর পাশাপাশি অন্য একটি libc ব্যবহার করে, এটি ব্যবহার করতে পারে।

clone()pthread_create()থ্রেড তৈরির জন্য পসিক্স ফাংশন বাস্তবায়নের জন্যও ব্যবহৃত হয় ।

পোর্টেবল প্রোগ্রামগুলির কল করা উচিত fork()এবং pthread_create()না clone()


2
পোস্টিক্স_স্পন আরেকটি প্রাসঙ্গিক ফাংশন - কিছু উপায়ে কাঁটাচামচের চেয়ে কম বেশি উভয়ই পোর্টেবল।
র্যান্ডম 832

10

দেখা যাচ্ছে clone()লিনাক্স ২.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 সিপিইউ) পেয়েছি :

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
"এটি আসলে অন্তর্নিহিত ক্লোন () সিস্টেম কলের উপরে স্তরযুক্ত একটি লাইব্রেরি ফাংশন" " - সাধারণভাবে, এটি প্রতিটি সিস্টেম কলের ক্ষেত্রে প্রযোজ্য। প্রোগ্রামাররা প্রকৃতপক্ষে libc এ কার্যত কল করে যা সিস্টেম কল অনুসারে নামকরণ করা হয়। এটি কারণ সি থেকে সরাসরি একটি আসল সিস্টেম কল করার জন্য প্ল্যাটফর্ম-নির্দিষ্ট যাদু প্রয়োজন (সাধারণত কোনও ধরণের সিপিইউ ফাঁদ চাপিয়ে, আর্কিটেকচার এবিআইয়ের উপর নির্ভর করে) এবং মেশিন কোডটি বাম বামকে libc তে প্রেরণ করা হয়।
সেলেদা

1
@ কেলাডা - হ্যাঁ, একমত এটা ঠিক যে man 2 cloneএটা বাক্যাংশ ঠিক যে ভাবে, যা আমি চিন্তা ইস্যু বিভ্রান্তিকর ছিল, এবং একটি ভাল উত্তর পাওয়া থেকে প্রশ্নকারী প্রতিরোধ।
ব্রুস এডিগার

2
আমি বিশ্বাস করি র manpage উপায়ে নির্দেশ করে আর্গুমেন্ট তালিকার এর cloneযুক্তি তালিকা অন্তর্নিহিত সিস্টেম কল দ্বারা গৃহীত লাইব্রেরি থেকে ফাংশন পৃথক যথেষ্ট। বিশেষত, সিস্টেম কল সর্বদা একই স্ট্যাকের উপর দ্বিগুণ ফিরে আসে, traditionalতিহ্যগতভাবে forkযেভাবে; শিশু স্ট্যাক সম্পর্কিত সমস্ত যুক্তি ব্যবহারকারীর স্থানে কঠোরভাবে পরিচালনা করা হয়। উদাহরণস্বরূপ দেখুন sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/...
zwol

1
আমি আপনার উত্তরটি সর্বোত্তম উত্তর দিতে চেয়েছিলাম কারণ এটি হুড়োহুড় করে, তবে আমি পশুপাল দ্বারা ডুবে গিয়েছিলাম এবং প্রথম উত্তরটি দিয়েছিলাম। তিনি প্রতিক্রিয়া সময় পয়েন্ট পায়। তোমার ব্যাখ্যার জন্য ধন্যবাদ.
গ্রেগ লেভেনথাল

6

fork()সিস্টেম কলটিতে কেবল পতাকাগুলির একটি নির্দিষ্ট সেট clone()clone()প্রক্রিয়া এবং থ্রেডের মধ্যে কোথাও যে কোনও "প্রক্রিয়া" বা "থ্রেড" বা এমনকী অদ্ভুত জিনিস তৈরি করতে যথেষ্ট সাধারণ (উদাহরণস্বরূপ, একই ফাইলের বিবরণী সারণীতে ভাগ করা বিভিন্ন "প্রক্রিয়া")।

মূলত, কার্নেলের একটি এক্সিকিউশন প্রসঙ্গে জড়িত প্রতিটি "প্রকারের" তথ্যের জন্য clone()আপনাকে সেই তথ্যকে আলাদা করে রাখার বা এটি অনুলিপি করার পছন্দ দেয়। থ্রেডগুলি এলিয়াসিংয়ের সাথে মিলে যায়, প্রক্রিয়াগুলি অনুলিপিটির সাথে মিলে যায়। এতে পতাকাগুলির মধ্যবর্তী সংমিশ্রণগুলি নির্দিষ্ট করে clone()আপনি এমন অদ্ভুত জিনিস তৈরি করতে পারেন যা থ্রেড বা প্রক্রিয়া নয়। আপনার সাধারণত এটি করা উচিত নয় এবং আমি কল্পনা করেছিলাম যে লিনাক্স কার্নেলের বিকাশের সময় কিছুটা সাধারণ ব্যবস্থার অনুমতি দেওয়া উচিত কিনা তা নিয়ে কিছু বিতর্ক হয়েছিল clone()

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.