fork
এবং মধ্যে পার্থক্য কি exec
?
fork
মূলত ক্লোনিং হয়: হে
fork
এবং মধ্যে পার্থক্য কি exec
?
fork
মূলত ক্লোনিং হয়: হে
উত্তর:
ইউএনআইএক্সের চেতনা ব্যবহার fork
এবং exec
উদাহরণ দিয়ে দেয় যে এটি নতুন প্রক্রিয়া শুরু করার খুব সহজ উপায় সরবরাহ করে।
fork
কল মূলত বর্তমান প্রক্রিয়ার একটি ডুপ্লিকেট অভিন্ন তোলে প্রায় প্রতি উপায়। সবকিছু অনুলিপি করা হয় না (উদাহরণস্বরূপ, কিছু বাস্তবায়নে সংস্থান সীমা) তবে ধারণাটি যতটা সম্ভব একটি অনুলিপি তৈরি করা।
নতুন প্রক্রিয়া (শিশু) একটি পৃথক প্রক্রিয়া আইডি (পিআইডি) পায় এবং পুরানো প্রক্রিয়াটির পিআইডি (পিতামাতাকে) তার প্যারেন্ট পিআইডি (পিপিআইডি) হিসাবে রাখে। যেহেতু দুটি প্রক্রিয়া এখন একই কোড চলছে, তারা জানাতে পারে যে কোনটি তার রিটার্ন কোড দ্বারা fork
- সন্তানের 0 হয়, পিতামাতারা সন্তানের পিআইডি পান। এটি অবশ্যই, fork
কল ধরে কাজ করে ধরে নিচ্ছে - তা না থাকলে কোনও শিশু তৈরি হয় না এবং পিতামাতার একটি ত্রুটি কোড পায়।
exec
কল একটি উপায় মূলত একটি নতুন প্রোগ্রাম সঙ্গে সমগ্র বর্তমান প্রক্রিয়া প্রতিস্থাপন হয়। এটি প্রোগ্রামটিকে বর্তমান প্রক্রিয়া জায়গাতে লোড করে এবং এন্ট্রি পয়েন্ট থেকে চালায়।
সুতরাং, fork
এবং exec
প্রায়শই ব্যবহার করা হয় একটি বর্তমান প্রক্রিয়া শিশু হিসাবে একটি নতুন প্রোগ্রাম চলমান পেতে ক্রমানুসারে। শেলগুলি সাধারণত যখনই আপনি এই জাতীয় প্রোগ্রাম চালানোর চেষ্টা করেন find
- শেল কাঁটাচামচ, তারপরে বাচ্চা find
প্রোগ্রামটি মেমোরিতে লোড করে , সমস্ত কমান্ড লাইন আর্গুমেন্ট, মান I / O ইত্যাদি সেটআপ করে।
তবে এগুলি একসাথে ব্যবহার করার দরকার নেই। আইং fork
ছাড়াই কোনও প্রোগ্রামের পক্ষে এটি পুরোপুরি গ্রহণযোগ্য হয় exec
যদি উদাহরণস্বরূপ, প্রোগ্রামটিতে পিতামাতার এবং সন্তানের কোড উভয়ই থাকে (আপনি যা করেন তার ক্ষেত্রে আপনার যত্নবান হওয়া দরকার, প্রতিটি প্রয়োগের ক্ষেত্রে বিধিনিষেধ থাকতে পারে)। এটি ডেমনগুলির জন্য যথেষ্ট পরিমাণে ব্যবহৃত হয়েছিল (এবং এখনও রয়েছে) যা কেবলমাত্র কোনও টিসিপি পোর্টে শোনেন এবং fork
একটি নির্দিষ্ট অনুরোধটি প্রক্রিয়া করার জন্য তাদের একটি অনুলিপি যখন পিতামাতা শোনায় ফিরে যায়।
একইভাবে, প্রোগ্রাম জানি যে, তারা সমাপ্ত করছি এবং মাত্র অন্য প্রোগ্রাম প্রয়োজন হবে না চালাতে চান fork
, exec
এবং তারপর wait
সন্তানের জন্য। তারা কেবল তাদের প্রক্রিয়া স্পেসে শিশুটিকে সরাসরি লোড করতে পারে।
কিছু ইউনিক্স বাস্তবায়নের একটি অপ্টিমাইজড রয়েছে fork
যা তারা অনুলিপি-অন-লিখনকে বলে uses fork
প্রোগ্রামটি সেই জায়গাতে কিছু পরিবর্তন করার চেষ্টা না করা পর্যন্ত প্রক্রিয়া স্পেসের অনুলিপিটি বিলম্ব করার একটি কৌশল । এটি কেবলমাত্র সেইসব প্রোগ্রামগুলির জন্যই দরকারী এবং এটির জন্য fork
নয় exec
যে তাদের একটি সম্পূর্ণ প্রক্রিয়া স্থান অনুলিপি করতে হবে না।
যদি exec
হয় নিম্নলিখিত নামক fork
(এবং এই কি বেশিরভাগই ঘটে থাকে), যে প্রক্রিয়া স্থান করার জন্য একটি লেখার কারণ এবং এটি তারপর সন্তান প্রক্রিয়ার জন্য অনুলিপি করা হয়েছে।
নোট একটি পুরো পরিবারের নেই exec
কল ( execl
, execle
, execve
ইত্যাদি) কিন্তু exec
প্রেক্ষাপটে এখানে তাদের কোন মানে।
নিম্নলিখিত চিত্রটি সেই সাধারণ fork/exec
ক্রিয়াকে চিত্রিত করে যেখানে bash
শেলটি ls
কমান্ডের সাহায্যে ডিরেক্টরিটি তালিকাবদ্ধ করতে ব্যবহৃত হয় :
+--------+
| pid=7 |
| ppid=4 |
| bash |
+--------+
|
| calls fork
V
+--------+ +--------+
| pid=7 | forks | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash | | bash |
+--------+ +--------+
| |
| waits for pid 22 | calls exec to run ls
| V
| +--------+
| | pid=22 |
| | ppid=7 |
| | ls |
V +--------+
+--------+ |
| pid=7 | | exits
| ppid=4 | <---------------+
| bash |
+--------+
|
| continues
V
fork()
বর্তমান প্রক্রিয়াটিকে দুটি প্রক্রিয়াতে বিভক্ত করে। বা অন্য কথায়, আপনার দুর্দান্ত রৈখিক সহজেই প্রোগ্রামটি ভাবা সহজ হ'ল হঠাত দুটি পৃথক প্রোগ্রামে পরিণত হয় কোডের এক টুকরো:
int pid = fork();
if (pid == 0)
{
printf("I'm the child");
}
else
{
printf("I'm the parent, my child is %i", pid);
// here we can kill the child, but that's not very parently of us
}
এটি আপনার মনকে ধাক্কা দিতে পারে। এখন আপনার কাছে কোডের একটি টুকরা রয়েছে যা দুটি প্রসেস দ্বারা কার্যকর হ'ল বেশ অভিন্ন অবস্থা। শিশু প্রক্রিয়াটি কেবলমাত্র প্রক্রিয়াটির সমস্ত কোড এবং মেমরির উত্তরাধিকার সূত্রে প্রাপ্ত, যা fork()
কলটি বন্ধ রেখেছিল সেখান থেকে শুরু করে । পার্থক্য শুধুমাত্রfork()
আপনি পিতামাতা বা সন্তানের কিনা তা আপনাকে জানানোর জন্য রিটার্ন কোড। আপনি যদি পিতামাতা হন তবে ফেরতের মান হ'ল সন্তানের আইডি।
exec
উপলব্ধি করা কিছুটা সহজ, আপনি কেবল exec
এক্সিকিউটেবল টার্গেটটি ব্যবহার করে কোনও প্রক্রিয়া চালিত করতে বলুন এবং আপনার দুটি কোড একই কোড চালাচ্ছেন না বা একই রাজ্যের উত্তরাধিকার সূত্রে পাবেন না। @ স্টিভ হকিন্সের মত , বর্তমান প্রক্রিয়ায় লক্ষ্য নির্বাহের জন্য কার্যকর করার exec
পরে আপনার ব্যবহার করা যেতে পারে fork
।
pid < 0
এবং fork()
কল ব্যর্থ হয়েছিল
আমার কাছে মনে হয় মার্ক মার্কচাইন্ডের "অ্যাডভান্সড ইউনিক্স প্রোগ্রামিং" থেকে কিছু ধারণা fork()
/ এর বিভিন্ন ভূমিকা বোঝার exec()
জন্য বিশেষত উইন্ডোজ CreateProcess()
মডেলটিতে ব্যবহৃত কারও জন্য সহায়ক ছিল :
একটি প্রোগ্রাম হ'ল নির্দেশাবলী এবং ডেটা সংগ্রহ যা ডিস্কে নিয়মিত ফাইলে রাখা হয়। (১.১.২ প্রোগ্রাম, প্রক্রিয়া এবং থ্রেড থেকে)
।
প্রোগ্রাম চালানোর জন্য, কার্নেলকে প্রথমে একটি নতুন প্রক্রিয়া তৈরি করতে বলা হয় , এটি একটি পরিবেশ যেখানে একটি প্রোগ্রাম কার্যকর করে। (এছাড়াও ১.১.২ প্রোগ্রাম, প্রক্রিয়া এবং থ্রেড থেকে)
।
কোনও প্রক্রিয়া এবং প্রোগ্রামের মধ্যে পার্থক্যটি পুরোপুরি না বুঝে এক্সেক বা কাঁটাচামচ কলগুলি বোঝা অসম্ভব। যদি এই শর্তাদি আপনার কাছে নতুন হয় তবে আপনি ফিরে যেতে পারেন এবং বিভাগ 1.1.2 পর্যালোচনা করতে পারেন। আপনি যদি এখনই এগিয়ে যেতে প্রস্তুত হন, আমরা এক বাক্যে পার্থক্যটি সংক্ষিপ্ত করব: একটি প্রক্রিয়া হল একটি মৃত্যুদন্ড কার্যকর করার পরিবেশ যা নির্দেশনা, ব্যবহারকারীর ডেটা এবং সিস্টেম-ডেটা বিভাগগুলি এবং সেই সাথে রানটাইমের সময়ে অর্জিত প্রচুর অন্যান্য সংস্থানগুলি নিয়ে গঠিত যদিও একটি প্রোগ্রাম হ'ল নির্দেশাবলী এবং ডেটা সম্বলিত একটি ফাইল যা কোনও প্রক্রিয়াটির নির্দেশনা এবং ব্যবহারকারী-ডেটা বিভাগগুলিকে আরম্ভ করতে ব্যবহৃত হয়। (5.3
exec
সিস্টেম কল থেকে)
একবার আপনি কোনও প্রোগ্রাম এবং একটি প্রক্রিয়ার মধ্যে পার্থক্য বুঝতে পারলে , আচরণ fork()
এবং exec()
ক্রিয়াকলাপটি এইভাবে সংক্ষেপিত করা যেতে পারে:
fork()
বর্তমান প্রক্রিয়াটির একটি সদৃশ তৈরি করেexec()
বর্তমান প্রক্রিয়াতে প্রোগ্রামটিকে অন্য একটি প্রোগ্রামের সাথে প্রতিস্থাপন করে(এটি মূলত প্যাক্সিডিয়াবলোর আরও বিস্তারিত উত্তরের ' ডামিদের জন্য' সংস্করণটি মূলত )
কাঁটাচামচ কল করার প্রক্রিয়াটির একটি অনুলিপি তৈরি করে। সাধারণত কাঠামো অনুসরণ করে
int cpid = fork( );
if (cpid = = 0)
{
//child code
exit(0);
}
//parent code
wait(cpid);
// end
(শিশু প্রক্রিয়া পাঠ্যের (কোড), ডেটা, স্ট্যাকের জন্য কলিং প্রক্রিয়া সমান) শিশু প্রক্রিয়া যদি ব্লক হয় তবে কোডটি কার্যকর করে।
এক্সইসি বর্তমান প্রক্রিয়াটিকে নতুন প্রক্রিয়ার কোড, ডেটা, স্ট্যাকের সাথে প্রতিস্থাপন করে। সাধারণত কাঠামো অনুসরণ করে
int cpid = fork( );
if (cpid = = 0)
{
//child code
exec(foo);
exit(0);
}
//parent code
wait(cpid);
// end
(এক্সিকিউটিভ কল ইউনিক্স কার্নেল পরে শিশু প্রক্রিয়া পাঠ্য, ডেটা, স্ট্যাক এবং foo প্রক্রিয়া সম্পর্কিত পাঠ্য / ডেটা পূরণ করে) এভাবে শিশু প্রক্রিয়াটি বিভিন্ন কোডের সাথে থাকে (ফু এর কোড parent পিতামাতার মতো নয়)}
তারা নতুন শিশু প্রক্রিয়া তৈরি করতে একসাথে ব্যবহার করছে। প্রথমত, কলিং fork
বর্তমান প্রক্রিয়াটির একটি অনুলিপি তৈরি করে (শিশু প্রক্রিয়া)। তারপরে, exec
নতুন প্রক্রিয়া সহ পিতামাতার প্রক্রিয়াটির অনুলিপি "প্রতিস্থাপন" করার জন্য শিশু প্রক্রিয়া থেকেই ডাকা হয়।
প্রক্রিয়াটি এরকম কিছু হয়:
child = fork(); //Fork returns a PID for the parent process, or 0 for the child, or -1 for Fail
if (child < 0) {
std::cout << "Failed to fork GUI process...Exiting" << std::endl;
exit (-1);
} else if (child == 0) { // This is the Child Process
// Call one of the "exec" functions to create the child process
execvp (argv[0], const_cast<char**>(argv));
} else { // This is the Parent Process
//Continue executing parent process
}
কাঁটাচামচ () বর্তমান সন্তানের প্রক্রিয়াটির একটি অনুলিপি তৈরি করে, কাঁটাচামচ () কল করার ঠিক পরে থেকেই নতুন শিশুটিকে কার্যকর করা হয়। কাঁটাচামচ () এর পরে, তারা কাঁটা ফাংশনের () ফাংশনের রিটার্ন মান ব্যতীত অভিন্ন। (আরও তথ্যের জন্য আরটিএফএম।) দুটি ভাগ প্রক্রিয়াটি তখনই অন্যদিকে বিভক্ত হতে পারে, যার মধ্যে একটির সাথে অন্যের সাথে হস্তক্ষেপ করতে অক্ষম হয়, সম্ভবত কোনও ভাগ করা ফাইল হ্যান্ডলগুলি বাদ দিয়ে।
এক্সিকিউট () বর্তমান প্রক্রিয়াটিকে একটি নতুন দিয়ে প্রতিস্থাপন করে। কাঁটাচামচ () এর সাথে এর কোনও যোগসূত্র নেই, কেবলমাত্র একজন এক্সিকিউটিভ () প্রায়শই কাঁটাচামচ অনুসরণ করে () যখন যা চেয়েছিল তা বর্তমানের প্রতিস্থাপনের পরিবর্তে একটি ভিন্ন শিশু প্রক্রিয়া চালু করতে হবে।
মধ্যে মূল পার্থক্য fork()
এবং exec()
যে,
fork()
সিস্টেম কল বর্তমানে চলমান প্রোগ্রাম এর ক্লোন তৈরি করে। মূল প্রোগ্রামটি কাঁটাচামচ () ফাংশন কলের পরে পরবর্তী লাইনের কোডের সাথে সম্পাদন অব্যাহত রাখে। ক্লোনটি কোডের পরবর্তী লাইনেও কার্যকর করা শুরু করে। নীচের কোডটি দেখুন যা আমি http://timmurphy.org/2014/04/26/ using-fork-in-cc-a-minimum-working- example/ থেকে পেয়েছি
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
int counter = 0;
pid_t pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n", ++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
return 0;
}
এই প্রোগ্রামটি একটি পাল্টা ভেরিয়েবল ঘোষণা করে, শূন্যে সেট করে, fork()
আইএনএন করার আগে । কাঁটাচামচ কল করার পরে, আমাদের দুটি সমান্তরালে চলমান দুটি প্রক্রিয়া রয়েছে, উভয়ই তাদের নিজস্ব সংস্করণের কাউন্টারকে বাড়িয়ে তুলছে। প্রতিটি প্রক্রিয়া সমাপ্তি এবং প্রস্থান করতে চালানো হবে। প্রক্রিয়াগুলি সমান্তরালভাবে চালিত হওয়ার কারণে, আমাদের জানার কোনও উপায় নেই যা প্রথমে শেষ হবে। এই প্রোগ্রামটি চালানো নীচের চিত্রের মতো একই জাতীয় কিছু মুদ্রণ করবে, যদিও ফলাফলগুলি এক রান থেকে পরের দিকে আলাদা হতে পারে।
--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
child process: counter=1
parent process: counter=4
child process: counter=2
parent process: counter=5
child process: counter=3
--end of program--
child process: counter=4
child process: counter=5
--end of program--
exec()
সিস্টেম কলের পরিবার কোডের অন্য টুকরা সঙ্গে একটি প্রক্রিয়া বর্তমানে নির্বাহ কোড প্রতিস্থাপন করে। প্রক্রিয়াটি তার পিআইডি বজায় রাখে তবে এটি একটি নতুন প্রোগ্রামে পরিণত হয়। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি বিবেচনা করুন:
#include <stdio.h>
#include <unistd.h>
main() {
char program[80],*args[3];
int i;
printf("Ready to exec()...\n");
strcpy(program,"date");
args[0]="date";
args[1]="-u";
args[2]=NULL;
i=execvp(program,args);
printf("i=%d ... did it work?\n",i);
}
এই প্রোগ্রামটি execvp()
তারিখ প্রোগ্রামের সাথে তার কোডটি প্রতিস্থাপন করতে ফাংশনটি কল করে । কোডটি যদি exec1.c নামক কোনও ফাইলে সংরক্ষণ করা হয়, তবে এটি সম্পাদন করে নিম্নলিখিত আউটপুট উত্পাদন করে:
Ready to exec()...
Tue Jul 15 20:17:53 UTC 2008
প্রোগ্রামটি লাইনটি আউটপুট করে exec রেডি টু এক্সিকিউট ()। । । The এবং এক্সিকিউপি () ফাংশন কল করার পরে, এর কোডটি তারিখ প্রোগ্রামের সাথে প্রতিস্থাপন করে। লক্ষ করুন যে লাইন -। । । এটি কাজ করে - প্রদর্শিত হয় না, কারণ সেই সময়ে কোডটি প্রতিস্থাপন করা হয়েছে। পরিবর্তে, আমরা ―date -u.‖ নির্বাহের ফলাফল দেখি
এটি চলমান প্রক্রিয়াটির একটি অনুলিপি তৈরি করে। চলমান প্রক্রিয়াটিকে অভিভাবক প্রক্রিয়া এবং নতুন তৈরি প্রক্রিয়াটিকে শিশু প্রক্রিয়া বলা হয় । দুটির পার্থক্যের উপায় হ'ল প্রত্যাবর্তিত মানটি দেখে:
fork()
পিতামাতার মধ্যে শিশু প্রক্রিয়াটির প্রক্রিয়া শনাক্তকারী (পিড) প্রদান করে
fork()
সন্তানের 0 প্রদান করে
exec()
:
এটি একটি প্রক্রিয়ার মধ্যে একটি নতুন প্রক্রিয়া সূচনা করে। এটি বিদ্যমান প্রোগ্রামটি প্রতিস্থাপন করে বর্তমান প্রক্রিয়াতে একটি নতুন প্রোগ্রাম লোড করে।
fork()
+ exec()
:
নতুন প্রোগ্রাম চালু করার সময় প্রথমে fork()
একটি নতুন প্রক্রিয়া তৈরি করা এবং তারপরে exec()
(যেমন মেমরির মধ্যে লোড করা এবং চালানো) প্রোগ্রামটি বাইনারি চালিত হওয়ার কথা।
int main( void )
{
int pid = fork();
if ( pid == 0 )
{
execvp( "find", argv );
}
//Put the parent to sleep for 2 sec,let the child finished executing
wait( 2 );
return 0;
}
ধারণা fork()
এবং exec()
ধারণাটি বোঝার প্রধান উদাহরণটি হ'ল শেল , কমান্ড ইন্টারপ্রেটার প্রোগ্রাম যা ব্যবহারকারীরা সাধারণত সিস্টেমে লগইন করার পরে চালায় The শেলটি কমান্ডের নাম হিসাবে কমান্ড লাইনের প্রথম শব্দটিকে ব্যাখ্যা করে ts
অনেক কমান্ড জন্য, শেল কাটাচামচ ও শিশু প্রক্রিয়া execs নাম কমান্ড পরামিতি হিসেবে কমান্ড লাইন অবশিষ্ট শব্দ চিকিত্সা সঙ্গে যুক্ত কমান্ড।
শেল কমান্ড তিন ধরনের পারেন। প্রথমত, একটি আদেশ একটি এক্সিকিউটেবল ফাইল হতে পারে যা উত্স কোড সংকলন দ্বারা উত্পাদিত অবজেক্ট কোড ধারণ করে (উদাহরণস্বরূপ একটি সি প্রোগ্রাম)। দ্বিতীয়ত, একটি কমান্ড একটি এক্সিকিউটেবল ফাইল হতে পারে যাতে শেল কমান্ড লাইনের ক্রম থাকে। অবশেষে, একটি কমান্ড একটি অভ্যন্তরীণ শেল কমান্ড হতে পারে ((এক্সিকিউটেবল ফাইলের পরিবর্তে-> সিডি , এলএস ইত্যাদি)