সাধারণত একটি প্রসেস হলো একটি প্রোগ্রাম এক্সিকিউশন। তবে প্রসেস শুধুমাত্র প্রোগ্রাম কোড ছাড়াও আরও অনেক কিছু বোঝায়, এটিকে অনেক সময় Text Section বলা হয়। এছাড়াও একটি প্রসেসে বর্তমান অ্যকটিভিটি একটি ইন্টিজার ভ্যালু হিসেবে থাকে, একে Program Counter বলে। এছাড়াও একটি প্রসেসে Stack নামক টেম্পরারি জায়গা থাকে, যেখানে বিভিন্ন ফাংশন প্যারামিটার, রিটার্ন ভ্যালু ও লোকাল ভ্যারিয়েবলের মান স্টোর থাকে। প্রসেসে গ্লোবাল ভ্যারিয়েবল স্টোর করে রাখার জন্য Data Section থাকে। এছাড়াও রানটাইমে ডায়নামিকালি অ্যালোকেট করার জন্য heap section থাকতে পারে। একটি প্রসেসের Memory স্ট্রাকচার তাহলে নিম্নরূপঃ
Process State:
Process এক্সিকিউশনের সাথে সাথে এর বিভিন্ন স্টেটের পরিবর্তন হয়ে থাকে। একটি প্রসেস নিচের যে কোনো একটি স্টেটে থাকতে পারেঃ
- New: প্রসেসটি কেবল তৈরী হয়েছে/হচ্ছে।
- Running: প্রসেসটি এক্সিকিউট হচ্ছে।
- Waiting: প্রসেসেটি কোন একটি ইভেন্ট ঘটার জন্য অপেক্ষা করছে (এটা হতে পারে কোনো I/O completion অথবা reception of Signal)
- Ready: প্রসেসটি প্রসেসর দ্বারা এক্সিকিউট হবার জন্য অপেক্ষা করছে।
- Terminated: প্রসেসটি তার এক্সিকিউশন শেষ করেছে।
Process Control Block (PCB)
Operating System এ প্রতিটি প্রসেস Process Control Block (PCB) বা Task Control Block এর মাধ্যমে রিপ্রেজেন্ট করা হয়ে থাকে। প্রসেস কন্ট্রোল ব্লকে (PCB)তে একটি প্রসেস সংক্রান্ত বিভিন্ন তথ্য থাকে। একটি PCB অনেকটা নিম্নরূপঃ
PCB তে প্রসেস সম্পর্কে যে সকল তথ্য থাকতে পারেঃ
- Process State: একটি প্রসেস কোন স্টেটে আছে ( New/Running/Waiting/Read/Terminated) তা এই অংশে থাকবে।
- Program Counter: প্রসেসটি পরবর্তীতে কোন ইন্সট্রাকশন এক্সিকিউট করবে তার address এই কাউন্টারে থাকে।
- CPU Registers: Register এর সংখ্যা ও টাইপ কম্পিউটার আর্কিটেকচার অনুসারে বিভিন্ন প্রকারের হতে পারে। যেমনঃ Accumulators, index registers, stack pointers এবং general-purpose registers।
- CPU Scheduling Information: বিভিন্ন প্রসেসের priority, scheduling queue র পয়েন্টার সহ অন্যান্য Scheduling Parameter এর তথ্য এখানে থাকতে পারে।
- Memory-management Information: এখানে base অথবা limit register, page table বা segment table এ বিভন্ন তথ্য থাকতে পারে।
- Accounting Information: এখানে CPU কতক্ষন ব্যবহার হয়েছে, time limits, job অথবা process numbers এর মত তথ্য থাকতে পারে।
- I/O status Information: এখানে কোন প্রসেসে কোন I/O device ব্যবহার করছে, কোন কোন ফাইল ওপেন আছে এই ধরনের তথ্য থাকবে।
CPU Switch from Process to Process:
Threads
সাধারণত প্রোসেস হলো একটি প্রোগ্রাম যা মূলত single thread এর এক্সিকিউশন। যেমন, যখন আমরা word processing software ব্যবহার করে থাকি তখন আমরা একই সাথে অনেকগুলো থ্রেড/প্রসেস রান করাতে পারি না। আমরা একই সাথে টাইপ করার সাথে সাথে একই থ্রেডে Spell Checker রান করতে পারি না। তবে বর্তমানে অনেক প্রসেসর Multiple-Thread হ্যান্ডেল করতে পারে। সেই সকল ক্ষেত্রে PCB তে প্রতিটি থ্রেডের জন্য তথ্য জমা থাকবে।
Process Scheduling
Multiprogramming এর উদ্দেশ্য হলো সব সময় যেনো প্রসেস রান করে থাকে যেনো CPU Utilization সর্বোচ্চ পরিমান হয়। আবার Time Sharing এর উদ্দেশ্য হলো CPU যেনো বারবার প্রসেস পরিবর্তন করে যেনো ব্যবহারকারি প্রতিটি প্রগ্রামের সাথে খুব দ্রুত কাজ করতে পারে। এই সকল উদ্দেশ্য সফল করার জন্য Process Scheduler রয়েছে। Process Scheduler এর কাজ হলো যে সকল প্রসেস available আছে তাদের মধ্য থেকে এক্সিকিউশন করার জন্য প্রসেস সিলেক্ট করা। Single-processor system এ একই সময়ে দুটি প্রসেস রান করতে পারবে না, তাই একটি প্রসেস শেষ না হওয়া পর্যন্ত অন্য প্রসেসগুলোকে অপেক্ষা করতে হবে। CPU ফাঁকা হলেই অন্য প্রসেসগুলো rescheduled হবে।
Scheduling Queues
Process Schedule এর জন্য মূলত তিন ধরনের Queue রয়ছে। এগুলো হলোঃ
- Job Queue: কোনো প্রসেস সিস্টেমে প্রবেশ করার সাথে সাথেই তা Job Queue তে জমা হয়। মূলত Job Queue তে সিস্টেমের সকল প্রকার প্রসেস থাকে।
- Ready Queue: যখন কোনো প্রসেস মেমোরিত থাকে এবং ready state এ থাকে ও এক্সিকিউট করার জন্য অপেক্ষমান তখন সেই প্রসেস যে লিস্টে থাকে তাকে Ready Queue বলে। এই কিউ সাধারনত লিংকড লিস্ট দিয়ে ইম্প্লিমেন্ট করা হয়। Ready Queue এর হেডারে PCB র প্রথম এবং PCBর শেষ পয়েন্টার থাকে। প্রতিটি PCB তে একটি পয়েন্টার থাকে যা read queue এর পরবর্তী PCB কে পয়েন্ট করবে।
- Device Queue: যে লিস্টে প্রসেসগুলো I/O Device এর জন্য অপেক্ষা করে তাকে Device Queue বলে। যেমন একটি প্রসেসের হার্ড ডিস্ক অ্যাকসেস করার প্রয়োজন হলো। কিন্তু হার্ড ডিস্কটি অন্য একটি প্রসেস দ্বারা ব্যবহৃত হচ্ছে। তখন তো এই প্রসেসকে অপেক্ষা করতে হবে হার্ড ডিস্ক অ্যাকসেস করার জন্য। তখনই সে Device Queue তে অপেক্ষমান থাকবে।
একটি প্রসেস প্রথমে Ready Queue তে থাকে। এটি execution এর জন্য সিলেক্ট না হওয়া পর্যন্ত বা dispatched না হওয়া পর্যন্ত কিউতে অপেক্ষা করে। যখন প্রসেসটি CPU দ্বারা এক্সিকিউশন চলে তখন নিচের যে কোনো একটি ঘটনা ঘটতে পারেঃ
- প্রসেসটি কোনো I/O অপারেশনের জন্য অপক্ষা করতে পারে এবং I/O বা Device Queue তে যেতে পারে।
- প্রসেসটি কোনো নতুন সাবপ্রসেস তৈরী করতে পারে এবং ঐ সাবপ্রসেসটি শেষ না হওয়া পর্যন্ত অপেক্ষমান থাকতে পারে।
- CPU জোড় করে প্রসেসটিকে মুছে ফেলতে পারে। এমনটি interrupt এর কারনে ঘটতে পারে এবং এই সময় সে ready queue তে চলে যেতে পারে।
Schedulers
বিভিন্ন প্রকাল সিডিউলারের (scheduler) মাধ্যমে অপারেটিং সিস্টেম প্রসেস সিলেক্ট করে থাকে। মূলত দু’ধরনের scheduler রয়েছে। (১) short-term scheduler বা CPU scheduler এবং (২) long-term scheduler বা job scheduler.
Short-Term Scheduler: এই সিডিউলারের কাজ হলো রেডি কিউ থেকে প্রসেস সিলেক্ট করা এবং সেই প্রসেসের জন্য CPU অ্যালোকেট করে দেওয়া।
Long-Term Scheduler: এই সিডিউলারের কাজ হলো Ready Queue তে প্রসেস নিয়ে আসা এবং তাদেরকে মেমোরিতে লোড করা।
এই দুটি ছাড়াও Medium-Term Scheduler আছে। এই সিডিউলারের কাজ হলো যে কোনো সময় প্রসেসকে মেমোরি থেকে মুছে ফেলে degree of multiprogramming কমিয়ে দেওয়া এবং পরবর্তীতে প্রয়োজন হলে ঐ প্রসেসকে পুনরায় মেমোরিতে রেস্টোর করা।
কাজরে ভিত্তিতে প্রসেসকে ২ ভাগে ভাগ করা যায়ঃ
(১) I/O Bound Process: এই সকল প্রসেস তার লাইফ টাইমে বেশিরভাগ সময়ই I/O operation পারফর্ম করে থাকে। এরা খুব কমই কম্পিউটেশনের কাজ করে থাকে।
(২) CPU Bound Process: এই সকল প্রোসেস I/O Bound প্রসেসের ঠিক বিপরীত। অর্থাৎ এর I/O Operation এর চেয়ে কম্পিউটেশনের কাজই বেশি করে থাকে।
Operation on Process: Process Creation
বিভিন্ন ভাবে একটি প্রসেস তৈরী করা যেতে পারে, হয় সিস্টেমের create-process ফাংশনের মধ্য দিয়ে অথবা একটি প্রসেস চলাকালীন সময়ে। যে প্রসেস একটি নতুন প্রসেস তৈরী করে তাকে Parent Process বলা হয় এবং নতুন যে প্রসেস তৈরী হয় তাকে ঐ প্যারেন্ট প্রসেসের Children Process বলা হয়। আবার প্রতিটি children process আরও অনেক প্রসেস তৈরী করতে পারে। এভাবে একটি প্রসেস Tree গঠন হতে পারে। সাধারণত প্রতিটি প্রসেসের জন্য একটি করে id দেওয়া থাকে ( pid ), যেটা ইউনিক ইন্টিজার নাম্বার হয়ে থাকে।
যখন একটি প্রসেস নতুন একিট প্রসেস তৈরী করে তখন এক্সিকিউশনের টার্ম অনুসারে দুটি সম্ভাবনা থাকেঃ
১. Parent প্রসেস children প্রসেসের সাথে পাশাপাশি এক্সিকিউট হবে। ২. Parent Process, কিছু বা সব children process এর এক্সিকিউট শেষ না হওয়া পর্যন্ত অপেক্ষা করবে।
স্পেসের টার্ম অনুসারেও দুটি সম্ভাবনা থাকেঃ
১. Child Process টি তার Parent Process এর অনুরূপ (duplicate) হবে [ এক্ষেত্রে parent process এর অনুরূপ program এবং data থাকবে ] ২. Child Process এ সম্পূর্ণ নতুন একটি প্রোগ্রাম লোড হবে।
UNIX অপারেটিং সিস্টেমের ক্ষেত্রে প্রসেস তৈরী করার একটি প্রোগ্রাম নিচে দেওয়া হলোঃ
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid t pid;
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0) { /* child process */
execlp("/bin/ls","ls",NULL);
}
else { /* parent process */
/* parent will wait for the child to complete */
wait(NULL);
printf("Child Complete");
}
return 0;
}
Windows অপারেটিং সিস্টেমের ক্ষেত্রে প্রসেস তৈরী করার প্রোগ্রাম নিচে দেওয়া হলোঃ
#include <stdio.h>
#include <windows.h>
int main(VOID)
{
STARTUPINFO si;
PROCESS INFORMATION pi;
/* allocate memory */
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
/* create child process */
if (!CreateProcess(NULL, /* use command line */
"C:\\WINDOWS\\system32\\mspaint.exe", /* command */
NULL, /* don’t inherit process handle */
NULL, /* don’t inherit thread handle */
FALSE, /* disable handle inheritance */
0, /* no creation flags */
NULL, /* use parent’s environment block */
NULL, /* use parent’s existing directory */
&si,
&pi))
{
fprintf(stderr, "Create Process Failed");
return -1;
}
/* parent will wait for the child to complete */
WaitForSingleObject(pi.hProcess, INFINITE);
printf("Child Complete");
/* close handles */
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
Operation on Process: Process Termination
যখন একটি প্রসেস তার শেষ স্টেটমেন্টটি এক্সিকিউশন করে এবং exit() স্টেটমেন্টের মাধ্যমে অপারেটিং সিস্টেমের কাছ থেকে ডিলিট করতে বলে তখন সে Terminate হয়। এই সময়ে প্রসেসটি তার Parent প্রসেসকে কোনো স্ট্যাটাস ভ্যালু ( সাধারণত integer ) রিটার্ন করতে পারে। এসময় অপারেটিং সিস্টেম সমস্ত প্রকার রিসোর্স deallocate করে ফেলে।
প্যারেন্ট প্রসেস চাইলে যে কোনো সময় তার Child Process কে terminate করতে পারবে। এছাড়াও ইউজার চাইলে যে কোনো সময় জোর করে কোনো প্রোসেসকে টারমিন্টে করতে পারে। নিচের কারণগুলোর কারনে সাধারনত Parent Process তার Child Process কে terminate করেঃ
- যখন Child Process কে অ্যালোকেট করে দেওয়া রিসোর্সের চেয়ে অতিরিক্ত রিসোর্স ব্যবহার করে।
- Child Process কে যে কাজ করতে দেওয়া হয়েছিলো তার আর প্রয়োজন নেই।
- যখন Parent Process শেষ ( exit ) হচ্ছে তখন অপারেটিং সিস্টেম এর child process গুলোকে Parent Terminate হওয়ার পর আর এক্সিকিউট করতে দেয় না।
Interprocess Communication
অপারেটিং সিস্টেমে একসাথে এক্সিকিউট হওয়া প্রসেসগুলোকে Independent Process অথবা Cooperating Process এই দুই ভাগে ভাগ করা যায়। যে সকল প্রোসেস অন্য কোনো প্রসেস দ্বারা প্রভাবিত হয় না এবং অন্য কোনো প্রসেসর সাথে কোনো প্রকার ডাটা শেয়ার করে না তাদেরকে Independent Process বলে। অপরদিকে, যে সকল প্রোসেসে অন্য কোনো প্রসেস দ্বারা প্রভাবিত হতে পারে অথবা, অন্য কোনো প্রসেসের সাথে ডাটা শেয়ার করে তাদেরকে Cooperating Process বলে।
Cooperating Process কে বৈধ করার কয়েকটি কারণ হলোঃ
- Information Sharing: অনেক সময়ই অনেকগুলো প্রসেসের একই ধরনের তথ্যের প্রয়োজন হতে পারে। এই ধরনের পরিস্তিতিতে এরকম পরিবেশের ব্যবস্থা করা উচিত।
- Computation speedup: যদি আমরা কোনো টাস্কের স্পীড বৃদ্ধি করতে চাই তাহলে এটিকে বিভিন্ন সাবটাস্কে ভাগ করে সমান্তরালে এক্সিকিউট করলে computation এর স্পীড বৃদ্ধি পাবে। এসকল ক্ষেত্রে রিসোর্স শেয়ার করা প্রয়োজন।
- Modularity: অনেক সময়ই আমাদেরকে প্রোসেস বা থ্রেডগুলোকে modular fashion এ গঠন করা প্রয়োজন হতে পারে।
- Convenience: ব্যবহারকারী একই সময়ে বিভিন্ন কাজ করতে পারে। যেমন editing, painting, compiling ইত্যাদি।
Cooperating Process গুলোর জন্য Interprocess Communication (IPC) মেকানিজমের প্রয়োজন। এই মেকানিজমের কাজ হলো ডাটা ও ইনফরমেশন শেয়ার করা। Interprocess Communication এর ২ টি প্রধান মডেল রয়েছে। এগুলো হলোঃ (১) shared memory এবং (২) message passing.
Shared-Memory Systems
Shared Memory system মডেলে communicate করার ্জন্য একটি shared memory region এর প্রয়োজন। সাধারণত, এই shared region প্রসেসের address স্পেসের পাশে তৈরী হয়ে থাকে। অন্য প্রসেসগুলো এই shared region এর সাথে communicate করার জন্য অবশ্যই তাদের address space এ এটাকে অ্যাটাচ/সংযুক্ত করার লাগবে। প্রসেসগুলো এই shared region এ ডাটা write / read এর মাধ্যমে communicate করে থাকবে। এই স্থানের ডাটা এবং লোকেশন অপারেটিং সিস্টেমের নিয়ন্ত্রনে থাকবে না, সম্পূর্ণ প্রসেসগুলোর নিয়ন্ত্রনে থাকবে।
Message-Passing Systems
Message Passing system এ প্রসেসগুলো তাদের মধ্যে একই address space ব্যবহার না করে শুধুমাত্র message pass করার মধ্যে কমিউনিকেট করে থাকে। Distributed environment এর ক্ষেত্রে এই ধরনের সিস্টেম কার্যকর। যেমন চ্যাটিং অ্যাপলিকেশনে একটি পিসি থেকে মেসেজ সেন্ড করা হয় এবং অন্য একটি পিসি থেকে সেই মেসেজ রিসিভ করা হয়। Message Passing System এ অবশ্যই send(message) এবং receive(message) এই দুটি ফিচার থাকতে হবে।
⇒Naming
প্রসেসগুলো যখন নিজেদের মধ্যে কমিউনিকেট করবে তখন অবশ্যই তাদেরকে রেফার করা জন্য Name থাকবে। তারা হয় direct না হয় indirect communication করতে পারে।
Direct communication এর ক্ষেত্রে সেন্ডার এবং রিসিভার এর নাম অবশ্যই কমিউনিকেট করার সময় পাস করতে হবে। এই স্কিমা অনুসারে send() এবং receive() ফাংশন হবেঃ
- send(P, message) – Send a message to process P
- receive(Q, message) – Receive a message from process Q
⇒Synchronization
ম্যাসেজ পাসিং সাধারণত send() এবং receive() ফাংশনের মাধ্যমে হয়ে থাকে। এছাড়াও এটি অন্যভাবেও ডিজাইন করো যায়। Message Passing টা blocking ( synchronous) অথবা nonblocking (asynchronous) হিসেবেও পাস হতে পারে।
- Blocking Send: এ পদ্ধতিতে Receiving process যতক্ষন না পর্যন্ত মেসেজ রিসিভ করে ততক্ষন পর্যন্ত Sending Process ব্লক অবস্থায় অপেক্ষা করতে হয়।
- Nonblocking Send: এ পদ্ধতিতে sending process মেসেজ সেন্ড করে এবং তার অপারেশন আবার শুরু করে।
- Blocking Receive: মেসেজ অ্যাভইলেবল না হওয়া পর্যন্ত receiver blocked অবস্থায় থাকে।
- Nonblocking Receive: Receiver হয় কোন বৈধ মেসেজ রিসিভ করে অথবা NULL মেসেজ রিসিভ করে।
⇒Buffering
মেসেজ এক্সেঞ্জের সময় একটি টেম্পরারি স্টোরেজের প্রয়োজন হয় ( Temporary Queue ) একেই সাধারণত বাফার বলে। এরকম queue ৩ ভাবে তৈরী করা যেতে পারেঃ
- Zero Capacity: এই কিউর সর্বোচ্চ ধারনক্ষমতা হবে ০ ! অর্থাৎ কোনো মেসেজ এর মধ্যে অপেক্ষা করতে পাবে না। এমতাবস্থায় সেন্ডারকে অবশ্যই ব্লক থাকতে হবে রিসিভার মেসেজ রিসিভ না করা পর্যন্ত !
- Bounded Capacity: এই কিউর কিছু নির্দিষ্ট ধারনক্ষমতা n থাকবে। অর্থাৎ এর মধ্যে সর্বোচ্চ n সংখ্যক মেসেজ থাকতে পারবে। মেসেজ পূর্ণ হলে sender ব্লক হবে।
- Unbounded Capacity: এই কিউর দৈর্ঘ্য অসীম! এতে যেকোনো সংখ্যক মেসেজ রাখা সম্ভব। এবং সেন্ডার কখনও ব্লক হবে না !
Leave a Reply