Saturday, July 13, 2013

ലിനക്സ് സിസ്റ്റം സ്റ്റാർട്ടപ്പ് - 3

ഇനിറ്റ് പ്രോസസ്സ് ആണ് ലിനക്സ്/യൂണിക്സ് സിസ്റ്റങ്ങളിലെ ആദ്യത്തെ യൂസർ പ്രോസസ്സ് എന്ന് പറഞ്ഞുവല്ലോ. കെർണൽ കമ്പ്യൂട്ടറിലെ ഹാർഡ്‌‌വെയറിനെ പ്രവർത്തനസജ്ജമാക്കിയ ശേഷം ഉപഭോക്താവിന്‌ കമ്പ്യൂട്ടർ ഉപയോഗിക്കാൻ സജ്ജമാക്കുന്ന വിവിധ ക്രമീകരണങ്ങൾ നടത്തുന്നത് ഇനിറ്റ് പ്രോസസ്സ് ആണ്. ഇതിനായി ഇനിറ്റ് മുൻകൂട്ടി ക്രമീകരിച്ചിരിക്കുന്ന വിവിധ സർവ്വീസുകൾ ആരംഭിക്കുന്നു. യൂണിക്സ് സിസ്റ്റങ്ങളിൽ ഈ സർവ്വീസുകളെ ഡെമോൺ പ്രോസസ്സുകൾ എന്നാണ് വിളിക്കുന്നത്. യൂണിക്സ് കീഴ്‌‌വഴക്കം അനുസരിച്ച് ഈ പ്രോസസ്സുകളുടെ പേരിന്റെ അവസാനം d എന്ന അക്ഷരം ചേർക്കാറുണ്ട്. നിങ്ങളുടെ കമ്പ്യൂട്ടറീലെ ഡെമോൺ പ്രോസസ്സുകൾ ഏതൊക്കെയാണെന്നറിയാൻ ഒരു ടെർമിനൽ തുറന്ന് ps -e എന്ന് ടൈപ്പ് ചെയ്ത് എന്റർ അമർത്തി നോക്കൂ, udevd, syslogd, smbd തുടങ്ങി വിവിധ പ്രോസസ്സുകൾ കാണാൻ സാധിക്കും. ഇനിറ്റ് പ്രോസസ്സ് ഒരിക്കൽ ആരംഭിച്ചാൽ കമ്പ്യൂട്ടർ ഓഫ് ചെയ്യുന്നത് വരെ പ്രവർത്തിച്ചുകൊണ്ടിരിക്കും. ഈ പ്രോസസ്സ് പ്രവർത്തനം അവസാനിപ്പിച്ചാൽ കെർണൽ പാനിക്ക് അവസ്ഥ ഉണ്ടാകുകയും കമ്പ്യൂട്ടർ റീസ്റ്റാർട്ട് ആകുകയും ചെയ്യും. (ഈ അവസരത്തിലെ കെർണലിന്റെ പെരുമാറ്റം ഓരോ യൂണിക്സ് സിസ്റ്റങ്ങളിലും വ്യത്യസ്തമായിരിക്കും).

വിവിധ യൂണിക്സ് സിസ്റ്റങ്ങളിൽ വിവിധ ഇനിറ്റ് പ്രോഗ്രാമുകൾ ആയിരിക്കും ഉണ്ടായിരിക്കുക. ലിനക്സ് ഡിസ്ട്രിബ്യൂഷനുകൾ ഉപയോഗിക്കുന്ന ചില ഇനിറ്റ് പ്രോഗ്രാമുകൾ താഴെ കൊടുക്കുന്നു.

1. സിസ്‌‌ വി ഇനിറ്റ് (SysV Init)
യൂണിക്സ് സിസ്റ്റങ്ങളിൽ പരമ്പരാഗതമായി ഉപയോഗിച്ച് വന്നിരുന്ന ഇനിറ്റ് പ്രോഗ്രാമാണിത്. ഈ പ്രോഗ്രാമിന്റെ പ്രവർത്തനം /etc/inittab എന്ന ക്രമീകരണ ഫയലിനെ അടിസ്ഥാനമാക്കി ആണ്. /etc/init.d/ എന്ന ഡയറക്റ്ററിയിൽ ആണ് വിവിധ സർവ്വീസുകൾ നിർവചിച്ചിരിക്കുന്ന ഫയലുകൾ ഉണ്ടായിരിക്കുക. ഇത് സർവ്വീസുകളെ ഒന്നിനു ശേഷം ഒന്നായി ആരംഭിക്കുന്നു.

2. സിസ്റ്റംഡി (Systemd)
താരതമ്യേന പുതിയ ഒരു ഇനിറ്റ് പ്രോഗ്രാമാണ് സിസ്റ്റംഡി. സിസ്റ്റം ഡെമോൺ എന്നതിന്റെ ചുരുക്കമാണ് ഇത്. വിവിധ സർവ്വീസുകൾ നിർവചിക്കാനും നിയന്ത്രിക്കാനുമുള്ള ഒരു മെച്ചപ്പെട്ട് ചട്ടക്കൂട് ലഭ്യമാക്കുക എന്നതാണ് ഇതിന്റെ ലക്ഷ്യം. ഫെഡോറ, ആർച്ച് ലിനക്സ് തുടങ്ങിയ വിവിധ ലിനക്സ് സിസ്റ്റങ്ങളിലെ ഇനിറ്റ് പ്രോസസ്സായി ഇപ്പോൾ സിസ്റ്റംഡി ഉപയോഗിക്കപ്പെടുന്നു. ഒന്നിനു പുറകെ ഒന്നായി പ്രോസസ്സുകൾ ആരംഭിക്കുന്ന പരമ്പരാഗത രീതിയിൽ നിന്ന് വ്യത്യസ്തമായി സമാന്തരമായി തന്നെ പ്രോസസ്സുകൾ ആരംഭിക്കാൻ സിസ്റ്റംഡി ക്ക് സാധിക്കുന്നു. ഇതുവഴി കമ്പ്യൂട്ടർ ബൂട്ട് ചെയ്യാൻ ആവശ്യമായ സമയം കുറക്കാൻ സാധിക്കും.

3. അപ്‌‌സ്റ്റാർട്ട് (Upstart)
ഉബുണ്ടു ലിനക്സ് ഡിസ്ട്രിബ്യൂഷന്റെ നിർമ്മാതാക്കളായ കാനോനിക്കൽ കമ്പനി വികസിപ്പിച്ചെടുത്ത് ഇനിറ്റ് പ്രോഗ്രാം ആണ് അപ്‌‌സ്റ്റാർട്ട്. പരമ്പരാഗത രീതിയിൽ മുൻകൂട്ടി തീരുമാനിക്കപ്പെട്ട ക്രമത്തിൽ സർവ്വീസുകൾ ആരംഭിക്കുന്നതിൽ നിന്ന് വ്യത്യസ്തമായി വിവിധ സംഭവങ്ങളുടെ (events) അടിസ്ഥാനത്തിൽ സർവ്വീസുകൾ ആരംഭിക്കുകയും അവസാനിപ്പിക്കുകയും ചെയ്യുന്ന രീതി ആണ് അപ്‌‌സ്റ്റാർട്ട് പിൻതുടരുന്നത്. നോക്കിയയുടെ മെമോ, ഗൂഗിൾ ക്രോം ഓ എസ്, ഉബുണ്ടൂ തുടങ്ങിയവ അപ്‌‌സ്റ്റാർട്ട് ആണ് ഇനിറ്റ് പ്രോഗ്രാമായി ഉപയോഗിക്കുന്നത്. കമ്പ്യൂട്ടറിന്റെ ബൂട്ടിങ്ങ് സമയം പത്തുസെക്കന്റിലും താഴേക്ക് കുറക്കാൻ അപ്‌‌സ്റ്റാർട്ട് വഴി സാധ്യമായി.

4. ആൻഡ്രോയിഡ് ഇനിറ്റ്
ആൻഡ്രോയിഡ് ഒരു ലിനക്സ് കെർണൽ അധിഷ്ഠിത ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ആണെന്നറിയാമല്ലോ. ആൻഡ്രോയിഡിനും സ്വന്തമായി ഒരു ഇനിറ്റ് പ്രോഗ്രാം ഉണ്ട്. പരമ്പരാഗത രീതി തന്നെ ആണ് ഈ ഇനിറ്റ് പ്രോഗ്രാമും പിൻതുടരുന്നത്.

ഇവക്ക് പുറമെ മാക് ഓഎസ്, സോളാരിസ്, ബിഎസ്‌‌ഡി തുടങ്ങിയ യൂണിക്സ് സിസ്റ്റങ്ങൾക്കൊക്കെ തന്നെ അവയുടെ ഇനിറ്റ് പ്രോഗ്രാമുകൾ ഉണ്ട്. കമ്പ്യൂട്ടറിന്റെ പ്രവർത്തന ആരംഭത്തിൽ സർവ്വീസുകൾ ആരംഭിക്കുന്നതോടെ ഇനിറ്റ് പ്രോസസ്സിന്റെ പ്രവർത്തനം അവസാനിക്കുന്നില്ല. ഈ സർവ്വീസുകൾ ഏതെങ്കിലും പ്രവർത്തനരഹിതമായാൽ അവയെ പുനരാരംഭിക്കൽ, വിവിധ റൺ ലെവലുകളിലെ ക്രമീകരണങ്ങൾ, സിസ്റ്റം ഷട്ട് ഡൗൺ ആരംഭിക്കുമ്പോൾ സർവ്വീസുകളെ അവസാനിപ്പിക്കൽ ഒക്കെ ഇനിറ്റ് പ്രോസസ്സിന്റെ കടമയാണ്.

യൂണിക്സ് സിസ്റ്റങ്ങളിൽ അവയുടെ ഓരോ സമയത്തെ പ്രവർത്തന സ്ഥിതിയെ റൺലെവൽ എന്ന് വിളിക്കുന്നു. ലിനക്സ് സിസ്റ്റങ്ങളിൽ 6 വ്യത്യസ്ത റൺ ലെവലുകൾ ഉണ്ട്. 
റൺലെവൽ 0 - സിസ്റ്റം ഹാൾട്ട് (ഓഫ് ആയിരിക്കുന്ന അവസ്ഥ)
റൺലെവൽ 1 - സിങ്കിൽ യൂസർ മോഡ് (ഒരൊറ്റ ഉപയോക്താവ് മാത്രം. അഡ്മിനിസ്ട്രേറ്റർ യൂസറിന്റെ അനുവാദങ്ങളോടെ ഉള്ള അറ്റകുറ്റപ്പണികൾക്കായി ഉപയോഗിക്കപ്പെടുന്നു)
റൺലെവൽ 2 - നെറ്റ്‌‌വർക്കിങ്ങ് ഇല്ലാത്ത ഒന്നിലധികം ഉപയോക്താക്കളെ പിൻതുണക്കുന്ന അവസ്ഥ.
റൺലെവൽ 3 - നെറ്റ്‌‌വർക്കിങ്ങ് പിൻതുണ അടക്കം ഒന്നിലധികം ഉപയോക്താക്കളെ പിൻതുണക്കുന്ന അവസ്ഥ
റൺലെവൽ 4 - ഉപയോഗത്തിൽ ഇല്ല.
റൺലെവൽ 5 - നെറ്റ്‌‌വർക്കിങ്ങ് പിൻതുണ, ഒന്നിലധികം ഉപയോക്താക്കൾക്കുള്ള പിൻതുണ, ഗ്രാഫിക്കൽ യൂസർ ഇന്റർഫേസ്
റൺലെവൽ 6 - സിസ്റ്റം റീസ്റ്റാർട്ട്

ഇനിറ്റ് കമാന്റ് ഉപയോഗിച്ച് റൺലെവലുകൾ മാറ്റാൻ സാധിക്കും. init 6 എന്ന കമാന്റ് കമ്പ്യൂട്ടർ റീസ്റ്റാർട്ട് ചെയ്യാൻ ഉപയോഗിക്കാം. (ഇതൊരു സുരക്ഷിതമായ മാർഗ്ഗമല്ല).

ലിനക്സിലെ മൾട്ടി യൂസർ പിൻതുണ, ടെർമിനലുകൾ, ഗ്രാഫിക്കൽ ഇന്റർഫേസ് എന്നിവയെപ്പറ്റി അടുത്ത പോസ്റ്റ്.

Friday, July 12, 2013

ലിനക്സ് സിസ്റ്റം സ്റ്റാർട്ടപ്പ് - 2

ലിനക്സ് കെർണൽ ഇമേജ് കമ്പ്രസ്സ്ഡ് ആയിരിക്കും എന്ന് നേരത്തേ പറഞ്ഞിരുന്നല്ലോ. സാധാരണ കമ്പ്യൂട്ടറുകളിൽ /boot ഡയറക്ടറിയിൽ ഉള്ള കെർണൽ ഇമേജ് (vmlinuz) ഒരു ഡീ-കമ്പ്രസ്സർ പ്രോഗ്രാമിൽ ലിനക്സ് കെർണൽ ഇമേജ് കൂടി ഉൾപ്പെടുത്തിയ ഫയൽ ആണ്. ബൂട്ട് ലോഡർ ഈ ഇമേജിനെ മെമ്മറിയിൽ പകർത്തിയതിനുശേഷം അതിന്റെ പ്രവർത്തിപ്പിച്ച് തുടങ്ങുമ്പോൾ ഈ ഡീ-കമ്പ്രസ്സർ ആണ് ആദ്യം പ്രവർത്തിക്കുന്നത്. ബൂട്ട് ലോഡർ പ്രവർത്തനക്ഷമമാക്കി വച്ച സീരിയൽ പോർട്ടോ ഡിസ്പ്ലേ ഡിവൈസോ ആയിരിക്കും ഈ സമയത്ത് കെർണൽ ഉപയോഗിക്കുന്നത്. ഡീ കമ്പ്രസ്സ് ചെയ്ത ലിനക്സ് കെർണൽ മെമ്മറിയിൽ മുൻകൂട്ടി നിശ്ചയിക്കപ്പെട്ട സ്ഥലത്തായിരിക്കും ഉണ്ടാവുക. ഡീ കമ്പ്രഷൻ പൂർണ്ണമായ ശേഷം ഈ മെമ്മറി അഡ്രസ്സിൽ നിന്ന് പ്രവർത്തനം പുനരാരംഭിക്കപ്പെടുന്നു. എല്ലാ സി പ്രോഗ്രാമുകൾക്കും പ്രവർത്തിക്കുന്നതിനാവശ്യമായ ചുറ്റുപാടുകൾ കെർണലിനും ആവശ്യമാണല്ലോ. സ്റ്റാക്ക്, ഹീപ്പ് തുടങ്ങിയവ ഒക്കെ ആദ്യം ബൂട്ട് ലോഡർ തയ്യാറാക്കുമെങ്കിലും അത് ഡീ കമ്പ്രസ്സറിന്റെ ഉപയോഗത്തിനു വേണ്ടി ആണ്. ലിനക്സ് കെർണലിന് പ്രവർത്തിക്കാനാവശ്യമായ സ്റ്റാക്ക്, ഹീപ്പ് തുടങ്ങിയവ ഒക്കെ തയ്യാറാക്കുന്നത് ഡീ കമ്പ്രസ്സർ പ്രോഗ്രാം ആണ്. ഇതും ലിനക്സ് കെർണൽ സോഴ്സ് കോഡിന്റെ ഭാഗം തന്നെ ആണ്.

കെർണൽ പ്രവർത്തനമാരംഭിച്ചാൽ ആദ്യം ചെയ്യുന്നത് അത് പ്രവർത്തിക്കുന്ന കമ്പ്യൂട്ടർ ആർക്കിട്ടെക്ചറിന് പ്രത്യേകമായുള്ള ക്രമീകരണങ്ങൾ ആയിരിക്കും. സാധാരണ ഇന്റൽ പ്രോസസ്സർ അധിഷ്ഠിതമായ കമ്പ്യൂട്ടറുകളിൽ ഇത് സമാനമായിരിക്കുമെങ്കിലും ലിനക്സ് പ്രവർത്തിക്കുന്ന ഓരോ വ്യത്യസ്ത ആർക്കിട്ടെക്ചറിലും ഇത് വ്യത്യസ്തമായിരിക്കും. വ്യത്യസ്ത ആം പ്രോസസ്സറുകൾ അടിസ്ഥാനമാക്കിയുള്ള് ഉപകരണങ്ങളിൽ പോലും ഇത് വ്യത്യസ്തമായിരിക്കും. പ്രവർത്തിക്കുന്ന ഉപകരണത്തെക്കുറിച്ചുള്ള വിവരങ്ങൾ ലിനക്സിനു നൽകുന്നത് ബൂട്ട് ലോഡർ ആണ്. ആം അധിഷ്ഠിത ഉപകരണങ്ങളിൽ ബൂട്ട് ലോഡർ ATAGS എന്ന ഒരു സ്ട്രക്ചറിൽ ആയിരിക്കും ഈ വിവരങ്ങൾ കൈമാറുന്നത്. എല്ലാ ഉപകരണങ്ങളിലും ബൂട്ട് ലോഡർ ലിനക്സ് കെർണലിന് കമാന്റ് ലൈൻ ആർഗ്യുമെന്റ്സ് കൈമാറിയിരിക്കും. സാധാരണ ടെർമിനലിൽ പ്രോഗ്രാമുകൾ ഉപയോഗിക്കുമ്പോൾ അവക്ക് നൽകുന്ന ആർഗ്യുമെന്റിന് സമാനമാണിത്. ലിനക്സ് റൂട്ട് ഫയൽ സിസ്റ്റം ഉൾക്കൊള്ളുന്ന ഡിസ്ക്, ബൂട്ടിങ്ങ് സമയത്ത് സീരിയൽ കൺസോളായി ഉപയോഗിക്കേണ്ട ഉപകരണം, ഉപകരണത്തിൽ ലഭ്യമായ മെമ്മറി തുടങ്ങി വിവിധ വിവരങ്ങൾ ഇതിൽ ഉണ്ടായിരിക്കും. ഇത് ഉപകരണങ്ങൾക്കനുസരിച്ച് മാറിക്കൊണ്ടിരിക്കുകയും ചെയ്യും. ഇതിലെ ഒരു പ്രധാനപ്പെട്ട ഭാഗം വിർച്ച്വൽ മെമ്മറി ഉപയോഗത്തിനാവശ്യമായ സെഗ്മെന്റുകളും പേജുകളും ഹാർഡ്‌വെയറും ക്രമീകരിക്കുക എന്നതാണ്. മെമ്മറി മാനേജ്മെന്റ് യൂണിറ്റ് എല്ലാ ആധുനിക പ്രോസസ്സറുകളുടെയും ഭാഗമാണ്. ഇന്റൽ പ്രോസസ്സറുകളിൽ ഈ സമയത്ത് സിപിയു റിയൽ മോഡിൽ നിന്നും പ്രൊട്ടക്റ്റഡ് മോഡിലേക്കും മാറുന്നു.

ഉപകരണത്തിനാവശ്യമായ പ്രത്യേക ക്രമീകരണങ്ങൾക്ക് ശേഷം കെർണൽ സിസ്റ്റത്തിലെ വിവിധ ഉപകരണങ്ങളെ പ്രവർത്തനസജ്ജമാക്കുവാൻ ആരംഭിക്കുന്നു. ലിനക്സ് ഡിവൈസ് ഡ്രൈവറുകൾ രണ്ട് രീതിയിൽ കെർണലിലേക്ക് ചേർക്കാൻ സാധിക്കും. ഒന്ന് കെർണൽ കമ്പൈലേഷൻ സമയത്ത് കെർണലിൽ ഇമേജിൽ തന്നെ ഉൾപ്പെടുത്തുക, രണ്ട്, മൊഡ്യൂളുകൾ ആയി കമ്പൈൽ ചെയ്ത് കെർണൽ പ്രവർത്തിക്കുന്ന സമയത്ത് അതിലേക്ക് ചേർക്കുക. ആദ്യത്തെ രീതിയിൽ ഇമേജിൽ ഉൾപ്പെടുത്തിയിരിക്കുന്ന ഡ്രൈവറുകൾ ഈ ഘട്ടത്തിൽ പ്രവർത്തനസജ്ജമാക്കപ്പെടുന്നു. ഉപകരണങ്ങൾ ക്രമീകരിച്ചതിനു ശേഷം കെർണൽ അതിന്റെ പ്രവർത്തനത്തിന്റെ മൂന്നാം ഘട്ടത്തിലേക്ക് പ്രവേശിക്കുന്നു.

ഡീ കമ്പ്രസ്സിങ്ങ്, പ്രത്യേക ക്രമീകരണങ്ങൾ എന്നീ ഘട്ടങ്ങൾ ഓരോ ഉപകരണത്തിലും ഓരോ രീതിയിൽ ആണെങ്കിലും ശേഷമുള്ള മൂന്നാം ഭാഗം എല്ലാ ഉപകരണങ്ങളിലും ഒരുപോലെ ആണ്. ഇതിനെ ഹാർഡ്‌വെയർ ഇൻഡിപ്പൻഡന്റ് എന്ന് പറയാം. ഈ ഭാഗത്ത് കെർണൽ ആദ്യം ചെയ്യുന്നത് പ്രോസസ്സുകൾ ആരംഭിക്കാൻ ആവശ്യമായ ക്രമീകരണങ്ങൾ നടത്തുകയാണ്. ഈ ഘട്ടത്തിൽ എത്തുമ്പോൾ കമ്പ്യൂട്ടറിൽ ഒരു പ്രോസസ്സ് മാത്രമേ ഉണ്ടാവുകയുള്ളു. ഇതിന്റെ പി ഐ ഡി 0 ആയിരിക്കും. ഇത് ലിനക്സ് കെർണൽ പ്രോസസ്സ് ആണ്. ഇതിനെ സ്വാപ്പർ (Swapper) എന്നും വിളിക്കാറുണ്ട്. പ്രോസസ്സ് ടേബിൾ, ഷെഡ്യൂളിങ്ങിനാവശ്യമായ വിവരങ്ങൾ എന്നിവ ക്രമീകരിച്ച ശേഷം ലിനക്സ് കെർണൽ ആദ്യത്തെ യൂസർ പ്രോസസ്സ് ആരംഭിക്കുന്നു. ഇതാണ് ഇനിറ്റ് പ്രോസസ്സ്. ഇനിറ്റ് പ്രോസസ്സിന്റെ പി ഐ ഡി 1 ആയിരിക്കും. ഇനിറ്റ് ആരംഭിക്കുന്ന പ്രോസസ്സുകളുടെയും പേരന്റ് പ്രോസസ്സ് പ്രവർത്തനം അവസാനിപ്പിച്ച ചൈൽഡ് പ്രോസസ്സുകളുടെയും പേരന്റ് പ്രോസസ്സ് ഇനിറ്റ് ആണ്. ലിനക്സ് കെർണൽ നേരിട്ട് സൃഷ്ടിക്കുന്ന ഒരു പ്രത്യേക പ്രോസസ്സ് ആണിത്. ഇനിറ്റ് പ്രോസസ്സിന്റെ യൂസർ ഐഡി 0 (റൂട്ട്) ആയിരിക്കും. ഇനിറ്റ് പ്രോസസ്സിന്റെ എക്സിക്യൂട്ടബിൾ സാധാരണയായി /sbin/init ആണ്. മറ്റേതെങ്കിലും എക്സിക്യൂട്ടബിൾ ഇനിറ്റ് ആയി ഉപയോഗിക്കണമെങ്കിൽ ബൂട്ട് ലോഡറിന്റെ കമാന്റ് ലൈൻ ആർഗ്യുമെന്റ് ലിസ്റ്റിൽ init=<ഇനിറ്റ് പ്രോഗ്രാമിന്റെ പാത്ത്> എന്ന് ചേർക്കാവുന്നതാണ്.

ഇനിറ്റ് പ്രോസസ്സ് ആരംഭിക്കുന്നതോടെ എക്സിക്യൂഷൻ കെർണൽ സ്പേസിൽ നിന്ന് യൂസർ സ്പേസിലേക്ക് മാറുന്നു. യൂസർ സ്പേസ് സിസ്റ്റം കോളുകൾ ഉപയോഗിക്കുമ്പോളും ഉപകരണങ്ങളിൽന്നിന്നുള്ള ഇന്ററപ്റ്റുകൾ ഉണ്ടാവുകയും ചെയ്യുമ്പോൾ ആണ് എക്സിക്യൂഷൻ പിന്നീട് കെർണൽ സ്പേസിലേക്ക് മാറുന്നത്.

ഇനിറ്റ് പ്രോസസ്സിനെക്കുറിച്ച് വിശദമായി അടുത്ത പോസ്റ്റ്.

Friday, July 05, 2013

ലിനക്സ് സിസ്റ്റം സ്റ്റാർട്ടപ്പ് - 1

പഴയ പോസ്റ്റുകളിൽ നിന്നും ഫയൽ സിസ്റ്റം, പ്രോസസ്സ് മാനേജ്മെന്റ് എന്നിവയെക്കുറിച്ച് ഒരു ധാരണ ലഭിച്ചിട്ടുണ്ടാകും എന്ന് കരുതുന്നു. ഒരു ലിനക്സ് സിസ്റ്റം പ്രവർത്തനമാരംഭിക്കുന്ന പ്രക്രിയ ആണ് ഈ പോസ്റ്റിൽ വിശദീകരിക്കാൻ ശ്രമിക്കുന്നത്. പ്രധാനമായും ഇന്റൽ x86 പ്രോസസ്സർ അടിസ്ഥാനമാക്കിയുള്ള ഒരു പിസിയിലും ARM പ്രോസസ്സർ അധിഷ്ഠിത സിസ്റ്റത്തിലും എങ്ങനെ ഒരു ലിനക്സ് സിസ്റ്റം ബൂട്ട് ചെയ്യുന്നു എന്ന് നോക്കാം.

സാധാരണ ഇന്റൽ പ്രോസസ്സർ (ഇത് നിർമ്മിക്കുന്നത് ഇന്റൽ തന്നെ ആകണമെന്നില്ല. ഇന്റൽ x86, x86_64 ഒരു ആർക്കിട്ടെക്ചർ ആണ്. എഎംഡി യും ഇതേ ആർക്കിട്ടെക്ചറിൽ പ്രോസസ്സറുകൾ നിർമ്മിക്കുന്നുണ്ട്) അധിഷ്ഠിതമായ പേഴ്സണൽ കമ്പ്യൂട്ടറുകൾ ഒക്കെ ഐബിഎം പിസി മാനദണ്ഡങ്ങൾ പാലിക്കുന്നവ ആണ്. ഇതിൽ ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റത്തിന്റെ ലോഡിങ്ങ്, ബൂട്ടിങ്ങ് ഒക്കെ പ്രതിപാദിച്ചിട്ടുണ്ട്. എന്നാൽ ആം പ്രോസസ്സറുകൾ ഉപയോഗിക്കുന്ന കമ്പ്യൂട്ടറുകൾക്ക് ഇതുപോലെ വ്യക്തമായ ഒരു മാനദണ്ഡം ഒന്നുമില്ല. ഓരോന്നിലും ഓരോ രീതിയിൽ ആയിരിക്കും ബൂട്ടിങ്ങ്. ഈ വ്യത്യാസങ്ങൾ ഒക്കെ ലിനക്സ് കെർണൽ/മറ്റേതെങ്കിലും ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ലോഡ് ചെയ്യുന്നത് വരെ മാത്രമേ കാണുകയുള്ളു. അതിനാൽ തന്നെ ലിനക്സിന്റെ സ്റ്റാർട്ടപ്പ് എല്ലാ സിസ്റ്റങ്ങളിലും ഒരുപോലെ തന്നെ ആയിരിക്കും.

ഒരു പിസി ഓൺ ചെയ്യുമ്പോൾ ആദ്യമായി പ്രവർത്തിച്ചുതുടങ്ങുക അതിലെ ബയോസ് (BIOS) ആണ്. ബയോസ് ആ കമ്പ്യൂട്ടറിൽ ഘടിപ്പിച്ചിരിക്കുന്ന ഉപകരണങ്ങളെ പ്രവർത്തിപ്പിക്കാൻ ആരംഭിക്കുകയും അവയുടെ പ്രവർത്തനത്തെ സംബന്ധിച്ച ചില അടിസ്ഥാന പരിശോധനകൾ നടത്തുകയും ചെയ്യുന്നു. ഇതിനെ പവർ ഓൺ സെൽഫ് ടെസ്റ്റ് (POST) എന്ന് വിളിക്കുന്നു. പോസ്റ്റിനു ശേഷം ബയോസ് സിസ്റ്റത്തിൽ ഘടിപ്പിച്ചിരിക്കുന്ന ഡിസ്കുകൾ പരിശോധിക്കുന്നു. അവയിലേതെങ്കിലും ഒരു ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ഉൾക്കൊള്ളുന്നുണ്ടോ എന്നറിയാനാണ് ഈ പരിശോധന. അങ്ങനെ ഉള്ള ഡിസ്കുകളുടെ മാസ്റ്റർ ബൂട്ട് റെക്കോഡിൽ (MBR) ബൂട്ടബിൾ എന്ന് രേഖപ്പെടുത്തിയിരിക്കും. ഏതൊക്കെ ഡിസ്ക് ഡ്രൈവുകൾ ഏത് ക്രമത്തിൽ പരിശോധിക്കണം എന്ന് ക്രമീകരിക്കാനുള്ള സൗകര്യങ്ങൾ ആധുനിക ബയോസുകൾ എല്ലാം നൽകുന്നുണ്ട്. ബൂട്ടബിൾ ആയ ഡിസ്കുകളുടെ മാസ്റ്റർ ബൂട്ട് റെക്കോഡിൽ അതിലുള്ള ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റത്തെ മെമ്മറിയിലേക്ക് കൊണ്ടുവരാനുള്ള പ്രോഗ്രാം ഉണ്ടായിരിക്കും. കൂടുതൽ വിശദീകരണം ഇവിടെ. ബയോസ് ഈ പ്രോഗ്രാമിനെ ഡിസ്കിൽ നിന്ന് വായിച്ച് കമ്പ്യൂട്ടറിന്റെ റാമിൽ മുൻകൂട്ടി നിശ്ചയിക്കപ്പെട്ട ഒരു മെമ്മറി വിലാസത്തിലേക്ക് പകർത്തുന്നു. അതിനുശേഷം ആ വിലാസത്തിലുള്ള നിർദ്ദേശങ്ങൾ പാലിക്കാൻ പ്രോസസ്സറിനോട് ആവശ്യപ്പെടുന്നു. ഇത്രയുമാണ് ബൂട്ടിങ്ങ് സമയത്തെ ബയോസിന്റെ കടമകൾ. റാമിൽ പകർത്തപ്പെട്ട ഈ പ്രോഗ്രാം ബൂട്ട് ലോഡർ എന്നറിയപ്പെടുന്നു. ഇന്ന് ബൂട്ട് ലോഡറുകൾ പല ഘട്ടങ്ങളായി ആണ് പ്രവർത്തിക്കുക. അതിനാൽ ബയോസ് ലോഡ് ചെയ്യുന്ന ഈ ചെറിയ ഭാഗത്തെ ബൂട്ട് ലോഡറിന്റെ ഒന്നാം ഘട്ടം എന്ന് വിളിക്കാം. ഈ ഒന്നാം ഭാഗത്തിന്റെ ജോലി ഡിസ്കിൽ നിന്ന് അല്പം കൂടി വലിപ്പമുള്ള രണ്ടാം ഘട്ട പ്രോഗ്രാമിനെ റാമിലേക്ക് പകർത്തൽ ആണ്. പിസി മാനദണ്ഡങ്ങൾ അടിസ്ഥാനമാക്കി പ്രവർത്തിക്കുന്ന ബയോസ് ആദ്യഘട്ടത്തിൽ ഡിസ്കിന്റെ എംബിആറിൽ നിന്ന് 512 ബൈറ്റുകൾ മാത്രമേ വായിക്കൂ എന്നതിനാലാണ് ഈ രീതി ആവശ്യമായി വരുന്നത്.

ആം പ്രോസസ്സർ അധിഷ്ഠിതമായ സിസ്റ്റങ്ങൾ ബൂട്ടിങ്ങിനായി പ്രത്യേക മാനദണ്ഡങ്ങൾ ഒന്നും ഉപയോഗിക്കുന്നില്ലെങ്കിലും ഈ പ്രവർത്തനം മിക്കവാറും സിസ്റ്റങ്ങളിൽ സമാനമാണ്. മിക്ക ആം അധിഷ്ഠിത സിസ്റ്റങ്ങളും ആം അധിഷ്ഠിത എസ്ഒ‌സി (സിസ്റ്റം ഓൺ ചിപ്പ്) ആണ് ഉപയോഗിക്കപ്പെടുന്നത്. ടിഐ ഒമാപ് (TI OMAP), ക്വാൽക്കോം സ്നാപ്‌ഡ്രാഗൺ, സാംസങ്ങ് എക്സിനോസ് തുടങ്ങിയവ ഒക്കെ പ്രസിദ്ധമായ ചില ആം അധിഷ്ഠിത എസ് ഓ സി കൾ ആണ്. എസ് ഓ സി യിൽ പ്രോസസ്സർ കോർ, റാം, റോം, ഐ/ഒ കണ്ട്രോളറുകൾ തുടങ്ങിയവ എല്ലാം ഒരൊറ്റ ചിപ്പിൽ തന്നെ ഉൾക്കൊള്ളിച്ചിരിക്കും. ഇവയിൽ എല്ലാം ഒരു റീഡ് ഒൺലി മെമ്മറിയിൽ ബൂട്ട് റോം എന്ന പേരിൽ ഒരു ചെറിയ പ്രോഗ്രാം ഉണ്ടാകും. ഈ ബൂട്ട് റോം പിസിയിലെ ബയോസിന് സമാനമാണെന്ന് പറയാം. എന്നാൽ ബൂട്ടിങ്ങിനു ശേഷം അനുബന്ധ ഉപകരണങ്ങളെ പ്രവർത്തിപ്പിക്കാൻ ഈ ബൂട്ട് റോമിന്റെ ആവശ്യമില്ല. മിക്കവാറും ഒരു ബൂട്ട് ലോഡറിനെയോ പ്രോഗ്രാമിനെയോ പ്രവർത്തിപ്പികുക, ഡിസ്കിൽ നിന്നോ മെമ്മറി കാർഡിൽ നിന്നോ, സീരിയൽ/യുഎസ്ബി ഇന്റർഫേസുകളിൽ നിന്നോ പ്രോഗ്രാമുകൾ/ഡാറ്റ സ്വീകരിച്ച് ഫ്ലാഷ് മെമ്മറിയിലേക്ക് എഴുതുക തുടങ്ങിയ പല കാര്യങ്ങൾ ബൂട്ട് റോമുകൾ പിന്തുണക്കാറുണ്ട്. ഇതിന്റെ പ്രവർത്തനത്തിനായുള്ള ക്രമീകരണങ്ങൾ പിന്നുകളും ജമ്പറുകളും ഉപയോഗിച്ചാണ് ചെയ്യാറ്. ഒരു ആം അധിഷ്ഠിത ഡെവലപ്പ്മെന്റ് ബോർഡ് വാങ്ങിയാൽ എസ് ഡി കാർഡിൽ നിന്ന് ബൂട്ട് ചെയ്യാൻ, യു എസ് ബി യിൽ നിന്ന് ബൂട്ട് ചെയ്യാൻ എന്നിങ്ങനെ ജമ്പർ ക്രമീകരണങ്ങൾ അതിൽ പ്രതിപാദിച്ചിരിക്കും. (നിർബന്ധമില്ല). മൊബൈൽ ഫോണുകളിലും മറ്റും ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം, ബൂട്ട് ലോഡർ തുടങ്ങിയവ ഉണ്ടാവുക ഫ്ലാഷ് മെമ്മറിയിൽ ആയിരിക്കും. ചില ബോർഡുകൾ എസ് ഡി കാർഡുകളും ഉപയോഗിക്കാറുണ്ട്. പവർ ഓൺ ചെയ്യുമ്പോൾ ആദ്യം എസ് ഓ സി യിലെ ബൂട്ട് ലോഡർ എസ് ഡി/ഫ്ലാഷ് കണ്ട്രോളറുകൾ പ്രവർത്തനക്ഷമമാക്കുകയും ബോർഡിൽ ആവശ്യമായ ക്രമീകരണങ്ങൾ നടത്തുകയും ചെയ്യും. അതിനുശേഷം ഫ്ലാഷ്/എസ് ഡി കാർഡിൽ നിന്ന് ബൂട്ട് ലോഡർ റാമിലേക്ക് പകർത്തുകയും അതിനെ പ്രവർത്തിപ്പിക്കുകയും ചെയ്യും.

ശേഷമുള്ള ഭാഗങ്ങൾ മിക്കവാറും എല്ലാ സിസ്റ്റങ്ങളിലും ഒരുപോലെ ആണ്. ഗ്രബ്, ലിലോ, യു-ബൂട്ട്, റെഡ് ബൂട്ട് തുടങ്ങിയവ ഇന്ന് വ്യാപകമായി ഉപയോഗിക്കപ്പെടുന്ന ചില ബൂട്ട് ലോഡറുകൾ ആണ്. ഗ്രബ്, ലിലോ തുടങ്ങിയവ സാധാരണയായി പിസിയിലും യു-ബൂട്ട് പോലുള്ളവ എംബെഡ്ഡഡ് ഉപകരണങ്ങളിലും ഉപയോഗിച്ച് വരുന്നു. ലിനക്സ് കെർണലിന് പ്രവർത്തിക്കാനാവശ്യമായ സാഹചര്യങ്ങൾ ഒരുക്കുക, അതിനെ മെമ്മറിയിലേക്ക് പകർത്തുക, പ്രോസസ്സറിനോട് അതിനെ പ്രവർത്തിപ്പിക്കാൻ ആവശ്യപ്പെടുക എന്നിവയാണ് പൊതുവേ ബൂട്ട് ലോഡറിന്റെ കടമകൾ. മിക്കവാറും ബൂട്ട് ലോഡറുകൾ ഈ സമയത്ത് ഒരു കമാന്റ് പ്രോംപ്റ്റ് നൽകാറുണ്ട്. ബൂട്ട് ലോഡർ പ്രോഗ്രാം പിന്തുണക്കുന്ന വിവിധ നിർദ്ദേശങ്ങൾ ഉപയോക്താവിന് ഇവിടെ ഉപയോഗിക്കാൻ സാധിക്കും. ഇത് വഴി ഏത് കെർണലാണ് പ്രവർത്തിപ്പിക്കേണ്ടത്, എന്തൊക്കെ വിവരങ്ങളാണ് കെർണലിനു നൽകണ്ടത് തുടങ്ങിയ വിവരങ്ങൾ ഉപയോക്താവിന് പരാമാർശിക്കാം. യു-ബൂട്ട് പോലുള്ള ബൂട്ട് ലോഡറുകൾ ഫ്ലാഷ് മെമ്മറിയിലെ വിവരങ്ങൾ മായിച്ച് കളയാനും പുതിയവ ചേർക്കാനും ഉള്ള സൗകര്യങ്ങളും നൽകുന്നുണ്ട്. ഈ സമയത്ത് ഉപയോക്താവിനായി കമാന്റ് പ്രോംപ്റ്റ് തുറക്കാൻ ആവശ്യമായ ഉപകരണങ്ങൾ കൂടി പ്രവർത്തിപ്പിക്കാനുള്ള വിവരങ്ങൾ (ഡ്രൈവറുകൾ) ബൂട്ട് ലോഡറിൽ ഉണ്ടായിരിക്കണം. യു എസ് ബി, സീരിയൽ പോർട്ട്, നെറ്റ്വർക്ക് ഇന്റർഫേസ് കാർഡ് തുടങ്ങിയവ ഒക്കെ മിക്കവാറും ബൂട്ട് ലോഡറുകൾക്ക് പ്രവർത്തിപ്പിക്കാൻ സാധിക്കും.

ലിനക്സ് കെർണൽ ഒരു മോണോലിത്തിക്ക് കെർണലാണ്. കമ്പൈൽ ചെയ്യപ്പെട്ട കെർണൽ ഒരൊറ്റ എക്സിക്യൂട്ടബിൾ ഫയൽ ആയിരിക്കും. ഈ ഫയൽ ഇ എൽ എഫ് ഫോർമാറ്റിൽ ആയിരിക്കും ഉണ്ടാവുക. മാത്രമല്ല വലിപ്പം കുറക്കാൻ ഇത് കമ്പ്രസ്സും ചെയ്തിരിക്കും. യു-ബൂട്ട് ബൂട്ട് ലോഡർ ആണ് ഉപയോഗിക്കുന്നതെങ്കിൽ അതിന് മനസ്സിലാകുന്ന യു ഇമേജ് എന്ന ഫോർമാറ്റിൽ ആയിരിക്കും കെർണൽ. ഇതിനെ ഡിസ്കിൽ നിന്ന് വായിച്ചെടുത്ത് മെമ്മറിയിലേക്ക് പകർത്തിയ ശേഷം അതിലെ ഇ എൽ എഫ് വിവരങ്ങൾ അനുസരിച്ച് അതിലെ വിവിധ സെഗ്മെന്റുകൾ മെമ്മറിയിൽ ക്രമീകരിക്കേണ്ടതുണ്ട്. ഇതും ബൂട്ട് ലോഡറിന്റെ കടമയാണ്. ലിനക്സ് കെർണലിനു മാത്രമല്ല, എല്ലാ എക്സിക്യൂട്ടബിൾ ഫയലുകൾക്കും പ്രവർത്തിക്കാൻ ഈ സഹായം ആവശ്യമാണ്. ലിനക്സ് കെർണൽ പ്രവർത്തിച്ച് തുടങ്ങിയാൽ കെർണൽ ഇത് ചെയ്തുകൊള്ളും.

ബൂട്ട് ലോഡർ ലിനക്സ് കെർണലിനെ മെമ്മറിയിൽ ക്രമീകരിച്ചതിനു ശേഷം നിയന്ത്രണം കെർണലിനു കൈമാറുന്നു. ഇവിടെ നിന്ന് സിസ്റ്റത്തിന്റെ പൂർണ്ണ നിയന്ത്രണം കെർണലിനായിരിക്കും. കെർണലിന്റെ സ്റ്റാർട്ടപ്പ് വിശദമായി അടുത്ത ഭാഗത്തിൽ.

Saturday, February 23, 2013

ഇന്റര്‍ പ്രോസസ്സ് കമ്യൂണിക്കേഷന്‍ - 2 : പൈപ്പുകള്‍

ഒന്നിലധികം പ്രോസസ്സുകള്‍ക്ക് ഒരു കുഴലിലൂടെ എന്നവണ്ണം വിവരങ്ങള്‍ കൈമാറാന്‍ സാധിക്കുന്ന ഒരുപാധിയാണ് പൈപ്പുകള്‍. ഇവക്ക് രണ്ട് അറ്റങ്ങള്‍ ഉണ്ടാകും. ഒരറ്റത്ത് എഴുതപ്പെടുന്ന വിവരങ്ങള്‍ അടുത്ത അറ്റത്തുനിന്ന് വായിച്ചെടുക്കാം. പൈപ്പുകള്‍ കമാന്റ്‌‌ ലൈന്‍ ഇന്റര്‍ഫേസുകളില്‍ നല്കുന്ന സൗകര്യങ്ങള്‍ ചില്ലറയല്ല. ഒരു കമാന്റിന്റെ ഔട്ട്പുട്ട് മറ്റൊരു കമാന്റിന്റെ ഇന്‍പുട്ടായി നല്‍കാന്‍ സാധിക്കുന്നത് വഴി ഒന്നിലധികം ലളിതമായ കമാന്റുകള്‍ ഉപയോഗിച്ച് ഒരു സങ്കീര്‍ണ്ണമായ ജോലി ചെയ്യാന്‍ സാധിക്കുമല്ലോ.

ഒരു പൈപ്പിന്റെ എഴുതാനുള്ള അറ്റത്ത് എഴുതപ്പെടുന്ന കാര്യങ്ങള്‍ മറ്റേ അറ്റത്തുനിന്ന് വായിക്കപ്പെടുന്നത് വരെ കെര്‍ണല്‍ അതിന്റെ മെമ്മറിയില്‍ സൂക്ഷിച്ചു വയ്ക്കുന്നു. ഇങ്ങനെ സൂക്ഷിക്കപ്പെടാന്‍ സാധിക്കുന്ന വിവരങ്ങളുടെ അളവ് സംബന്ധിച്ച് ചില നിബന്ധനകളോ നിയന്ത്രണങ്ങളോ ഉണ്ടെങ്കിലും വിവിധ സിസ്റ്റങ്ങളില്‍ അവ വ്യത്യസ്തമായിരിക്കും. പോസിക്സ് മാനദണ്ഡമനുസരിച്ച് ഇതിന്റെ വലിപ്പം കുറഞ്ഞത് 512 ബൈറ്റുകള്‍ ആയിരിക്കണം എന്നതാണ്. മെമ്മറിയുടെ ലഭ്യത അനുസരിച്ച് കൂടിയ വലിപ്പം എത്രവേണമെങ്കിലും ആകാം. ലിനക്സില്‍ ഇത് 4096 ബൈറ്റുകള്‍ ആണ്. അതായത് ലിനക്സിലെ ഒരു പൈപ്പിന് സംഭരിക്കാന്‍ സാധിക്കുന്ന ഡാറ്റയുടെ പരമാവധി വലിപ്പം 4096 ബൈറ്റുകള്‍ ആണ്. ഇതില്‍ കൂടുതല്‍ ഡാറ്റ കൈമാറ്റം ചെയ്യേണ്ടത് ആവശ്യമാണെങ്കില്‍ എഴുതുന്ന പ്രോസസ്സിന് തുടര്‍ച്ചയായി എഴുതുന്നതില്‍ നിയന്ത്രണങ്ങള്‍ ഒന്നും ഇല്ല. എന്നാല്‍ പൈപ്പ് ഒരിക്കല്‍ നിറഞ്ഞ് കഴിഞ്ഞാല്‍ മറ്റൊരു പ്രോസസ്സ് അതില്‍ നിന്ന് ഡാറ്റ വായിക്കുന്നത് വരെ ഈ എഴുത്തിന് തുടരാന്‍ സാധിക്കുകയില്ല. വായിക്കേണ്ട അറ്റത്ത് നിന്നും ഒരു പ്രോസസ്സ് ഡാറ്റ വായിച്ചെടുത്ത് കഴിഞ്ഞാല്‍ ആ വായിച്ച അത്ര വിവരങ്ങള്‍ പൈപ്പില്‍ നിന്ന് നീക്കം ചെയ്യപ്പെടുന്നു. കൂടുതല്‍ വിവരങ്ങള്‍ എഴുതാന്‍ പ്രോസസ്സ് കാത്തുനില്‍ക്കുന്നുണ്ടെങ്കില്‍ അതിന് ഈ കാലിലായ സ്ഥലം നിറയുന്നത് വരെ വീണ്ടും എഴുതാവുന്നതാണ്.

പൈപ്പിലേക്ക് വിവരങ്ങള്‍ എഴുതുകയോ പൈപ്പില്‍ നിന്ന് വായിക്കുകയോ ചെയ്യുന്ന സമയത്ത് എഴുതാന്‍ സ്ഥലമില്ലാതെ വരിക/വായിക്കാന്‍ പൈപ്പില്‍ വിവരങ്ങള്‍ ഇല്ലാതെ വരിക എന്ന രണ്ട് സാഹചര്യങ്ങള്‍ ഉണ്ടാകാം. ഈ അവസരങ്ങളില്‍ അതിനായി ശ്രമിക്കുന്ന പ്രോസസ്സ് എങ്ങനെ പെരുമാറും എന്നതിന്റെ അടിസ്ഥാനത്തില്‍ ഇന്‍പുട്ട്/ഔട്ട്പുട്ട് പ്രക്രിയകള്‍ രണ്ട് തരത്തില്‍ ആകാം. (ഇവ ബാക്കി ഫയൽ ഇൻപുട്ട്/ഔട്ട്പുട്ടുകൾക്കും ബാധകമാണ്)

1. ബ്ലോക്കിങ്ങ് ഐഒ: പൈപ്പിലേക്ക്/ഫയലിലേക്ക് എഴുതാനോ അവയിൽ നിന്ന് വായിക്കാനോ ശ്രമിക്കുമ്പോൾ വിവരം/സ്ഥലം ലഭ്യമല്ലെങ്കിൽ കെർണൽ ആ പ്രോസസ്സിനെ താൽക്കാലികമായി സസ്പെൻഡ് ചെയ്യുന്നു. പ്രോസസ്സ് വെയിറ്റ് അവസ്ഥയിലേക്ക് പോകും. വിവരങ്ങൾ ലഭ്യമാകുമ്പോൾ പഴയ നിലയിലേക്ക് തിരിച്ച് വരികയും പ്രവർത്തനം തുടരുകയും ചെയ്യും. ശരിക്കും ഈ അവസ്ഥാ മാറ്റങ്ങളൊക്കെ പ്രോസസ്സിന്റെ അറിവോടെ അല്ല നടക്കുന്നത്.

2. നോൺ ബ്ലോക്കിങ്ങ് ഐഒ: ഈ രീതിയിലാണെങ്കിൽ വിവരങ്ങൾ/സ്ഥലം ലഭ്യമല്ലാതെ വരുമ്പോൾ ആ റൈറ്റ്/റീഡ് പ്രോസസ്സ് താൽക്കാലികമായി ആ പ്രവർത്തനം സാധ്യമല്ല എന്ന എറർ കോഡോടെ അവസാനിപ്പിക്കപ്പെടുന്നു. ഇവിടെ പ്രോസസ്സ് വിവര/സ്ഥല ലഭ്യതക്കായി കാത്തു നിൽക്കുന്നില്ല.

ആദ്യമേ‌ തന്നെ സൂചിപ്പിച്ചതുപോലെ പൈപ്പുകള്‍ രണ്ട് വിധത്തിലുണ്ട്. പേരുള്ളവയും ഇല്ലാത്തവയും. ആദ്യം പേരില്ലാത്ത പൈപ്പുകളെക്കുറിച്ച് വിശദീകരിക്കാം.

പേരില്ലാത്ത പൈപ്പുകള്‍ (Unnamed Pipes)
ഇത്തരം പൈപ്പുകളുടെ സവിശേഷത അവയെ  പരസ്പരം ബന്ധപ്പെട്ടിട്ടില്ലാത്ത പ്രോസസ്സുകള്‍ക്ക് ഉപയോഗിക്കാന്‍ സാധിക്കില്ല എന്നതാണ്‌. ഈ പൈപ്പിനെ സൃഷ്ടിക്കുന്ന പ്രോസസ്സിനും അതിന്റെ ചൈല്‍ഡ് പ്രോസസ്സുകള്‍ക്കും മാത്രമേ ഈ പൈപ്പ് ഉപയോഗിക്കാന്‍ സാധിക്കുകയുള്ളു.ഒരു പ്രോസസ്സ് അതിൽ തുറന്ന് വച്ചിരിക്കുന്ന ഫയലുകളൊക്കെ തുറന്നതിനു ശേഷം സൃഷ്ടിക്കപ്പെടുന്ന ചൈൽഡ് പ്രോസസ്സുകൾക്ക് കൂടി ഉപയോഗിക്കാൻ സാധിക്കും എന്നതാണ് ഇതിന്റെ അടിസ്ഥാനം. എന്നാൽ മറ്റൊരു പ്രോസസ്സിന് തുറക്കാൻ പാകത്തിൽ ഈ പൈപ്പുമായി ബന്ധപ്പെട്ട ഫയൽ ഡിസ്കിലോ ഫയൽ സിസ്റ്റത്തിലോ കാണില്ല. അതിനാൽത്തന്നെ അതിനെ സൃഷ്ടിച്ച പ്രോസസ്സിന് മാത്രമേ അതിനെക്കുറിച്ചുള്ള വിവരങ്ങളും ലഭ്യമാവുകയുള്ളു. ഇവയുടെ ഉപയോഗത്തിന് താഴെക്കൊടുത്തിരിക്കുന്ന ഉദാഹരണം നോക്കൂ,

 /* Creating an unnamed pipe */  
 #include <unistd.h>  
 #include <stdio.h>  
   
 int main(void)  
 {  
     int fd[2];  
     pid_t pid;  
   
     char hello[] = "Hello child";  
     char reply[] = "Got it parent..";  
     char buffer[100];  
   
     if (pipe(fd) == -1) {  
         perror("pipe");  
         return;  
     }  
   
     pid = fork();  
     if (pid < 0) {  
         perror("fork");  
         return;  
     }  
   
     if (pid != 0) {  
         printf("\nParent: writing hello to pipe\n");  
         printf("Wrote %d bytes\n",write(fd[1],hello,sizeof(hello)));  
         sleep(2);  
         printf("\nParent: Reading pipe\n");  
         printf("Read %d bytes\n",read(fd[0],buffer,sizeof(buffer)));  
         printf("Data: %s\n\n",buffer);  
         return;  
     } else {  
         sleep(1);  
         printf("\nChild: Reading pipe\n");  
         printf("Read %d bytes\n",read(fd[0],buffer,sizeof(buffer)));  
         printf("Data: %s\n",buffer);  
         printf("\nChild: writing reply to pipe\n");  
         printf("Wrote %d bytes\n",write(fd[1],reply,sizeof(reply)));  
         return;  
     }  
   
     return 0;  
 }  
   

പേരില്ലാത്ത പൈപ്പുകള്‍ സൃഷ്ടിക്കാന്‍ pipe() സിസ്റ്റം  കോളാണ് ഉപയോഗിക്കുന്നത്. ഇതിന്റെ ആര്‍ഗ്യുമെന്റായി നല്‍കുന്നത് രണ്ട് ഫയല്‍ ഡിസ്ക്രിപ്റ്ററുകള്‍ ഉള്ള ഒരു അറേ ആണ്. ഇതില്‍ ഒരെണ്ണം  ആ പൈപ്പിന്റെ റീഡ് എന്‍ഡും  മറ്റേത് റൈറ്റ് എന്‍ഡും  ആണ്. fd[0] പൈപ്പില്‍ നിന്ന് വായിക്കാനും  fd[1] പൈപ്പിലേക്ക് എഴുതാനും  ഉപയോഗിക്കുന്നു. ഒരു ചൈല്‍ഡ് പ്രോസസ്സിന് അതിന്റെ പേരന്റ് പ്രോസസ്സില്‍ തുറക്കപ്പെട്ട എല്ലാ ഫയല്‍ ഡിസ്ക്രിപ്റ്ററുകളും  ലഭ്യമാകും. അതിനാല്‍ പൈപ്പ് സൃഷ്ടിക്കപ്പെടുന്നത് fork നടക്കുന്നതിന്റെ മുന്‍പ് ആയിരിക്കണം. പ്രോഗ്രാമിലെ fork ഉപയോഗത്തെ പറ്റി സംശയമുണ്ടെങ്കില്‍ പ്രോസസ്സ് മാനേജ്മെന്റ് പോസ്റ്റിലെ ഫോര്‍ക്കിന്റെ ഉപയോഗം  പരാമര്‍ശിച്ചിരിക്കുന്ന ലേഖനം  വായിക്കൂ.

പേരുള്ള പൈപ്പുകൾ (Named Pipes) ഈ പൈപ്പുകൾ ഫയൽ സിസ്റ്റത്തിൽ സാധാരണ ഫയലുകളെ പോലെ തന്നെ പ്രവർത്തിക്കുന്നു. അതിനാൽ ഈ ഫയലുകളുടെ പേരറിയുന്ന ഏത് പ്രോസസ്സിനും അതറിയാവുന്ന മറ്റ് പ്രോസസ്സുകളുമായുള്ള ആശയവിനിമയത്തിന് ഈ പൈപ്പ് ഉപയോഗിക്കാം. പേരുള്ള പൈപ്പുകള്‍ സൃഷ്ടിക്കാന്‍ ഉപയോഗിക്കുന്ന സിസ്റ്റം  കോള്‍ mkfifo ആണ്. ഇതിന്റെ ഉപയോഗം  താഴെപ്പറയുന്നത് പോലെ ആണ്,

int mkfifo(const char *pathname, mode_t mode);

ആദ്യത്തെ പരാമീറ്റര്‍ പൈപ്പിന്റെ പാത്ത് ആണ്. ഫയല്‍ സിസ്റ്റത്തിലെ ഏത് പാത്ത് വേണമെങ്കിലും  നല്കാവുന്നതാണ്. ഒരു സാധാരണ ഫയല്‍ നിര്‍മ്മിക്കപ്പെടുമ്പോളുള്ള പരിമിതികള്‍ ഒക്കെ ഇവിടെയും ബാധകമായിരിക്കും. രണ്ടാമത്തെ പരാമീറ്റര്‍ ആ പൈപ്പിന്റെ അനുമതികള്‍ നിര്‍ണ്ണയിക്കുന്നു. (ഫയല്‍ അനുമതികളെക്കുറിച്ചുള്ള പോസ്റ്റ് കാണുക). വിജയകരമായി ഒരു പൈപ്പ് നിര്‍മ്മിക്കപ്പെട്ടാല്‍ ഈ സിസ്റ്റം  കോള്‍ 0 റിട്ടേണ്‍ ചെയ്യുന്നു. വിജയകരമല്ലെങ്കില്‍ -1. ഉദാഹരണത്തിന്

mkfifo("myfifo", 0644);

എന്ന രീതിയില്‍ ഉപയോഗിച്ചാല്‍ അപ്പോളത്തെ വര്‍ക്കിങ്ങ് ഡയറക്ടറിയില്‍ myfifo എന്ന പേരില്‍ ഈ പൈപ്പ് സൃഷ്ടിക്കപ്പെടും. ഉപഭോക്താവിന് വായിക്കാനും  എഴുതാനും  ബാക്കിയുള്ളവര്‍ക്ക് എഴുതാന്‍ മാത്രവും  ഉള്ള അനുമതികളായിരിക്കും  ഇതിന് നല്‍കപ്പെടുക. സൃഷ്ടിക്കപ്പെട്ടതിന് ശേഷം  open, read, write, close സിസ്റ്റം  കോളൂകളുപയോഗിച്ച് മറ്റ് ഫയലുകളെ കൈകാര്യം  ചെയ്യുന്നത് പോലെ തന്നെ ഇവയേയും  കൈകാര്യം  ചെയ്യാവുന്നതാണ്.

Friday, December 07, 2012

ഇന്റര്‍ പ്രോസസ്സ് കമ്യൂണിക്കേഷന്‍ - 1 : സിഗ്നല്‍

സിഗ്നലുകള്‍ ഇന്റര്‍ പ്രോസസ്സ് കമ്മ്യൂണിക്കേഷനില്‍ വളരെ പ്രധാനപ്പെട്ടവയാണെങ്കിലും അവയുടെ സാധ്യതകള്‍ പരിമിതമാണ്. എന്നാല്‍ സിസ്റ്റത്തില്‍ നടക്കുന്ന വിവിധ സംഭവങ്ങളെക്കുറിച്ചുള്ള അറിയിപ്പുകള്‍ വിവിധ പ്രോസസ്സുകള്‍ക്ക് നല്‍കാനും പ്രോസസ്സുകളുടെ പ്രവര്‍ത്തനത്തെ നിയന്ത്രിക്കാനും സിഗ്നലുകള്‍ ഉപയോഗിക്കാന്‍ സാധിക്കും. ഓരോ സിഗ്നലുകള്‍ക്കും ഓരോ അര്‍ഥമാണുള്ളത്. ഈ സിഗ്നലുകളെ തിരിച്ചറിയാന്‍ പോസിക്സ് മാനദണ്ഡത്തില്‍ ഓരോ സംഖ്യകള്‍ അവക്ക് നല്‍കപ്പെട്ടിരിക്കുന്നു. kill സിസ്റ്റം കോള്‍, അല്ലെങ്കില്‍ kill കമാന്റ് തുടങ്ങിയവ വഴി വിവിധ പ്രോസസ്സുകളിലേക്ക് സിഗ്നലുകള്‍ അയക്കാന്‍ സാധിക്കും. പോസിക്സ് നിര്‍വ്വചിച്ചിരിക്കുന്നതില്‍ കൂടുതല്‍ സിഗ്നലുകള്‍ പല സിസ്റ്റങ്ങളിലും ലഭ്യമാണ്. ലഭ്യമായ സിഗ്നലുകളുടെ പട്ടിക കാണുന്നതിന് kill -l എന്ന കമാന്റ് ഉപയോഗിക്കാവുന്നതാണ്.

സിസ്റ്റത്തിലെ ഓരോ പ്രോസസ്സിനും കെര്‍ണലിന്റെ പ്രോസസ്സ് ടേബിളില്‍ ഒരു എന്‍ട്രി ഉണ്ടായിരിക്കും എന്ന് പറഞ്ഞിരുന്നല്ലോ. ഓരോ പ്രോസസ്സിലേക്കും അയക്കപ്പെടുന്ന സിഗ്നലുകള്‍ ഇതില്‍ രേഖപ്പെടുത്തിയിരിക്കുന്നു. ഒരു പ്രോസസ്സിന്റെ പ്രോസസ്സ് ടേബിള്‍ എന്‍ട്രിയില്‍ ഒരു സിഗ്നലിനെ സൂചിപ്പിക്കാന്‍ ഒരു ബിറ്റ് എന്ന കണക്കിലാണ് മെമ്മറി അനുവദിച്ചിരിക്കുക. അതിനാല്‍ത്തന്നെ ഒരേ സിഗ്നല്‍ എത്ര തവണ ഒരു പ്രോസസ്സിലേക്ക് അയക്കപ്പെട്ടു എന്ന് അറീയാന്‍ സാധ്യമല്ല. എന്നാല്‍ ആ പ്രോസസ്സിലേക്ക് ഏതൊക്കെ സിഗ്നല്‍ അയക്കപ്പെട്ടിട്ടുണ്ട് എന്നറിയാന്‍ സാധിക്കും.

ഒരു പ്രോസസ്സ് ഒരു സിഗ്നല്‍ സ്വീകരിച്ച് കഴിഞ്ഞാല്‍ ആ സിഗ്നലിനോട് മൂന്നുതരത്തിലുള്ള പ്രതികരണങ്ങളാണ് സാധ്യമാകുക. ആ സിഗ്നല്‍ കണ്ടില്ലെന്ന് നടിക്കുക (Ignore), ആ സിഗ്നലിനെ കൈകാര്യം ചെയ്യുക (Handle), പ്രോസസ്സ് അവസാനിപ്പിക്കുക (Terminate) എന്നിവയാണ് അവ. എല്ലാ സിഗ്നലുകളെയും കണ്ടില്ലെന്ന് നടിക്കാന്‍ സാധിക്കുകയില്ല. എല്ലാ സിഗ്നലുകളെയും കൈകാര്യം ചെയ്യാനും സാധിക്കില്ല. ഒരു സിഗ്നലിനോട് നാമെഴുതുന്ന ഒരു പ്രോഗ്രാം എങ്ങനെ പ്രതികരിക്കണമെന്ന് നാം പരാമര്‍ശിക്കുന്നില്ലെങ്കില്‍ കെര്‍ണല്‍ മുന്‍കൂട്ടി നിശ്ചയിച്ചിരിക്കുന്ന രീതിയിലുള്ള ഒരു നടപടി എടുക്കുന്നു. ഓരോ സിഗ്നലുകള്‍ക്കും ഈ നടപടി വ്യത്യസ്തമായിരിക്കും. ഒരു സിഗ്നലിലെ നമ്മുടെ പ്രോഗ്രാമില്‍ കൈകാര്യം ചെയ്യുന്നതിനായി ഒരു സിഗ്നല്‍ ഹാന്‍ഡ്‌‌ലര്‍ ഫങ്‌‌ഷന്‍ എഴുതുകയും അതിനെ ആ സിഗ്നലുമായി ബന്ധിപ്പിക്കുകയും ചെയ്യണം. നമ്മുടെ പ്രോഗ്രാം  പിന്നീട് ആ സിഗ്നല്‍ സ്വീകരിക്കുകയാണെങ്കില്‍ ബന്ധപ്പെട്ട ഫങ്ഷന്‍ പ്രവര്‍ത്തിക്കുന്നതായിരിക്കും. എന്നാല്‍ ഇക്കാര്യങ്ങളൊന്നും തന്നെ നാമെഴുതുന്ന പ്രോഗ്രാമിന്റെ നിയന്ത്രണത്തില്‍ വരുന്ന കാര്യങ്ങളല്ല. ഇതൊക്കെ ചെയ്യുന്നത് കെര്‍ണല്‍ നേരിട്ടാണ്. നമ്മുടെ പ്രോസസ്സിന്റെ യു-ഏരിയയില്‍ ആണ് അത് ഓരോ സിഗ്നലിനോടും  എങ്ങനെ പ്രതികരിക്കുന്നു എന്നും സിഗ്നലുകള്‍ കൈകാര്യം ചെയ്യാനുള്ള ഫങ്ങ്ഷനുകള്‍ ഉണ്ടെങ്കില്‍ അവയുടെ വിലാസം രേഖപ്പെടുത്തിയിരിക്കുന്നതും.

ഒരു പ്രോസസ്സിന് അത് ഏതവസ്ഥയില്‍ ആയിരിക്കുമ്പോളും സിഗ്നലുകള്‍ സ്വീകരിക്കാന്‍ സാധിക്കും. എന്നാല്‍ ആ സിഗ്നല്‍ കൈകാര്യം ചെയ്യപ്പെടുന്നത് ആ പ്രോസസ്സിന്റെ അവസ്ഥയില്‍ മാറ്റങ്ങള്‍ വരുമ്പോളാണ്.
  • ഒരു പ്രോസസ്സിന്റെ പ്രവര്‍ത്തനം കെര്‍ണല്‍ സ്പേസില്‍ നിന്ന് യൂസര്‍ സ്പേസിലേക്ക് മാറുക 
  • സ്ലീപ്പ് അവസ്ഥയില്‍ നിന്ന് പ്രോസസ്സ് പ്രവര്‍ത്തിക്കുന്ന അവസ്ഥയിലേക്ക് വരിക 
  • പ്രോസസ്സ് ഷെഡ്യൂള്‍ ചെയ്യപ്പെടുക
തുടങ്ങിയ സാഹചര്യങ്ങളിലാണ് ആ പ്രോസസ്സിലേക്ക് അയക്കപ്പെട്ടിരിക്കുന്ന സിഗ്നലുകളെ കെര്‍ണല്‍ പരിശോധിക്കുകയും ആവശ്യമായ നടപടികള്‍ എടുക്കുകയും ചെയ്യുന്നത്. പ്രോസസ്സിന് കണ്ടില്ലെന്ന് നടിക്കാന്‍ അനുവാദമുള്ള സിഗ്നല്‍ ആണെങ്കില്‍ ആ സിഗ്നലിനെ കൈകാര്യം ചെയ്യാനുള്ള ഫങ്ങ്ഷനുകള്‍ ഒന്നും പ്രോസസ്സ് രെജിസ്റ്റെര്‍ ചെയ്തിട്ടില്ലെങ്കില്‍ പ്രത്യേകിച്ചൊരു നടപടിയും ആവശ്യമില്ല. ആ സിഗ്നല്‍ കൈകാര്യം ചെയ്യപ്പെട്ടു എന്ന് പ്രോസസ്സിന്റെ പ്രോസസ്സ് ടേബിള്‍ എന്‍ട്രിയില്‍ രേഖപ്പെടുത്തുകയേ‌ വേണ്ടൂ. ഇനി പ്രോസസ്സിലേക്ക് അയക്കപ്പെട്ട സിഗ്നലിന്റെ സാമാന്യ പ്രതികരണം പ്രോസസ്സ് അവസാനിപ്പിക്കുക എന്നതാണെങ്കില്‍ കെര്‍ണല്‍ ആ പ്രോസസ്സിന്റെ എക്സിറ്റ് ഹാന്‍ഡ്‌‌ലര്‍ പ്രവര്‍ത്തിപ്പിക്കുകയും ആ പ്രോഗ്രാമിന്റെ പ്രവര്‍ത്തനം അവസാനിപ്പിക്കുകയും ചെയ്യും. ഒരു സിഗ്നലിനെ കൈകാര്യം ചെയ്യാനുള്ള ഫങ്ങ്ഷന്‍ ഒരു പ്രോസസ്സ് രെജിസ്റ്റര്‍ ചെയ്തിട്ടുണ്ടെങ്കില്‍ കാര്യങ്ങള്‍ അല്‍പം കൂടി സങ്കീര്‍ണ്ണമാണ്. എല്ലാ ഫങ്ങ്ഷനുകള്‍ക്കും  പ്രവര്‍ത്തിക്കാന്‍ ഒരു സ്റ്റാക്ക് ആവശ്യമാണ്. പ്രോഗ്രാമില്‍ തന്നെ വിളിക്കപ്പെടുന്ന ഫങ്ങ്ഷന്‍ ആണെങ്കില്‍ ആ ഫങ്ങ്‌‌ഷനായുള്ള സ്റ്റാക്ക് പ്രോസസ്സിന്റെ സ്റ്റാക്ക് സെഗ്‌‌മെന്റില്‍ നിര്‍മ്മിക്കാനുള്ള നിര്‍ദ്ദേശങ്ങള്‍ സി കമ്പൈലര്‍ ആ പ്രോഗ്രാമില്‍ തന്നെ ഉള്‍പ്പെടുത്തിയിരിക്കും. എന്നാല്‍ ഇവിടെ ആ ഫങ്ങ്‌‌ഷനെ വിളിക്കുന്നത് ആ പ്രോസസ്സില്‍ നിന്നല്ല എന്ന കാര്യം ഓര്‍മ്മിക്കുക. ഇവിടെ കെര്‍ണല്‍ ആദ്യം ചെയ്യുന്നത് ആ പ്രോസസ്സിന്റെ യു-ഏരിയയില്‍ നിന്ന് സിഗ്നല്‍ കൈകാര്യം ചെയ്യാനുള്ള ഫങ്ങ്ഷന്റെ വിലാസം കണ്ടെത്തുകയാണ്. പിന്നീട് ആ ഫങ്ങ്ഷന് പ്രവര്‍ത്തിക്കാന്‍ ആവശ്യമായ ഒരു സ്റ്റാക്ക് ഫ്രെയിം ആ പ്രോസസ്സിന്റെ സ്റ്റാക്ക് സെഗ്‌‌മെന്റില്‍ സൃഷ്ടിക്കുന്നു. ആ ഫങ്ങ്‌‌ഷനുള്ള പരാമീറ്ററുകള്‍ ആ സ്റ്റാക്കിലേക്ക് ചേര്‍ക്കുകയും ആ പ്രോസസ്സില്‍ അടുത്തതായി പ്രവര്‍ത്തിക്കേണ്ട നിര്‍ദ്ദേശത്തിന്റെ വിലാസം (ഇത് പ്രോഗ്രാം കൗണ്ടര്‍ എന്നറിയപ്പെടുന്നു) സ്റ്റാക്കിലേക്ക് സിഗ്നല്‍ ഹാന്‍ഡ്‌‌ലര്‍ ഫങ്ങ്ഷന്റെ റിട്ടേണ്‍ അഡ്രസ്സായി ചേര്‍ക്കുകയും ചെയ്യുന്നു. ആ ഫങ്ങ്ഷന്റെ പ്രവര്‍ത്തനം തീരുമ്പോള്‍ പ്രോഗ്രാം  എവിടെനിന്ന് തുടരണം എന്നതാണ് ഫങ്ങ്‌‌ഷന്റെ റിട്ടേണ്‍ അഡ്രസ്സ് എന്നറിയപ്പെടുന്നത്. ഇതിന് ശേഷം ആ ഫങ്ങ്ഷന്റെ സ്റ്റാര്‍ട്ടിങ്ങ് അഡ്രസ്സ് പ്രോഗ്രാം കൗണ്ടറില്‍ എഴുതിയ ശേഷം ആ പ്രോസസ്സിനെ പ്രവര്‍ത്തിക്കാന്‍ അനുവദിക്കുന്നു. ചുരുക്കത്തില്‍ നേരിട്ട് യൂസര്‍ സ്പേസിലേക്ക് മടങ്ങി പ്രവര്‍ത്തനം തുടരേണ്ടിയിരുന്ന പ്രോസസ്സ് ആ ഫങ്ങ്ഷനിലൂടെ കടന്ന് പോകുകയും ആ ഫങ്ങ്ഷന്‍ പൂര്‍ത്തിയാക്കിയ ശേഷം അതിന്റെ പ്രവര്‍ത്തനം തുടരുകയും ചെയ്യും.

ഇതില്‍നിന്ന് മനസ്സിലാക്കാനുള്ള കാര്യം സിഗ്നലുകള്‍ സ്വീകരിക്കുകയോ അവയെ കൈകാര്യം ചെയ്യുകയോ ചെയ്യുന്നത് ഒരു പ്രോസസ്സിന്റെ അധികാര പരിധിയില്‍ ഉള്ള കാര്യമല്ല. അവ നടക്കുന്നത് ആ പ്രോസസ്സ് അറിയുകയും ഇല്ല. ഒരു പ്രോസസ്സ് ഫോര്‍ക്ക് ഉപയോഗിച്ച് അതിന്റെ ചൈല്‍ഡ് പ്രോസസ്സിനെ സൃഷ്ടിക്കുമ്പോള്‍ അത് രെജിസ്റ്റര്‍ ചെയ്തിരുന്ന ഹാന്‍ഡ്‌‌ലര്‍ ഫങ്ങ്ഷനുകള്‍ ഒക്കെ ചൈല്‍ഡ് പ്രോസസ്സിലും അതേ നിലയില്‍ തുടരും. എന്നാല്‍ ചൈല്‍ഡ് പ്രോസസ്സ് സൃഷ്ടിക്കപ്പെടുന്നതിനു മുന്‍പ് പേരന്റ് പ്രോസസ്സ് സ്വീകരിച്ചതും കൈകാര്യം ചെയ്യപ്പെട്ടിട്ടില്ലാത്തതുമായ സിഗ്നലുകള്‍ ഒന്നും ചൈല്‍ഡ് പ്രോസസ്സിന് ബാധകമാകില്ല.

ഒരു പ്രോസസ്സിന് വേറൊരു പ്രോസസ്സിലേക്ക് സിഗ്നല്‍ അയക്കാന്‍ kill() സിസ്റ്റം കോള്‍ ഉപയോഗിക്കാമെന്ന് പറഞ്ഞു. അതേ പ്രോസസ്സിലേക്ക് തന്നെ സിഗ്നല്‍ അയക്കാന്‍ (സ്വയം) ഒരു പ്രോസസ്സിന് raise() എന്ന ഫങ്ങ്ഷന്‍ ഉപയോഗിക്കാവുന്നതാണ്. ഇതല്ലാതെ പ്രത്യേക സാഹചര്യങ്ങളില്‍ പ്രോസസ്സുകള്‍ സിഗ്നലുകള്‍ സ്വീകരിക്കാറുണ്ട്. ഉദാഹരണത്തിന് കമാന്റ് ലൈനില്‍ പ്രവര്‍ത്തിച്ചുകൊണ്ടിരിക്കുന്ന ഒരു പ്രോസസ്സിലേക്ക് ഉപയോക്താവ് കണ്ട്രോള്‍ + സി എന്ന കീബോര്‍ഡ് കോമ്പിനേഷന്‍ ഉപയോഗിക്കുമ്പോള്‍ SIGINT എന്ന സിഗ്നല്‍ അയക്കപ്പെടുന്നു. പ്രോസസ്സ് അതിന്റെ അഡ്രസ്സ് സ്പേസിനു പുറത്തുള്ള ഒരു അഡ്രസ്സിലെ വിവരങ്ങള്‍ വായിക്കാനോ എഴുതാനോ ശ്രമിക്കുമ്പോള്‍ SIGSEGV എന്ന സിഗ്നല്‍, പ്രോസസ്സില്‍ ഒരു സംഖ്യയെ പൂജ്യം കൊണ്ട് ഹരിക്കാന്‍ ശ്രമിച്ചാല്‍ SIGFPE, ഒരു പ്രോസസ്സിന്റെ ചൈല്‍ഡ് പ്രോസസ്സ് പ്രവര്‍ത്തനം  അവസാനിപ്പിച്ചാല്‍ SIGCHILD എന്നിങ്ങനെ. ഇത് കൂടാതെ പോസിക്സ് ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റത്തില്‍ ആപ്ലിക്കേഷന്‍ പ്രോഗ്രാമുകള്‍ക്ക് ലഭ്യമായ ടൈമര്‍/കൗണ്ടര്‍ സര്‍വ്വീസുകള്‍ ഒക്കെ സിഗ്നലുകള്‍ ഉപയോഗപ്പെടുത്തിയാണ് പ്രവര്‍ത്തിക്കുന്നത്.

പോസിക്സില്‍ നിര്‍വ്വചിക്കപ്പെട്ടിരിക്കുന്ന സിഗ്നലുകളുടെ വിശദാംശങ്ങള്‍ ഈ വിക്കിപീഡിയ ലേഖനത്തില്‍ കാണാം. പ്രോസസ്സിലെ സിഗ്നല്‍ ഹാന്‍ഡ്ലിങ്ങിന്റെ വിശദാംശത്തിനും ഓരോ സിഗ്നലും എങ്ങനെ പെരുമാറുന്നു എന്നുമുള്ള വിശദാംശങ്ങള്‍ക്കായി man 7 signal എന്ന് ടെര്‍മിനലില്‍ ടൈപ്പ് ചെയ്ത് നോക്കുക.

കമാന്റ് ലൈനില്‍ നിന്നയക്കപ്പെടുന്ന SIGINT എങ്ങനെ കൈകാര്യം ചെയ്യാം എന്നൊരു ഉദാഹരണം നോക്കാം
 #include <stdio.h>  
 #include <signal.h>  
 #include <unistd.h>  
   
 volatile sig_atomic_t terminated = 0;  
   
 void sigint_handler(int signum)  
 {  
     printf("\nSignal %d received..\n", signum);  
     terminated = 1;  
 }  
   
 int main(void)  
 {  
     unsigned long counter = 0;  
   
     signal(SIGINT, sigint_handler);  
   
     printf("Entering an infinit loop..\n");  
   
     while (!terminated) {  
         counter++;  
         sleep(1);  
         printf("\r%ld seconds without signal..", counter);  
         fflush(stdout);  
     }  
   
     printf("\nLoop terminated\n");  
   
     return 0;  
 }

ഇവിടെ SIGINT എന്ന സിഗ്നല്‍ ഹാന്‍ഡില്‍ ചെയ്യാന്‍ sigint_handler എന്ന ഫങ്ങ്ഷനെ രെജിസ്റ്റര്‍ ചെയ്യുകയാണ് signal ഫങ്ങ്ഷന്‍ ഉപയോഗിച്ച് ചെയ്യുന്നത്. terminated എന്ന വേരിയബിളിന്റെ മൂല്യം പൂജ്യമല്ലാതാകുന്നത് വരെ മെയിന്‍ ഫങ്ങ്ഷനിനെ while ലൂപ്പ് പ്രവര്‍ത്തിച്ച് കൊണ്ടിരിക്കുന്നു. ഇവിടെ terminated എന്ന വേരിയബിളിന്റെ ഡാറ്റ ടൈപ്പ് ശ്രദ്ധിക്കുക. volatile sig_atomic_t എന്ന പ്രത്യേക ഡാറ്റാ ടൈപ്പ് ആണ് ഉപയോഗിച്ചിരിക്കുന്നത്. ഇതിലെ volatile എന്ന് കീവേര്‍ഡ് ആ ചരത്തിന് ചില പ്രത്യേകതകള്‍ നല്‍കുന്നതാണ്. ആ ചരത്തിന്റെ മൂല്യം പ്രോഗ്രാമില്‍ എവിടെ വേണമെങ്കിലും മാറ്റം വരാവുന്നതാണെന്നും അതിനാല്‍ തന്നെ ഒരു രീതിയിലുള്ള ഓപ്‌‌റ്റിമൈസേഷനും ആ വേരിയബിളിന്റെ മേല്‍ നടത്തരുതെന്നും ആ വേരിയബിള്‍ ആവശ്യമാകുമ്പോളൊക്കെ അതിനെ പ്രത്യേകം വായിക്കണം എന്നും സി കമ്പൈലറിനോട് പറയുന്നതാണത്. സിഗ്നലുകള്‍ റേസ് കണ്ടീഷന്‍സ് എന്ന പ്രശ്നത്തില്‍ നിന്ന് മുക്തമല്ലെന്ന് മാത്രമല്ല ആ പ്രശ്നത്തിന്റെ കാഠിന്യം നന്നായി അനുഭവിക്കുന്നവയും ആണ്. സ്വീകരിക്കപ്പെട്ട ഒരു സിഗ്നല്‍ കൈകാര്യം ചെയ്യപ്പെടുന്ന അവസരത്തില്‍ മറ്റൊരു സിഗ്നല്‍ സ്വീകരിക്കപ്പെട്ടാല്‍ സംഭവിക്കാവുന്ന പല പ്രശ്നങ്ങളും ഉണ്ട്. ഉദാഹരണത്തിന് ഒരു സിഗ്നല്‍ എത്ര തവണ പ്രോഗ്രാം കൈകാര്യം ചെയ്തു എന്നറിയാന്‍ ഒരു കൗണ്ടര്‍ ഉപയോഗിക്കുന്നു എന്ന് കരുതുക. ഓരോ കൈകാര്യം ചെയ്യലിലും അതിന്റെ മൂല്യം ഒന്ന് വീതം വര്‍ദ്ധിക്കുകയും ഒരു പ്രത്യേക മൂല്യം എത്തുമ്പോള്‍ ഒരു കാര്യം ചെയ്യേണ്ടതും ആണെന്ന് കരുതൂ. അതായത് ആ കൗണ്ടറിന്റെ മൂല്യം നാലിന്റെ ഗുണിതങ്ങളാകുമ്പോള്‍ ഒരു സന്ദേശം ഉപയോക്താവിനെ കാണിക്കണം. കൗണ്ടറിലെ മൂല്യം 3 ആയിരിക്കുമ്പോള്‍ പ്രോഗ്രാം സിഗ്നല്‍ സ്വീകരിക്കുകയും അതിന്റെ മൂല്യം 4 ആക്കുകയും ചെയ്തു എന്ന് കരുതുക. അതിന്റെ മൂല്യം നാലിന്റെ ഗുണിതമാണോ എന്ന് പരിശോധിക്കാനുള്ള നിര്‍ദ്ദേശത്തിന്റെ തൊട്ട് മുന്‍പേ കെര്‍ണല്‍ ഷെഡ്യൂളിങ്ങ് നടത്തുകയാണെങ്കില്‍ ആ പ്രോസസ്സ് താല്‍ക്കാലികമായി പ്രവര്‍ത്തനം നിര്‍ത്തും. വീണ്ടും പ്രവര്‍ത്തനം തുടങ്ങുന്നതിനു മുന്‍പേ ഒരിക്കല്‍ കൂടി ആ സിഗ്നല്‍ സ്വീകരിക്കപ്പെട്ടാല്‍ വീണ്ടും ആ നിര്‍ദ്ദേശത്തിലെത്തുമ്പോള്‍ ആ കൗണ്ടറിന്റെ മൂല്യം 5 ആയിട്ടുണ്ടാകും. ഷെഡ്യൂളിങ്ങ് നടന്നില്ലെങ്കില്‍ പോലും മൂല്യം വര്‍ദ്ധിപ്പിക്കുന്ന നിര്‍ദ്ദേശം പ്രവര്‍ത്തിക്കുമ്പോള്‍ അടുത്ത സിഗ്നല്‍ വന്നാലും ഈ പ്രശ്നം ഉണ്ടാകാം. sig_atomic_t ആ ചരത്തിന്റെ ഉപയോഗത്തെ ഒരു ആറ്റോമിക് ഓപ്പറേഷന്‍ ആയി നടത്തണം എന്ന് ജിസിസി കമ്പൈലറിനോട് ആവശ്യപ്പെടും. ഒരു പരിധി വരെ പ്രശ്നങ്ങള്‍ ഇതുവഴി പരിഹരിക്കാം. 

ഇനി SIGINT എന്ന സിഗ്നലിനെ കണ്ടില്ലെന്ന് നടിക്കുന്നതെങ്ങനെ എന്ന് നോക്കാം
 #include <stdio.h>  
 #include <signal.h>  
 #include <unistd.h>  
   
 volatile sig_atomic_t terminated = 0;  
   
 int main(void)  
 {  
     unsigned long counter = 0;  
   
     signal(SIGINT, SIG_IGN);  
   
     printf("Entering an infinit loop..\n");  
   
     while (!terminated) {  
         counter++;  
         sleep(1);  
         printf("\r%ld seconds without signal..", counter);  
         fflush(stdout);  
     }  
   
     printf("\nLoop terminated\n");  
   
     return 0;  
 }  
ഇവിടെ SIG_IGN എന്നതാണ് signal ഫങ്ങ്ഷന്റെ രണ്ടാമത്തെ ആര്‍ഗ്യുമെന്റ്. പരാമര്‍ശിക്കപ്പെട്ട സിഗ്നലിനെ ഇഗ്നോര്‍ ചെയ്യുക എന്നതാണ് ഇതിന്റെ അര്‍ഥം. ഈ പ്രോഗ്രാം പ്രവര്‍ത്തിക്കുമ്പോള്‍ CTRL+C അമര്‍ത്തിയാല്‍ ഒന്നും സംഭവിക്കില്ലെന്ന് കാണാം. എന്നാല്‍ ആദ്യത്തെ പ്രോഗ്രാം അതോടെ ലൂപ്പില്‍ നിന്ന് പുറത്ത് വരുമായിരുന്നു. ഇനി ഈ പ്രോഗ്രാമിന്റെ പ്രവര്‍ത്തനം അവസാനിപ്പിക്കാന്‍ ഒരു പുതിയ ടെര്‍മിനല്‍ തുറന്ന് ps -e കമാന്റ് ഉപയോഗിച്ച് അതിന്റെ പിഐഡി കണ്ടുപിടിക്കുക. അതിന് ശേഷം kill -9 <pid> ഉപയോഗിച്ച് SIGKILL എന്ന സിഗ്നല്‍ അതിലേക്ക് അയക്കാം. അപ്പോള്‍ ആ പ്രോസസ്സ് killed എന്ന് ടെര്‍മിനലില്‍ കാണിക്കും. SIGKILL സിഗ്നലിന്റെ സംഖ്യ 9 ആണ്. kill -l വഴി വിവിധ സിഗ്നലുകളുടെ സംഖ്യകള്‍ കണ്ട് പിടിച്ച് 9 നു പകരം ഉപയോഗിച്ച് എന്ത് സംഭവിക്കുന്നു എന്ന് നോക്കൂ.. 

പോസിക്സ് സിഗ്നലുകളെ വികസിപ്പിച്ചാണ് ജിറ്റികെ പോലെയുള്ള യുഐ ലൈബ്രറികള്‍ ഈവന്റ് മെക്കാനിസം പ്രായോഗികമാക്കിയതെന്ന് പറയപ്പെടുന്നു..

ഇന്റര്‍ പ്രോസസ്സ് കമ്യൂണിക്കേഷന്‍

എല്ലാ മള്‍ട്ടി പ്രോസസ്സ് ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റങ്ങളിലും ഒന്നിലധികം പ്രോസസ്സുകള്‍ ഒരേ സമയത്ത് പ്രവര്‍ത്തിക്കുന്നുണ്ടാകും. ചില അവസരങ്ങളില്‍ ഈ പ്രോസസ്സുകള്‍ക്ക് പരസ്പരം വിവരങ്ങള്‍ കൈമാറേണ്ട ആവശ്യം വരും. ഇങ്ങനെയുള്ള വിവര കൈമാറ്റങ്ങളെ ഇന്റര്‍ പ്രോസസ്സ് കമ്യൂണിക്കേഷന്‍ എന്ന് പറയുന്നു. ഇതിന് വിവിധ മാര്‍ഗ്ഗങ്ങള്‍ ഉണ്ട്. യൂണിക്സ് ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റത്തിന്റെ ആദ്യകാല കമേര്‍ഷ്യല്‍ പതിപ്പുകളില്‍ ഒന്നായ സിസ്റ്റം വി (System V - വായിക്കുന്നത് സിസ്റ്റം ഫൈവ്) ആണ് ഇക്കാര്യത്തില്‍ അടിസ്ഥാന മാനദണ്ഡമായി പരിഗണിക്കപ്പെടുന്നവയില്‍ ഒന്ന്. SysV യില്‍ ഉണ്ടായിരുന്ന ഐ പി സി മെക്കാനിസങ്ങളെ SysV IPC Mechanisms എന്ന് വിളിക്കുന്നു. അതില്‍ ഉണ്ടായിരുന്നതിലധികം  സംവിധാനങ്ങള്‍ ഇന്ന് ലിനക്സിലടക്കം ഉണ്ട്.

രണ്ട് പ്രോഗ്രാമുകള്‍ക്ക് പരസ്പരം  വിവരങ്ങള്‍ കൈമാറാന്‍ അവയെ വെറുതെ ഒരു ഫയലില്‍ എഴുതി അടുത്ത പ്രോഗ്രാമിന് വായിക്കാനായി കൊടുക്കാവുന്നതാണ്. എന്നാല്‍ ഇതിനൊന്നും  പൊതുവായ മാനദണ്ഡങ്ങള്‍ ഇല്ല. കൂടാതെ ഒരു പ്രോസസ്സിനോട്‌ ഒരു പ്രത്യേക രീതിയില്‍ പെരുമാറാന്‍ ആവശ്യപ്പെടുക, സിസ്റ്റത്തില്‍ നടന്നിരിക്കുന്ന വിവിധ സംഭവങ്ങളെപ്പറ്റി അവക്ക് പൊതുവായ വിവരങ്ങള്‍ കൈമാറുക, ഒരു പ്രത്യേക സാഹചര്യം  ഉണ്ടാകുന്നത് വരെ കാത്തിരിക്കാന്‍ ആവശ്യപ്പെടുക തുടങ്ങി വിവിധ കാര്യങ്ങള്‍ ചെയ്യേണ്ടതായി വരും. ലഭ്യമായ വിവിധ ഐപിസി മെക്കാനിസങ്ങള്‍ താഴെ ചേര്‍ക്കുന്നു. ഇവയെപ്പറ്റി വിശദമായി ഓരോ പോസ്റ്റുകള്‍ ഇടാം.
  1. പൈപ്പുകള്‍ (pipe)
    1. പേരുള്ളവ (named pipes)
    2. പേരില്ലാത്തവ (unnamed pipes)
  2. സോക്കറ്റുകള്‍ (socket)
  3. സിഗ്നലുകള്‍ (signal)
  4. മെസ്സേജ് ക്യൂ (message queue)
  5. ഷെയേര്‍ഡ് മെമ്മറി (shared memory)
  6. സെമാഫോറുകള്‍ (semaphore)
പൈപ്പുകള്‍
വെള്ളവും മറ്റും  കൊണ്ടുപോകുന്ന പൈപ്പുകള്‍ പോലെ തന്നെയാണ് ഇവയുടെ പ്രവര്‍ത്തനം. ഇവക്ക് രണ്ട് അഗ്രങ്ങള്‍ ഉണ്ടായിരിക്കും. ഒരു വശത്തുകൂടി പോകുന്ന വിവരങ്ങള്‍ മറുവശത്ത് ലഭ്യമാകുന്നു. പേരുള്ള പൈപ്പുകള്‍ ആ പേര് അറിയാവുന്ന പ്രോസസ്സുകള്‍ക്ക് എല്ലാം  ഉപയോഗിക്കാം. എന്നാല്‍ പേരില്ലാത്തവ അതിനെ നിര്‍മ്മിച്ച പ്രോസസ്സിനും അതിന്റെ ചൈല്‍ഡ് പ്രോസസ്സുകള്‍ക്കും  മാത്രമേ ലഭ്യമാവുകയുള്ളു.

സോക്കറ്റുകള്‍
ബിഎസ്‌‌ഡി യൂണിക്സില്‍ ആണ് സോക്കറ്റുകള്‍ ആദ്യമായി വന്നത്. ഇവയൂടെ ഉപയോഗം  കമ്പ്യൂട്ടറുകള്‍ തമ്മില്‍ നെറ്റ്‌‌വര്‍ക്ക് ചെയ്യുന്നതില്‍ ആണ്. ഒരു സോക്കറ്റിനെ വിവിധ വയറുകള്‍ ഘടിപ്പിച്ച് വയ്ക്കാവുന്ന ഒരു പ്ലഗ്ഗുമായി താരതമ്യം ചെയ്യാം. ഒരേ കമ്പ്യൂട്ടറിലെ വിവിധ പ്രോഗ്രാമുകള്‍ക്ക് പരസ്പരം സംവദിക്കാന്‍ സോക്കറ്റുകള്‍ ഉപയോഗിക്കാവുന്നതാണ്. എന്നാല്‍ ഇതിന് കെര്‍ണലിലെ നെറ്റ്‌‌വര്‍ക്കിങ്ങ് ഭാഗത്തിന്റെ പിന്‍തുണ ആവശ്യമാണ്.

സിഗ്നലുകള്‍
സിഗ്നലുകള്‍ വഴി പ്രോസസ്സുകള്‍ക്ക് പരസ്പരം വിവരങ്ങള്‍കൈമാറാന്‍ സാധിക്കുകയില്ല. എന്നാല്‍ വിവിധ സാഹചര്യങ്ങളെക്കുറിച്ച് മറ്റ് പ്രോസസ്സുകള്‍ക്ക് അറിയിപ്പ് കൊടുക്കാന്‍ സിഗ്നലുകള്‍ വഴി സാധിക്കും. ഒരു പ്രോഗ്രാമിന്റെ വിവിധ അവസ്ഥകളെക്കുറിച്ച് ആ പ്രോഗ്രാമിനെ അറിയിക്കാന്‍ കെര്‍ണലിനും സിഗ്നലുകള്‍ വഴി സാധിക്കും.

മെസ്സേജ് ക്യൂ
അധികം വലിപ്പമില്ലാത്ത വിവരങ്ങള്‍ പ്രോസസ്സുകള്‍ക്ക് പരസ്പരം കൈമാറ്റം ചെയ്യാന്‍ മെസ്സേജ് ക്യൂ വഴി സാധിക്കും. പ്രോസസ്സുകള്‍ ക്യൂവിലേക്ക് മെസ്സേജുകള്‍ അയക്കുകയും ക്യൂവില്‍ നിന്ന് മെസ്സേജുകള്‍ സ്വീകരിക്കുകയും ചെയ്യും.

ഷെയേര്‍ഡ് മെമ്മറി
പ്രധാന മെമ്മറിയിലെ ഒരു ഭാഗം ഒന്നോ അതിലധികമോ പ്രോസസ്സുകള്‍ പങ്കിട്ട് ഉപയോഗിക്കുന്ന രീതിയിലാണ് ഇതിന്റെ രൂപകല്‍പ്പന. ഇത് വിവരങ്ങള്‍ പരസ്പരം കൈമാറാന്‍ ഏറ്റവും വേഗതയുള്ള രീതിയാണ്.

സെമാഫോറുകള്‍
ഒരു പൊതുവായ വിഭവം വിവിധ പ്രോസസ്സുകള്‍ക്ക് ഒരേ സമയം ഉപയോഗിക്കേണ്ട അവസ്ഥയുണ്ടായാല്‍ ഒന്നിനു പുറകെ ഒന്നായി അവയ്ക്ക് ആ വിഭവത്തെ ഉപയോഗിക്കാനുള്ള അവസരം കൊടുക്കുന്നതിനുവേണ്ടിയുള്ള ഒരു സംവിധാനമാണിത്. ഉപയോഗിക്കേണ്ടിവരുന്ന ഒരു വിഭവത്തെ മറ്റൊരു പ്രോസസ്സ് ഉപയോഗിക്കുന്നുണ്ടോ എന്ന് പരിശോധിക്കാനും പ്രോസസ്സുകള്‍ക്ക് ഇവ ഉപയോഗിക്കാം. ബൈനറി സെമാഫോര്‍, കൗണ്ടിങ്ങ് സെമാഫോര്‍ എന്ന് രണ്ട്‌ തരത്തിലുള്ള സെമാഫോറുകള്‍ ഉണ്ട്.

ലിനക്സ് അധിഷ്ഠിത സിസ്റ്റങ്ങള്‍ ഉപയോഗിക്കുന്നവര്‍ക്ക്  ipcs കമാന്റ് ഉപയോഗിച്ച് സിസ്റ്റത്തില്‍ വിവിധ പ്രോസസ്സുകള്‍ ഉപയോഗിച്ചുകൊണ്ടിരിക്കുന്ന ഐ പി സി മെക്കാനിസങ്ങളെക്കുറിച്ചുള്ള വിവരങ്ങള്‍ കാണാന്‍ സാധിക്കും. ഈ കമാന്റിന്റെ കൂടുതല്‍ വിവരങ്ങള്‍ക്ക് man ipcs ഉപയോഗിക്കുക.

മുകളില്‍ പരാമര്‍ശിച്ച ഐപിസി മെക്കാനിസങ്ങളില്‍ മെസ്സേജ് ക്യൂ, ഷെയേര്‍ഡ് മെമ്മറി, സെമാഫോറുകള്‍ എന്നിവ സിസ്റ്റം വി ഐപിസി മെക്കാനിസങ്ങളാണ്. സിഗ്നലുകള്‍, പൈപ്പുകള്‍ എന്നിവ പോസിക്സും സോക്കറ്റുകള്‍ ബിഎസ്ഡി സ്റ്റാന്‍ഡേര്‍ഡും ആണ്. ലിനക്സ് പിന്‍തുടരുന്നത് പോസിക്സ് മാനദണ്ഡമാണ്. സിസ്റ്റം വി ഐപിസി മെക്കാനിസങ്ങളെ പൂര്‍ണ്ണമായും പോസിക്സ് നിര്‍വ്വചിക്കുന്നില്ലെങ്കിലും ഇവയെല്ലാം ലിനക്സില്‍ ലഭ്യമാണ്. ഇതില്‍ സോക്കറ്റുകള്‍ വളരെ വിശാലമായ ഒരു വിഷയമായതിനാല്‍ അവയെ മാത്രമായി മറ്റൊരു വിഭാഗത്തില്‍ പരിചയപ്പെടാം.

Wednesday, October 24, 2012

പ്രോഗ്രാം, പ്രോസസ്സ് - 7

പ്രോസസ്സുകളെക്കുറിച്ചുള്ള വിവരങ്ങള്‍ രണ്ട് വിഭാഗങ്ങളിലായി ആണ് സൂക്ഷിക്കപ്പെട്ടിരിക്കുന്നത്. പ്രോസസ്സ് ടേബിളും യു-ഏരിയയും. പ്രോസസ്സിനെക്കുറിച്ച് കെര്‍ണലിന് ആവശ്യമുള്ള വിവരങ്ങള്‍ പ്രോസസ്സ് ടേബിളില്‍ സൂക്ഷിച്ചിരിക്കും. പ്രോസസ്സിന് തന്നെ ആവശ്യമുള്ള വിവരങ്ങള്‍ യു-ഏരിയയിലും സൂക്ഷിച്ചിരിക്കും.

പ്രോസസ്സ് ടേബിള്‍ എന്‍ട്രി
കെര്‍ണല്‍ സൂക്ഷിക്കുന്ന പ്രോസസ്സുകളുടെ പട്ടികയാണ് പ്രോസസ്സ് ടേബിള്‍. കെര്‍ണല്‍ എങ്ങനെയാണ് പ്രോസസ്സുകളെ കൈകാര്യം ചെയ്യുന്നത് എന്ന് മനസ്സിലാക്കാന്‍ പ്രോസസ്സ് ടേബിളിനെക്കുറിച്ചൂള്ള വിവരങ്ങള്‍ സഹായകമായിരിക്കും.

പ്രോസസ്സ് ടേബിള്‍ ഒരു സര്‍ക്കുലാര്‍ ഡബ്ലി ലിങ്ക്ഡ് ലിസ്റ്റ് ആണ്. (Circular Doubly Linked List). ഇതില്‍ ഏത് പ്രോസസ്സിന്റെ എന്‍ട്രിയില്‍ നിന്ന് ആരംഭിച്ചാലും മുന്നിലേക്കോ പിന്നിലേക്കോ പോയി എല്ലാ പ്രോസസ്സുകളുടെയും  എന്‍ട്രികളിലൂടെ പോയി വരാന്‍ സാധിക്കും. ഒരു പ്രോസസ്സിന്റെ പ്രോസസ്സ് ടേബിള്‍ എന്‍ട്രിയില്‍ ഉള്ള വിവരങ്ങളില്‍ ചിലത് താഴെക്കൊടുക്കുന്നു.
1.പ്രോസസ്സിന്റെ അവസ്ഥ. യൂണിക്സിലെ വിവിധ പ്രോസസ്സ് അവസ്ഥകള്‍ വിശദമാക്കുന്ന ചിത്രം താഴെക്കൊടുത്തിരിക്കുന്നു.
2. പ്രോസസ്സ് ഐഡി
3. വിവിധ യൂസര്‍ ഐഡികള്‍ - ഇവ ഉപയോഗിച്ചാണ് ഒരു പ്രോസസ്സിനുള്ള അനുമതികള്‍ തീരുമാനിക്കപ്പെടുന്നത്.
4. പ്രോസസ്സിലും ഷെയേര്‍ഡ് ലൈബ്രറികളിലുമായി ഉള്ള ടെക്സ്റ്റ് സെഗ്‌‌മെന്റുകളിലേക്കുള്ള പോയിന്ററുകള്‍.
5. മെമ്മറി മാനേജ്‌‌മെന്റ് ആവശ്യങ്ങള്‍ക്കായി പേജ് ടേബിളിലേക്കുള്ള പോയിന്ററുകള്‍.
6. ഷെഡ്യൂളിങ്ങിന് ആവശ്യമായ വിവരങ്ങള്‍. ലിനക്സ് സിസ്റ്റങ്ങളില്‍ പ്രോസസ്സുകള്‍ക്ക് 'നൈസ് വാല്യു' എന്നറിയപ്പെടുന്ന മൂല്യങ്ങള്‍ നല്‍കിയിരിക്കും. പ്രോസസ്സ് ഷെഡ്യൂളിങ്ങിന്റെ സമയത്ത് ഏതൊക്കെ പ്രോസസ്സുകള്‍ക്ക് പ്രാധാന്യം നല്‍കണം എന്ന് തീരുമാനിക്കപ്പെടുന്നത് ഈ മൂല്യത്തിന്റെ അടിസ്ഥാനത്തിലാണ്.
7. വിവിധ ടൈമറുകള്‍. ഓരോ പ്രോസസ്സിനും പ്രവര്‍ത്തിക്കാന്‍ സി പി യു വില്‍ സമയ പരിധികള്‍ തീരുമാനിക്കപ്പെട്ടിരിക്കും. ഈ പരിധികള്‍ പാലിക്കാനും പ്രോസസ്സ് എത്ര സമയം ഏതൊക്കെ മോഡില്‍ പ്രവര്‍ത്തിച്ചു എന്നൊക്കെ കണക്കാക്കാനും ഈ ടൈമറുകള്‍ ഉപയോഗിക്കപ്പെടുന്നു.
8. പ്രോസസ്സിന്റെ യു-ഏരിയയിലേക്കുള്ള പോയിന്റര്‍.

യു-ഏരിയ
പ്രോസസ്സിന്റെ യു-ഏരിയയില്‍ ഉള്‍പ്പെടുത്തിയിരിക്കുന്ന കാര്യങ്ങള്‍ ചുവടെ ചേര്‍ക്കുന്നു.
1. റിയല്‍ യൂസര്‍ ഐഡി, എഫക്റ്റീവ് യൂസര്‍ ഐഡി.
2. പ്രോഗ്രാമിന്റെ വര്‍ക്കിങ്ങ് ഡയറക്ടറി (ഒരു പ്രോഗ്രാം പ്രവര്‍ത്തിക്കുന്നത് ഒരു സമയത്ത് ഫയല്‍ സിസ്റ്റത്തിലെ ഏതെങ്കിലും  ഒരു ഡയറക്ടറിയില്‍ ആയിരിക്കും. ഇതിന് പ്രോഗ്രാമുമായി നേരിട്ട് ബന്ധമൊന്നുമില്ലെങ്കിലും ആ ഡയറക്ടറിയില്‍ ഉള്ള ഫയലുകള്‍ ഉപയോഗിക്കാന്‍ മുഴുവന്‍ പാത്ത് നല്‍കാതെ ഫയലിന്റെ പേര് മാത്രം ഉപയോഗിച്ചാല്‍ മതിയാകും)
3. യൂസര്‍ മോഡിലും  കെര്‍ണല്‍ മോഡിലുമായി പ്രോഗ്രാം  ചെലവിട്ട സമയം കണക്കാക്കുന്നതിനായുള്ള ടൈമറുകള്‍.
4. പ്രോഗ്രാം സിഗ്നലുകളോട് എങ്ങനെ പ്രതികരിക്കണം എന്നതിനെ സംബന്ധിച്ച വിവരങ്ങള്‍.
5. പ്രോഗ്രാമുമായി ബന്ധപ്പെട്ടിരിക്കുന്ന കണ്ട്രോളിങ്ങ് ടെര്‍മിനലിനെ സംബന്ധിച്ച വിവരങ്ങള്‍.
6. പ്രോഗ്രാം നടത്തിയ സിസ്റ്റം കോളൂകളെ സംബന്ധിച്ച വിവരങ്ങള്‍.
7. യൂസര്‍ ഫയല്‍ ഡിസ്ക്രിപ്റ്റര്‍ ടേബിള്‍ - ഒരു പ്രോഗ്രാം തുറക്കുന്ന ഫയലുകളുടെ ഡിസ്ക്രിപ്റ്ററുകളുടെ പട്ടിക.
8. ഫയല്‍ സിസ്റ്റത്തെയും പ്രോസസ്സ് എന്‍വയോണ്‍മെന്റിനെയും സംബന്ധിച്ച വിവരങ്ങള്‍യ്

യൂസര്‍ ഐഡികള്‍
ഫയലുകള്‍ക്ക് ഉള്ളത് പോലെ തന്നെ പ്രോസസ്സുകള്‍ക്കും യൂസറും ഗ്രൂപ്പും ഒക്കെ ഉണ്ട്. ഇത് കൂടാതെ സെഷനും. പ്രോസസ്സുകള്‍ക്കുള്ള വിവിധ യൂസര്‍/ഗ്രൂപ്പ് ഐഡികള്‍ എന്നിവ ചുവടെ. സിസ്റ്റത്തില്‍ ഉള്ള ഓരോ ഉപയോക്താവിന്റെയും ഗ്രൂപ്പിന്റെയും പേരുകള്‍ ഒരു യൂസര്‍ ഐഡിയും ഗ്രൂപ്പ് ഐഡിയും ആയി ബന്ധപ്പെട്ടിരിക്കുന്നു. എല്ലാ സമയത്തും മുഴുവന്‍ പേരും ഉപയോഗിക്കാനുള്ള വിഷമം പരിഗണിച്ചാണ് ഓരോ പേരുകളുമായി ബന്ധപ്പെട്ട് സംഘ്യകള്‍ നല്‍കിയിരിക്കുന്നത്. ഇതിനെപ്പറ്റിയുള്ള വിവരങ്ങള്‍ അടങ്ങിയിരിക്കുന്നത് /etc/passwd, /etc/group എന്നീ ഫയലുകളില്‍ ആണ് ഉണ്ടായിരിക്കുക.

റിയല്‍ യൂസര്‍ ഐഡി
ഇത് ഒരു പ്രോസസ്സ് തുടങ്ങിവച്ച ഉപയോക്താവിന്റെ ഐഡി ആയിരിക്കും. ഒരു പ്രോസസ്സ് ആരംഭിച്ച ശേഷം സെറ്റ്‌‌യുഐഡി വഴി അതിന്റെ യൂസര്‍ ഐഡി മാറ്റിയേക്കാം. എന്നാലും റിയല്‍ യൂസര്‍ ഐഡി പഴയത് തന്നെ ആയിരിക്കും. ഈ പ്രോസസ്സ് ഉണ്ടാക്കുന്ന ഫയലുകള്‍ക്കോ പ്രോസസ്സിന്റെ അനുമതികള്‍ക്കോ റിയല്‍ യൂസര്‍ ഐഡി ഉപയോഗിക്കാറില്ല. എന്നാല്‍ മറ്റ് പ്രോസസ്സുകള്‍ക്ക് സിഗ്നലുകള്‍ അയക്കുമ്പോള്‍ പരിഗണിക്കുന്നത് റിയല്‍ യൂസര്‍ ഐഡി ആണ്‍. സൂപ്പര്‍യൂസര്‍ അനുമതികളില്ലാത്ത ഒരു പ്രോസസ്സിന് അതിന്റെ റിയല്‍ യൂസര്‍ ഐഡി തന്നെയുള്ള പ്രോസസ്സുകള്‍ക്കേ സിഗ്നലുകള്‍ അയക്കാന്‍ സാധിക്കുകയുള്ളു.

എഫക്റ്റീവ് യൂസര്‍ ഐഡി
ഒരു പ്രോസസ്സ് സൃഷ്ടിക്കപ്പെട്ട ശേഷം സെറ്റ്‌‌യുഐഡി ഉപയോഗിച്ച് ആ പ്രോസസ്സിന്റെ എഫക്റ്റീവ് യൂസര്‍ ഐഡി റിയല്‍ യൂസര്‍ ഐഡിയില്‍ നിന്ന് മാറ്റാന്‍ സാധിക്കും. ഒരു പ്രോസസ്സ് ഫയലുകള്‍ നിര്‍മ്മിക്കുകയോ ഏതെങ്കിലും  ഒരു റിസോഴ്സ് ഉപയോഗിക്കാന്‍ ശ്രമിക്കുകയോ ചെയ്യുമ്പോള്‍ ആ പ്രോസസ്സിന്റെ എഫക്റ്റീവ് യൂസര്‍ ഐഡി ആണ് പരിഗണിക്കപ്പെടുക.

ഗ്രൂപ്പ് ഐഡികളും മേല്‍പ്പറഞ്ഞത് പോലെ തന്നെ. യൂസറിന് പകരം യൂസര്‍ ഉള്‍പ്പെടുന്ന ഗ്രൂപ്പിന്റെ ഐഡി ആയിരിക്കും പരിഗണിക്കപ്പെടുക. താഴെക്കൊടുത്തിരിക്കുന്ന പ്രോഗ്രാം പ്രോസസ്സിന്റെ യൂസര്‍ ഐഡി, ഗ്രൂപ്പ് ഐഡി തുടങ്ങിയവ കാണിച്ചു തരും. sudo ഉപയോഗിക്കാതെ റണ്‍ ചെയ്താല്‍ setuid പ്രവര്‍ത്തിക്കില്ല. 65534 nobody എന്ന യൂസറിന്റെ ഐഡി ആണ്. ലഭ്യമായ യൂസര്‍ ഐഡികള്‍ക്കായി /etc/passwd ഫയല്‍ തുറന്ന് നോക്കുക. സെറ്റ്‌‌യുഐഡി റിയല്‍ യൂസര്‍ ഐഡി മാറ്റുന്നില്ല എന്ന് ഈ പ്രോഗ്രാം  പ്രവര്‍ത്തിക്കുമ്പോള്‍ മനസ്സിലാക്കാം.

 #include <stdio.h>  
 #include <unistd.h>  
   
 int main(void)   
 {  
     printf("The real user of this process has ID %d\n",getuid());  
     printf("The effective user of this process has ID %d\n",geteuid());  
     printf("The real user group ID for this process is %d\n",getgid());  
     printf("The effective user group for this process is %d\n",getegid());  
   
     setuid(65534);  
   
     printf("The real user of this process has ID %d\n",getuid());  
     printf("The effective user of this process has ID %d\n",geteuid());  
     printf("The real user group ID for this process is %d\n",getgid());  
     printf("The effective user group for this process is %d\n",getegid());  
   
     return 0;  
 }  

പ്രോസസ്സ് സെഷന്‍
എല്ലാ പ്രോസസ്സുകളും  ഒരു പ്രോസസ്സ് സെഷന്റെ ഭാഗമായിരിക്കും. മിക്കവാറും സിസ്റ്റം പ്രവര്‍ത്തിച്ച് തുടങ്ങുമ്പോള്‍ ഉള്ള ലോഗിന്‍ പ്രോസസ്സ് ആയിരിക്കും ഒരു സെഷന്‍ ആരംഭിക്കുക. അതിന്റെ ചൈല്‍ഡ് പ്രോസസ്സുകള്‍ ഒക്കെ ആ സെഷനില്‍ ആയിരിക്കും. ഒരു സെഷനിലെ ആദ്യത്തെ പ്രോസസ്സ് ആണ് സെഷന്‍ ലീഡര്‍ എന്നറിയപ്പെടുന്നത്. സെഷന്‍ ഐഡി സെഷന്‍ ലീഡറിന്റെ പിഐഡി ആയിരിക്കും. എല്ലാ പ്രോസസ്സ് സെഷനുകള്‍ക്കും ഒരു കണ്ട്രോളിങ്ങ് റ്റിറ്റിവൈ ഉണ്ടായിരിക്കും. ഇതിനെ ടെര്‍മിനല്‍ എന്ന് വിളിക്കാം. ആദ്യകാലത്ത് ഒരു പ്രധാന കമ്പ്യൂട്ടറുമായി ഘടിപ്പിക്കപ്പെട്ടിരുന്ന ഉപകരണങ്ങളായിരുന്നു ടെര്‍മിനലുകള്‍. ഒന്നിലധികം ടെര്‍മിനലുകള്‍ ഉപയോഗിച്ച് ഒന്നിലധികം ഉപയോക്താക്കള്‍ ഒരേ കമ്പ്യൂട്ടര്‍ തന്നെ പ്രവര്‍ത്തിപ്പിച്ചിരുന്നു. ps -e കമാന്റ് ഉപയോഗിച്ച് സിസ്റ്റത്തിലെ പ്രോസസ്സുകളും അവയുടെ TTY ഉം  കാണാന്‍ സാധിക്കും. ചില പ്രോസസ്സുകള്‍ക്ക് കണ്ട്രോളിങ്ങ് ടെര്‍മിനല്‍ കാണില്ല. അവയെക്കുറിച്ച് പിന്നീട് പറയാം. താഴെക്കൊടുത്തിരിക്കുന്ന പ്രോഗ്രാം അതിന്റെ സെഷന്‍ ഐഡി കാട്ടിത്തരും. അതിന് ശേഷം ps കമാന്റ് ഉപയോഗിച്ചാല്‍ ആ പ്രോഗ്രാമിനെ പ്രവര്‍ത്തിപ്പിച്ച ഷെല്ലിന്റെ പിഐഡി തന്നെയാണ് സെഷന്‍ ഐഡി എന്ന് കാണാം. അതിന്റെ കാരണം ഊഹിക്കാമല്ലോ..

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
   
 int main(void)  
 {  
     printf("My session id is: %d\n", getsid(getpid()));  
   
     return 0;  
 }  

ഇന്റര്‍ പ്രോസസ്സ് കമ്യൂണിക്കേഷന്‍, സിഗ്നലുകള്‍ എന്നിവയെപ്പറ്റി അടുത്ത പോസ്റ്റ്..

Sunday, October 14, 2012

പ്രോഗ്രാം, പ്രോസസ്സ് - 6

യൂണിക്സ്/ലിനക്സ് സിസ്റ്റങ്ങളില്‍ ബൂട്ടിങ്ങിന് ശേഷം കെര്‍ണല്‍ തന്നെ നിര്‍മിക്കുന്ന പ്രോസസ്സാണ് ഇനിറ്റ്. ഇനിറ്റ് വരെ സിസ്റ്റം കെര്‍ണല്‍ മോഡിലായിരിക്കും. ഇനിറ്റ് പ്രവര്‍ത്തനമാരംഭിക്കുന്നതോടെ സിസ്റ്റം യൂസര്‍മോഡിലേക്ക് മാറുന്നു. ഇനിറ്റിന്റെ വകഭേദങ്ങളും  പ്രവര്‍ത്തനവും ഒരു പോസ്റ്റി വിശദീകരിക്കാം. ഇനിറ്റിനു ശേഷമുള്ള  എല്ലാ പ്രോസസ്സുകളും ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിച്ച് സൃഷ്ടിക്കപ്പെടുന്നവയാണ്. ഇനിറ്റ് പ്രോസസ്സ് ഷെല്ലുകളോ ഗ്രാഫിക്കല്‍ യൂസര്‍ ഇന്റര്‍ഫേസുകളോ എക്സിക്യൂട്ട് ചെയ്യുന്നു. അപ്പോള്‍ ഉപഭോക്താവിന് കമ്പ്യൂട്ടര്‍ പ്രവര്‍ത്തിപ്പിക്കാനുള്ള ഉപാധികള്‍ ലഭ്യമാകും. ഉപഭോക്താവ് കമാന്റുകളോ മൗസോ ഉപയോഗിച്ച് ഒരു പുതിയ പ്രോഗ്രാം തുറക്കുമ്പോള്‍ സംഭവിക്കുന്ന കാര്യങ്ങള്‍ എന്തൊക്കഎയാണെന്ന് നോക്കാം. ഷെല്ലോ ഗ്രാഫിക്കല്‍ ഇന്റര്‍ഫേസോ ആദ്യം ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിച്ച് അതിന്റെ തന്നെ ഒരു കോപ്പി നിര്‍മ്മിക്കുന്നു. ഈ കോപ്പി നിര്‍മ്മിക്കപ്പെടുന്ന വഴി ഇങ്ങനെയാണ്.
1. ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിക്കപ്പെടുമ്പോള്‍ സിസ്റ്റം യൂസര്‍ മോഡില്‍ നിന്ന് കെര്‍ണല്‍ മോഡിലേക്ക് മാറുന്നു.
2. കെര്‍ണലിന്റെ സിസ്റ്റം കോള്‍ ഇന്റര്‍ഫേസ് ഫോര്‍ക്ക് സിസ്റ്റം കോളിലെ നിര്‍ദ്ദേശങ്ങള്‍ പ്രവര്‍ത്തിപ്പിക്കാന്‍ ആരംഭിക്കുന്നു.
3. സിസ്റ്റത്തില്‍  ഓരോ ഉപയോക്താവിനും ഒരു സമയത്ത് പ്രവര്‍ത്തിപ്പിക്കാനാകുന്ന പ്രോസസ്സുകളുടെ എണ്ണം തീരുമാനിക്കപ്പെട്ടിട്ടുണ്ടെങ്കില്‍ ആ പരിധി പാലിക്കപ്പെട്ടിട്ടുണ്ടോ എന്ന് പരിശോധിക്കപ്പെടുന്നു.
4. ഒരു പ്രോസസ്സ് ആരംഭിക്കാനാവശ്യമായ വിഭവങ്ങള്‍ സിസ്റ്റത്തില്‍ ബാക്കിയുണ്ടോ എന്ന് പരിശോധിക്കപ്പെടുന്നു (മെമ്മറി ഇതില്‍ പ്രധാനമാണ്)
5. പുതിയ ഒരു എന്‍ട്രി പ്രോസസ്സ് ടേബിളില്‍ സൃഷ്ടിക്കപ്പെടുന്നു. യു-ഏരിയക്കായി മെമ്മറി തയ്യാറാക്കുന്നു.
6. ഫോര്‍ക്ക് ഉപയോഗിച്ച പ്രോസസ്സിന്റെ ടെക്സ്റ്റ്, ഡാറ്റ, സ്റ്റാക്ക്, ഹീപ്പ് എന്നിവയുടെ കോപ്പി തയ്യാറാക്കപ്പെടുന്നു. ഇവിടെ ശരിക്കും കോപ്പി ഉണ്ടാക്കുകയില്ല. ടെക്സ്റ്റ് സെഗ്മന്റ് ആദ്യത്തെ പ്രോസസ്സിന്റെ തന്നെ ഉപയോഗിക്കപ്പെടും. ശരിക്കും കോപ്പികള്‍ ഉണ്ട് എന്ന് തോന്നിപ്പിക്കുകയും  അവിടെ പഴയ സെഗ്മെന്റുകളുടെ വിലാസം രേഖപ്പെടുത്തുകയും ആണ് ചെയ്യുന്നത്. സ്റ്റാക്ക്, ഡാറ്റ, ഹീപ്പ് സെഗ്മന്റുകള്‍ ടെക്സ്റ്റ് സെഗ്മന്റില്‍ നിന്നും വ്യത്യസ്തമായി മാറ്റങ്ങള്‍ വരുത്താന്‍ അനുവദിക്കപ്പെട്ടവയായതിനാല്‍ അവിടെ കോപ്പി ഓണ് റൈറ്റ് എന്ന സങ്കേതം ഉപയോഗിക്കും. അതായത് അവയില്‍ മാറ്റങ്ങള്‍ വരുത്തപ്പെടുന്നത് വരെ ആദ്യമുണ്ടായിരുന്നവ തന്നെ ഉപയോഗിക്കുകയും മാറ്റങ്ങള്‍ വരുത്തപ്പെട്ട ശേഷം മാത്രം പുതിയ പതിപ്പ് സൃഷ്ടിക്കുകയും ചെയ്യുന്നു.

ഇപ്പോള്‍ സിസ്റ്റത്തില്‍ ഒരേ പ്രോസസ്സിന്റെ രണ്ട് കോപ്പി ഉണ്ടായി. ഫലത്തില്‍ ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിച്ച രണ്ട് പ്രോസസ്സുകള്‍. ഫോര്‍ക്ക് സിസ്റ്റം കോളിന് രണ്ട് വ്യത്യസ്ത റിട്ടേണ്‍ മൂല്യങ്ങള്‍ ഉണ്ട്. സാധാരണ ഫങ്ങ്ഷനുകള്‍ അവയെ വിളിച്ച ഒരു പ്രോസസ്സിലേക്ക് മാത്രമേ മൂല്യങ്ങള്‍ തിരികെ നല്‍കുകയുള്ളു. എന്നാല്‍ ഫോര്‍ക്ക് പേരന്റ് പ്രോസസ്സിലേക്കും ചൈല്‍ഡ് പ്രോസസ്സിലേക്കും ഓരോ മൂല്യങ്ങള്‍ മടക്കി നല്‍കും. വിജയകരമായ ഫോര്‍ക്ക് പേരന്റ് പ്രോസസ്സിലേക്ക് ചൈല്‍ഡ് പ്രോസസ്സിന്റെ പിഐഡിയും ചൈല്‍ഡ് പ്രോസസ്സിലേക്ക് പൂജ്യവും മടക്കി നല്‍കുന്നു. ഇത് ഉപയോഗിച്ചാണ് ഇപ്പോള്‍ പ്രവര്‍ത്തിക്കുന്നത് പേരന്റാണോ ചൈല്‍ഡ് ആണോ എന്ന് മനസ്സിലാക്കാന്‍ സാധിക്കുന്നത്. സി പ്രോഗ്രാമിങ്ങ് വശമുള്ളവര്‍ക്ക് ഈ ഉദാഹരണം പരീക്ഷിക്കാവുന്നതാണ്.

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
   
 int main(void)  
 {  
     int pid;  
   
     pid = fork();  
     if (pid == -1) {  
         printf("fork failed..\n");  
         exit(-1);  
     }  
   
     if (pid == 0) {  
         printf("I am the child process. My PID is %d\n", getpid());  
         exit(0);  
     } else {  
         printf("I am the parent process PID is %d. Child PID is %d\n",getpid(), pid);  
     }  
   
     return 0;  
 }  

ഇതിനെ fork.c എന്ന ഫയലില്‍ സേവ് ചെയ്യുക. അതിനു ശേഷം ടെര്‍മിനലില്‍
gcc fork.c -o fork എന്ന് ടൈപ്പ് ചെയ്ത് എന്റര്‍ അമര്‍ത്തുക. പ്രവര്‍ത്തിപ്പിക്കാന്‍ ./fork എന്ന് ടൈപ്പ് ചെയ്ത് എന്റര്‍ അമര്‍ത്തുക. താഴെക്കാണുന്നതിന് സമാനമായ ഔട്ട്പുട്ട് ലഭിക്കും,
I am the parent process PID is 3691. Child PID is 3692
I am the child process. My PID is 3692
if സ്റ്റേറ്റ്മെന്റ് ഉപയോഗിക്കുമ്പോള്‍ സാധാരണയായി നിര്‍ദ്ദേശത്തിലെ ഒരു ഭാഗം മാത്രം പ്രവര്‍ത്തിക്കുന്നിടത്ത് ഇവിടെ രണ്ട് ഭാഗങ്ങളും പ്രവര്‍ത്തിക്കുന്നതായി കാണാം. ശരിക്കും  ഇത് രണ്ട് വ്യത്യസ്ത പ്രോസസ്സുകളില്‍ നിന്നാണ് വരുന്നത്. ആദ്യം ചൈല്‍ഡ്‌ പ്രവര്‍ത്തിക്കുമോ പേരന്റ് പ്രവര്‍ത്തിക്കുമോ എന്ന് പറയാന്‍ സാധിക്കുകയില്ല. സിസ്റ്റം കോള്‍ പൂര്‍ത്തിയായ ശേഷം പ്രോസസ്സ് വീണ്ടും യൂസര്‍ മോഡിലേക്ക് തന്നെ മടങ്ങി വരുന്നു.

ഒരു പുതിയ പ്രോസസ്സ് ഇവിടെ സൃഷ്ടിക്കപ്പെട്ടെങ്കിലും അത് ആദ്യത്തെ പ്രോസസ്സിന്റെ തന്നെ പകര്‍പ്പാണെന്ന് മനസ്സിലാക്കിയിരിക്കുമല്ലോ. എന്നാല്‍ നമുക്കാവശ്യം ഒരു പുതിയ പ്രോഗ്രാമിനെ പ്രവര്‍ത്തിപ്പിക്കലാണ്. ഇതിനായി ഉപയോഗിക്കുന്ന സിസ്റ്റം കോള്‍ ആണ് എക്സക്ക് (exec). ഈ സിസ്റ്റം കോള്‍ ചെയ്യുന്നത് അതിനെ ഉപയോഗിച്ച പ്രോസസ്സിന്റെ സെഗ്മന്റുകള്‍ മാറ്റി അവിടെ ഒരു പുതിയ പ്രോഗ്രാമില്‍ നിന്നുള്ള സെഗ്‌‌മന്റുകള്‍ ചേര്‍ക്കുകയാണ്. ഇതുവഴി ഒറിജിനല്‍ പ്രോസസ്സ് ഇല്ലാതാകുകയും പകരം പുതിയ പ്രോഗ്രാം പ്രോസസ്സായി അവിടെ വരികയും ചെയ്യുന്നു. ഇതിന്റെ പ്രവര്‍ത്തനം താഴെപ്പറയുന്നത് പോലെയാണ്.
1. എക്സെക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിക്കുമ്പോള്‍ പ്രതിപാദിക്കപ്പെട്ട എക്സിക്യൂട്ടബിള്‍ ഫയല്‍ ഡിസ്കില്‍ കണ്ടെത്തുക. (ഫയല്‍ അനുബന്ധമായ ക്രിയകളുടെ വിശദാംശങ്ങള്‍ക്കായി ഫയല്‍ സിസ്റ്റങ്ങളെക്കുറിച്ചുള്ള പോസ്റ്റുകള്‍ കാണുക)
2. ആ ഫയല്‍ സാധുവായ ഒരു പ്രോഗ്രാം ആണോ എന്ന് പരിശോധിക്കുക (elf ഫയലുകളെപ്പറ്റി നേരത്തെ പ്രദിപാദിച്ചിരുന്നു)
3. സാധുവായ ഒരു പ്രോഗ്രാം ആണെങ്കില്‍ അതില്‍ നിന്ന് വിവിധ സെഗ്മന്റുകളെക്കുറിച്ചുള്ള വിവരങ്ങള്‍ വായിക്കുകയും അവയെ മെമ്മറിയിലേക്ക് കൊണ്ടുവരികയും ചെയ്യുക.
4. നിലവിലെ സെഗ്മന്റുകളെ നശിപ്പിക്കുകയും അവക്ക് പകരം പുതിയ സെഗ്മെന്റുകള്‍ അവിടെ ചേര്‍ക്കുകയും ചെയ്യുക.
5. പുതിയ പ്രോഗ്രാമിന്റെ തുടക്കം മുതല്‍ പ്രവര്‍ത്തനം ആരംഭിക്കുക.

ഇവിടെ ശ്രദ്ധിക്കേണ്ട ഒരു പ്രധാന കാര്യം വിജയകരമായ ഒരു എക്സെക്ക് സിസ്റ്റം കോള്‍ ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ചെയ്തതുപോലെ മൂല്യങ്ങളൊന്നും മടക്കി നല്‍കുന്നില്ല. ഒരു ഫങ്ങ്ഷന്‍ റിട്ടേണ്‍ ചെയ്യുന്നത് അതിനെ വിളിച്ച പ്രോസസ്സിലേക്കാണ്. ഇവിടെ എക്സെക്കിനെ വിളിച്ച പ്രോസസ്സ് ബാക്കിയില്ല. അവിടെ പുതിയ പ്രോഗ്രാം പ്രവര്‍ത്തനം തുടങ്ങിയിരിക്കുന്നു. അതിനാല്‍ തന്നെ വിജയകരമായ എക്സെക്കില്‍ നിന്ന് റിട്ടേണ്‍ ഇല്ല. (ഇത് മിക്കവാറും ഇന്റര്‍വ്യൂകളില്‍ ഒക്കെ ചോദിക്കാറുള്ള ഒരു ചോദ്യമാണ്) മുകളിലെ പ്രോഗ്രാമിനെ അല്‍പം പരിഷ്കരിച്ച് ls എന്ന പ്രോഗ്രാമിനെ എങ്ങനെ പ്രവര്‍ത്തിപ്പിക്കം എന്ന് നോക്കാം. ഷെല്ലുകള്‍ എങ്ങനെ പ്രവര്‍ത്തിക്കുന്നു എന്ന് മനസ്സിലാക്കാന്‍ ഇത് ഉപകരിക്കും. സി പ്രോഗ്രാമിങ്ങില്‍ എക്സെക്ക് നേരിട്ട് ഉപയോഗിക്കാന്‍ വിഷമമാണ്. അതിനാല്‍ സി ലൈബ്രറി നല്‍കുന്ന execl, execlp, execle, execv, execvp, execvpe എന്ന വകഭേദങ്ങളില്‍ ഒന്ന് ഉപയോഗിക്കാം. ഇവയൊക്കെ ഉള്ളില്‍ എക്സെക്ക് തന്നെയാണ് ഉപയോഗിക്കുന്നത്.

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
   
 int main(void)  
 {  
     int pid, ret;  
   
     pid = fork();  
     if (pid == -1) {  
         printf("fork failed..\n");  
         exit(-1);  
     }  
   
     if (pid == 0) {    
         printf("I am the child process. Now executing ls\n");  
         ret = execl("/bin/ls", "ls", "/", NULL);  
         if (ret == -1) {   
             printf("exec failed\n");  
         }   
     } else {  
         printf("I am the parent process PID is %d. Child PID is %d\n",getpid(), pid);  
     }  
   
     return 0;  
 }  

ആദ്യത്തെ പ്രോഗ്രാമിനെ മേലെ കാണുന്നതുപോലെ മാറ്റുക. ബാക്കി നിര്‍ദ്ദേശങ്ങള്‍ പഴയത് തന്നെ. ഇവിടെ താരതമ്യേന എളുപ്പമുള്ള execl എന്ന രൂപമാണ് ഉപയോഗിച്ചിരിക്കുന്നത്. അതിലെ ആദ്യത്തെ പരാമീറ്റര്‍ എക്സിക്യൂട്ട് ചെയ്യണ്ട പ്രോഗ്രാമിന്റെ പാത്ത് ആണ്. ബാക്കിയുള്ളവ ആ പ്രോഗ്രാമിന് ഉള്ള ആര്‍ഗ്യുമെന്റുകള്‍. യൂണിക്സ് സിസ്റ്റങ്ങളില്‍ ഒരു പ്രോഗ്രാമിന്റെ ആദ്യത്തെ ആര്‍ഗ്യുമെന്റായി ആ പ്രോഗ്രാമിന്റെ തന്നെ പേര് നല്‍കുന്നതാണ് കീഴ്‌‌വഴക്കം. വിവിധ പേരുകളില്‍ ഉപയോഗിക്കുമ്പോള്‍ വിവിധ തരത്തില്‍ പ്രവര്‍ത്തിക്കുന്ന പ്രോഗ്രാമുകള്‍ തയ്യാറാക്കാന്‍ ഇതുവഴി സാധിക്കും. അതാണ് രണ്ടാമത്തെ ആര്‍ഗ്യുമെന്റായി ls എന്ന് തന്നെ കൊടുത്തിരിക്കുന്നത്. മൂന്നാമതെ ആര്‍ഗ്യുമെന്റ്‌‌ "/" ആണ്. / എന്ന പാത്തിലെ ഫയലുകളുടെ പട്ടിക നല്‍കാന്‍ ls പ്രോഗ്രാമിനോട് ആവശ്യപ്പെടുന്നതിനാണ് ഇത്. അവസാനമായി NULL എന്നത് സെന്റിനല്‍ ആര്‍ഗ്യുമെന്റ് അഥവാ സെന്റിനല്‍ എന്നറിയപ്പെടുന്നു. വ്യത്യസ്ത എണ്ണത്തിലുള്ള പരാമീറ്ററുകള്‍ സ്വീകരിക്കുന്ന ഫങ്ങ്ഷനുകളോട് ഇതാണ് അവസാനത്തെ പരാമീറ്റര്‍ എന്ന് സൂചിപ്പിക്കാന്‍ ഇവ ഉപയോഗിക്കുന്നു. (NULL എന്നത് സെന്റിനല്‍ അല്ല. അതിന് മറ്റ് ഉപയോഗങ്ങള്‍ ഉണ്ട്. ഇനി പരാമീറ്ററുകള്‍ ഇല്ല എന്നത് സൂചിപ്പിക്കാനായി ഉപയോഗിക്കുന്നവയെ ആണ് സെന്റിനല്‍ എന്ന് വിളിക്കുന്നത്. എക്സെക്ക് പ്രതീക്ഷിക്കുന്ന സെന്റിനല്‍ NULL ആണ്). ls കമാന്റ് -l എന്ന ആര്‍ഗ്യുമെന്റ് സ്വീകരിക്കും. ls -l എന്നുപയോഗിക്കുമ്പോള്‍ ലഭിക്കുന്ന രീതിയിലുള്ള ഔട്ട്പുട്ട് ലഭിക്കാന്‍  ret = execl("/bin/ls", "ls", "-l", "/", NULL); എന്നാക്കി ആ വരിയെ മാറ്റിയാല്‍ മതി.

ഒരു പ്രോസസ്സിലെ തന്നെ സ്വതന്ത്രമായ ഒരു ഭാഗം മറ്റൊരു പ്രോസസ്സ് പോലെ ഷെഡ്യൂള്‍ ചെയ്യാന്‍ സാധിക്കുന്ന തരത്തില്‍ പ്രവര്‍ത്തിപ്പിക്കുക എന്നതാണ് ത്രെഡുകള്‍ വഴി ചെയ്യുന്നത്. ഒരു പ്രോസസ്സില്‍ ചിലപ്പോള്‍ ത്രെഡുകള്‍ ഉണ്ടാകാം. ഈ ത്രെഡുകള്‍ക്ക് വ്യത്യസ്ത സ്റ്റാക്ക് സെഗ്‌‌മന്റുകള്‍ ഉണ്ടായിരിക്കുമെങ്കിലും ടെക്സ്റ്റ്, ഡാറ്റ തുടങ്ങിയ സെഗ്മന്റുകള്‍ ഒക്കെ ഒന്നുതന്നെ ആയിരിക്കും. ലിനക്സില്‍ ഒരു ത്രെഡ് സൃഷ്ടിക്കാന്‍ ഉപയോഗിക്കുന്ന സിസ്റ്റം കോള്‍ ക്ലോണ്‍ (clone) ആണ്. ഇത് ഒരു പ്രോഗ്രാമില്‍ നേരിട്ട് ഉപയോഗിക്കുന്നതിന് പകരം  പി-ത്രെഡ്‌ പോലെ ത്രെഡുകള്‍ കൈകാര്യം ചെയ്യാനുള്ള ലൈബ്രറികള്‍ എന്തെങ്കിലും  ഉപയോഗിക്കുന്ന രീതിയാണ് ശുപാര്‍ശ ചെയ്യപ്പെട്ടിരിക്കുന്നത്.

പ്രോസസ്സ് ടേബിള്‍, യു-ഏരിയ എന്നിവയെക്കുറിച്ച് വിശദമായി അടുത്ത പോസ്റ്റില്‍.

Saturday, October 13, 2012

പ്രോഗ്രാം, പ്രോസസ്സ് - 5

ഒരു ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം  നല്‍കുന്ന സേവനങ്ങള്‍ ഉപയോഗിക്കുന്നത് സിസ്റ്റം കോളുകള്‍ വഴിയാണ്. സാധാരണ പ്രോഗ്രാമിങ്ങ് ഭാഷകളൊക്കെ സിസ്റ്റം കോളുകള്‍ ഉപയോഗിക്കാനുള്ള ഫങ്‌‌ഷനുകള്‍ നല്‍കാറുണ്ട്. ജാവ പോലെയുള്ള വിര്‍ച്ച്വല്‍ മെഷീനുകള്‍ ഉപയോഗിക്കുന്ന അല്ലെങ്കില്‍ ഒരു ഇന്റര്‍പ്രിറ്റര്‍ കൈകാര്യം  ചെയ്യുന്ന  പ്രോഗ്രാമിങ്ങ് ഭാഷകളാണെങ്കില്‍ ഈ സിസ്റ്റം കോളുകള്‍ അവയുടെ ഇന്റര്‍പ്രിറ്റര്‍ തന്നെ കൈകാര്യം ചെയ്യും. പ്രോഗ്രാമര്‍ക്ക് അവയെക്കുറിച്ചറിയണ്ട കാര്യമില്ല. സി/സി++ ഭാഷകളില്‍ ഈ സിസ്റ്റം കോളുകള്‍ നേരിട്ട് ഉപയോഗിക്കാന്‍ സാധിക്കും. യൂണിക്സ്/ലിനക്സ് സിസ്റ്റങ്ങളില്‍ ഒരു പുതിയ പ്രോസസ് ഉണ്ടാക്കാനുള്ള സിസ്റ്റം കോള്‍ ഫോര്‍ക്ക്  (fork) ആണ്. നിലവിലുള്ള ഒരു പ്രോസസ് ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിക്കുമ്പോള്‍  ആ പ്രോസസിന്റെ മറ്റൊരു പതിപ്പ് സൃഷ്ടിക്കപ്പെടുന്നു. ഈ പതിപ്പിനെ ചൈല്‍ഡ് പ്രോസസ്സ് എന്നും ഫോര്‍ക്ക് സിസ്റ്റം കോള്‍ ഉപയോഗിച്ച പ്രോസസിനെ പേരന്റ് പ്രോസസ്സ് എന്നും  വിളിക്കുന്നു. എല്ലാ പ്രോസസുകള്‍ക്കും ഒരു പ്രോസസ്സ് ഐഡി ഉണ്ടായിരിക്കും. പ്രോസസുകളെ കൈകാര്യം ചെയ്യാന്‍ ഈ പ്രോസസ്സ് ഐഡി ഉപയോഗിക്കാം. ഇതിനെ ചുരുക്കു പിഐഡി (PID) എന്ന് വിളിക്കുന്നു. ലിനക്സ് കെര്‍ണല്‍ അതിന്റെ പ്രാധമിക ക്രമീകരണങ്ങള്‍ ഒക്കെ നടത്തിയ ശേഷം ഇനിറ്റ് (init) എന്ന പ്രോസസ്സിന്റെ സൃഷ്ടിക്കുന്നു. ഈ പ്രോസസ് മാത്രമാണ് ഫോര്‍ക്ക് ഉപയോഗിക്കാതെ സൃഷ്ടിക്കപ്പെടുന്ന ഒരേ ഒരെണ്ണം. ഇനിറ്റ് പ്രോസസ്സിന്റെ പിഐഡി 1 ആയിരിക്കും. തുടക്കത്തില്‍ ആവശ്യമായ ബാക്കിയുള്ള പ്രോസസുകളെ ഒക്കെ സൃഷ്ടിക്കുന്നത് ഇനിറ്റ് ആണ്. അപ്പോള്‍ ഇനിറ്റ് ഒഴികെയുള്ള എല്ലാ പ്രോസസ്സുകള്‍ക്കും  ഒരു പേരന്റ് പ്രോസസ് ഉണ്ടാകും. ഈ പേരന്റ് പ്രോസസിനെ മനസ്സിലാക്കാന്‍ പേരന്റ് പ്രോസസ് ഐഡി - പിപിഐഡി (PPID) ഉപയോഗിക്കുന്നു. ഒരു ചൈല്‍ഡ് പ്രോസസ്സിന്റെ പേരന്റ് പ്രോസസ്സ് പ്രവര്‍ത്തനം നിര്‍ത്തിയാല്‍ ആ ചൈല്‍ഡ് പ്രോസസ്സിനെ ഓര്‍ഫണ്‍ പ്രോസസ്സ് എന്ന് വിളിക്കാം. എല്ലാ ഓര്‍ഫണ്‍ പ്രോസസ്സുകളുടെയും  പേരന്റ് പ്രോസസ്സ് ഇനിറ്റ് ആയിരിക്കും. കെര്‍ണല്‍ എല്ലാ പ്രോസസ്സുകളുടെയും ഒരു പട്ടിക സൂക്ഷിക്കും. ഇതിനെ പ്രോസസ്സ് ടേബിള്‍ എന്ന് വിളിക്കുന്നു. ഇത് എല്ലാ പ്രോസസ്സുകള്‍ക്കും പ്രോസസ്സ് ടേബിളില്‍ ഒരു സ്ഥലം അനുവദിച്ചിരിക്കും. ഇതിനെ ആ പ്രോസസ്സിന്റെ പ്രോസസ്സ് ടേബിള്‍ എന്‍ട്രി എന്ന് വിളിക്കാം. കൂടാതെ ഓരോ പ്രോസസ്സിനും യു-ഏരിയ എന്ന പേരില്‍ അതിനെപ്പറ്റിയുള്ള വിവരങ്ങള്‍ സൂക്ഷിച്ചിരിക്കുന്ന ഒരു സ്ഥലം കൂടിയുണ്ട്. ഒരു പ്രോസസ്സിലെ വിവിധ സെഗ്‌‌മന്റുകളെക്കുറിച്ച് നേരത്തേ പറഞ്ഞിരുന്നല്ലോ. കെര്‍ണലിനും  ഈ സെഗ്മെന്റുകള്‍ ഉണ്ടായിരിക്കും. അവയിലാണ് ഈ വിവരങ്ങള്‍ ശേഖരിക്കപ്പെടുക.

യൂസര്‍ സ്പേസ് - കെര്‍ണല്‍ സ്പേസ്
ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റത്തിന്റെ ഹൃദയമായ കെര്‍ണല്‍ ആണ് ഒരു സിസ്റ്റത്തിലെ എല്ലാ പ്രവര്‍ത്തനങ്ങളെയും നിയന്ത്രിക്കുന്നത്. അതില്‍ ഘടിപ്പിച്ചിരിക്കുന്ന ഉപകരണങ്ങളെ പ്രവര്‍ത്തിപ്പിക്കുന്നതും  ഫയലുകളെ കൈകാര്യം ചെയ്യുന്നതും  എല്ലാം  കെര്‍ണല്‍ ആണ്. ഒരു ഫയല്‍ വായിക്കാനോ ഏതെങ്കിലും  ഉപകരണങ്ങളെ ഉപയോഗിക്കാനോ ഒരു പ്രോസസ്സിനും  അവകാശമില്ല. അത് ആവശ്യമായ സന്ദര്‍ഭങ്ങളില്‍ സിസ്റ്റം കോളുകള്‍ വഴി പ്രോസസ്സ് അത് കെര്‍ണലിനോട് ആവശ്യപ്പെടുന്നു. ആ പ്രോസസ്സിന് അതിനുള്ള അനുവാദം നല്‍കാമോ എന്ന് പരിശോധിച്ച ശേഷം കെര്‍ണല്‍ ആവശ്യമായ നടപടികള്‍ എടുക്കുന്നു. കെര്‍ണല്‍ പ്രവര്‍ത്തിക്കുന്ന അവസ്ഥ കൂടുതല്‍ അധികാരങ്ങളുള്ള (privileged) ഒന്നാണ്. ഇതിനെ കെര്‍ണല്‍ മോഡ് എന്ന് വിളിക്കുന്നു. സാധാരണ രീതിയില്‍ ഒരു പ്രോസസ്സ് പ്രവര്‍ത്തിക്കുന്ന അവസ്ഥ യൂസര്‍ മോഡ് എന്നും അറിയപ്പെടുന്നു. യൂസര്‍ മോഡില്‍ ഒരു പ്രോസസ്സിന് അധികാരങ്ങള്‍ വളരെ കുറവാണ്. പ്രോസസ്സ് ഒരു സിസ്റ്റം കോള്‍ ഉപയോഗിക്കുമ്പോള്‍ അത് യൂസര്‍മോഡില്‍ നിന്ന് കെര്‍ണല്‍ മോഡിലേക്ക് മാറുന്നു. കെര്‍ണലുമായി നേരിട്ട് ബന്ധപ്പെട്ടിരിക്കുന്ന വിവരങ്ങള്‍ എല്ലാം കെര്‍ണല്‍ സ്പേസ് എന്ന പദം കൊണ്ടാണ് സൂചിപ്പിക്കുന്നത്. അല്ലാത്തവ യൂസര്‍ സ്പേസും. ഒരു പ്രോഗ്രാമില്‍ ഉപയോഗിച്ചിരിക്കുന്ന ചരങ്ങള്‍ (വേരിയബിളുകള്‍) എല്ലാം  യൂസര്‍ സ്പേസില്‍ ആയിരിക്കും ഉണ്ടാകുന്നത്. പ്രോസസ്സ് ടേബിള്‍, യു-ഏരിയ എന്നിവയെല്ലാം കെര്‍ണല്‍ സ്പേസിലും.

പ്രോസസ്സിന്റെ വിവിധ അവസ്ഥകള്‍ (Process states)
ഒരു പ്രോസസ്സിന്റെ വിവിധ അവസ്ഥകള്‍ താഴെപ്പറയുന്നവയാണ്,
കടപ്പാട്: വിക്കിപീഡിയ
ഹാര്‍ഡ് ഡിസ്കില്‍ നിന്നും  പ്രോഗ്രാമിനെ മെമ്മറിയില്‍ എത്തിച്ചുകഴിഞ്ഞാല്‍ അത് ക്രിയേറ്റഡ് എന്ന അവസ്ഥയിലായിരിക്കും. സൃഷ്ടിക്കപ്പെട്ടു എന്ന അര്‍ഥത്തില്‍. ഒന്നിലധികം  പ്രോസസ്സുകള്‍ പ്രവര്‍ത്തിക്കുന്ന സിസ്റ്റത്തില്‍ സൃഷ്ടിക്കപ്പെട്ട ഉടനെ തന്നെ പ്രോസസ്സിന് പ്രവര്‍ത്തിച്ചു തുടങ്ങാനാകില്ല. ഒരു സമയത്ത് ഒരൊറ്റ പ്രോസസ്സിന് മാത്രമേ പ്രവര്‍ത്തിക്കാന്‍ സാധിക്കുകയുള്ളു എന്നതാണ് ഇതിന് കാരണം. അപ്പോള്‍ ആ പ്രോസസ്സ് കാത്തിരിപ്പ് (വെയിറ്റിങ്ങ്‌‌) അവസ്ഥയിലായിരിക്കും. ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ഷെഡ്യൂള്‍ ചെയ്യുന്നതിനനുസരിച്ച് അതിന് പ്രവര്‍ത്തിച്ച് തുടങ്ങാന്‍ സാധിക്കുന്നു. പ്രവര്‍ത്തിച്ചുകൊണ്ടിരിക്കുന്ന അവസ്ഥയാണ് റണ്ണിങ്ങ്. മെയിന്‍ മെമ്മറിയുടെ ലഭ്യതയുടെ അടിസ്ഥാനത്തില്‍ ചിലപ്പോള്‍ പ്രോസസ്സിനെ മെമ്മറിയില്‍ നിന്നും  ഡിസ്കിലേക്ക് സ്വാപ്പ് ചെയ്യാന്‍ സാധ്യതയുണ്ട്. സ്വാപ്പിങ്ങിനെപ്പറ്റി മെമ്മറി മാനേജ്‌‌മെന്റിനെക്കുറിച്ചുള്ള പോസ്റ്റില്‍ വായിക്കാം. കാത്തിരിക്കുന്ന സമയത്ത് മെമ്മറിയില്‍ നിന്ന് ഡിസ്കിലേക്ക് മാറ്റപ്പെട്ട അവസ്ഥയാണ് ഇടതുവശത്ത് താഴെയുള്ളത്. ഇനിയുള്ള അവസ്ഥ ബ്ലോക്ക് ചെയ്യപ്പെട്ട അവസ്ഥയാണ്. ഒരു പ്രോസസ്സിന് പ്രവര്‍ത്തനം തുടരാന്‍ ഏതെങ്കിലും  ഉപകരണത്തില്‍ നിന്നുള്ള സിഗ്നല്‍ ആവശ്യമാണെന്ന് കരുതുക. ഇത് ചിലപ്പോള്‍ ഉപഭോക്താവ് കീബോര്‍ഡില്‍ എന്തെങ്കിലും  അമര്‍ത്താനായിരിക്കാം, ഇന്റര്‍നെറ്റില്‍ നിന്ന് ഒരു പാക്കറ്റ് ലഭിക്കാനായിരിക്കാം. ഇത് പൂര്‍ത്തിയാകുന്നത് വരെ ആ പ്രോസസ്സിന് തുടരാന്‍ സാധിക്കില്ല. ഈ അവസ്ഥയില്‍ ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റം ആ പ്രോസസ്സിനെ ബ്ലോക്ക് ചെയ്‌‌ത് സി പി യു മറ്റൊരു പ്രോസസ്സിനായി വിട്ടു കൊടുക്കുന്നു. ആ അവസ്ഥയില്‍ ചിലപ്പോള്‍ പ്രോസസ്സ് മെമ്മറിയില്‍ നിന്നും  ഡിസ്കിലേക്ക് മാറ്റപ്പെട്ടേക്കാം. ഈ അവസ്ഥയാണ് വലതുവശത്ത് താഴെക്കാണുന്നത്.

ഫോര്‍ക്ക് സിസ്റ്റംകോളിന്റെ പ്രവര്‍ത്തനത്തെപ്പറ്റി വിശദമായി അടുത്ത പോസ്റ്റില്‍.

Sunday, October 07, 2012

പ്രോഗ്രാം, പ്രോസസ്സ് - 4

 പ്രോഗ്രാം
പ്രോസസ് എന്നത് മെമ്മറിയില്‍ ലോഡ് ചെയ്യപ്പെട്ട പ്രോഗ്രാം ആണെന്ന് നേരത്തേ‌ പറഞ്ഞു. പ്രോസസ്സുകള്‍ ആയി മാറുന്ന പ്രോഗ്രാമുകളെക്കുറിച്ച് ഈ ഭാഗത്തില്‍..

ലിനക്സിലെ ഫയല്‍ അനുമതികളില്‍ എക്സിക്യൂട്ടബിള്‍ എന്ന ഒരു അനുമതി ഉണ്ട്. ഇത് ഏത് ഫയലിന് വേണമെങ്കിലും  കൊടുക്കാവുന്നതാണ്. ഈ അനുവാദം ഉള്ളതുകൊണ്ട് മാത്രം  ഒരു ഫയല്‍ എക്സിക്യൂട്ടബിള്‍ ഫയല്‍ ആകുന്നില്ല. ഒരോ ഫയലുകളും  ഏത് തരത്തില്‍ ഉള്ളവയാണെന്ന് മനസ്സിലാക്കാന്‍ ലിനക്സില്‍ ഫയല്‍ (file) കമാന്റ് ഉപയോഗിക്കാവുന്നതാണ്. ചില ഉദാഹരണങ്ങള്‍ നോക്കൂ, 

subin@subin:~/Pictures/Tux$ file 100px-NewTux.png
100px-NewTux.png: PNG image data, 100 x 120, 8-bit/color RGBA, non-interlaced

subin@subin:/bin$ file bash
bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped

subin@subin:/lib$ file libfuse.so.2.8.6
libfuse.so.2.8.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped

ഈ പ്രോഗ്രാം  ഫയലിന്റെ പേരോ എക്സ്റ്റന്‍ഷനോ അടിസ്ഥാനമാക്കിയല്ല ഫയലിന്റെ തരം തീരുമാനിക്കുന്നത്. മിക്കവാറൂം  ബൈനറി വിവരങ്ങള്‍ അടങ്ങിയിരിക്കുന്ന ഫയലുകള്‍ക്കൊക്കെ ഒരു ക്രമീകരണ രീതി ഉണ്ടാകും. ആ ഫയലിലെ ആദ്യത്തെ ഏതാനും  ബൈറ്റുകളില്‍ ഒരു മാജിക് നമ്പര്‍ അടങ്ങിയിരിക്കും. ഈ മാജിക് നമ്പര്‍ ഓരോ തരത്തിലുള്ള ഫയലിനും  ഓരോന്നായിരിക്കും. മുകളിലെ ഉദാഹരണത്തില്‍ രണ്ടാമതും  മൂന്നാമതും  ഉള്ള ഫയലുകള്‍ ELF എന്ന തരത്തില്‍ പെട്ടവയാണ്. ലിനക്സിലെ എക്സിക്യൂട്ടബിള്‍ ഫയലിന്റെ ക്രമീകരണരീതികളില്‍ ഒന്നാണ് ELF. എക്സിക്യൂട്ടബിള്‍ ആന്‍ഡ്‌ ലിങ്കബിള്‍ ഫോര്‍മാറ്റ് എന്നതിന്റെ ചുരുക്കമാണിത്. ഇത് കൂടാതെ ഷെല്‍ സ്ക്രിപ്റ്റുകള്‍, പൈത്തണ്‍, പേള്‍ പ്രോഗ്രാമുകള്‍ എന്നിവയെയൊക്കെ എക്സിക്യൂട്ടബിളുകള്‍ ആയി പരിഗണിക്കും. എന്നാല്‍ ELF ഫയലുകള്‍ പോലെയല്ല അവ കൈകാര്യം ചെയ്യപ്പെടുന്നത്. അവയെ പ്രവര്‍ത്തിപ്പിക്കാനാവശ്യമായ പ്രോഗ്രാമുകളുടെ വിവരം ആ ഫയലുകളുടെ ആദ്യം രേഖപ്പെടുത്തിയിരിക്കും. ഷെല്‍ സ്ക്രിപ്റ്റുകളുടെ ഒക്കെ ഫയലിലെ ആദ്യത്തെ വരി മിക്കവാറും  #!/bin/bash എന്നായിരിക്കും. /bin/bash എന്ന പ്രോഗ്രാമുപയോഗിച്ചാണ് ആ ഫയലിനെ പ്രവര്‍ത്തിപ്പിക്കേണ്ടത് എന്നര്‍ഥം. എന്നാല്‍ ELF ഫയലുകളെ കെര്‍ണല്‍ നേരിട്ട് പ്രവര്‍ത്തിപ്പിക്കുകയാണ് ചെയ്യുന്നത്. ELF ഫയലുകളിലെ വിവരങ്ങള്‍ വിവിധ വിഭാഗങ്ങളില്‍ ആയാണ് ക്രമീകരിച്ചിരിക്കുക. മുകളിലെ ഉദാഹരണത്തില്‍ രണ്ടാമത് കാണുന്നത് ഒരു എക്സിക്യൂട്ടബിള്‍ ഫയലും  മൂന്നാമത്തേത് ഒരു ഷെയേര്‍ഡ്‌ ലൈബ്രറിയും  ആണ്. ഇവയെക്കുറിച്ച് പിന്നീട് പറയാം. ഈ ഫയലുകളില്‍ ഒക്കെ ഉണ്ടാകുന്ന വിവിധ ഭാഗങ്ങള്‍ (സെഗ്‌‌മെന്റ്) ചുവടെ (ഇത് ഒരു സി കമ്പൈലര്‍ ഉണ്ടാക്കുന്ന എക്സിക്യൂട്ടബിളിനെ അടിഥാനമാക്കിയാണ്),

1. .text: പ്രോഗ്രാമിലെ നിര്‍ദ്ദേശങ്ങള്‍. ഇവക്കനുസരിച്ചാണ് പ്രോഗ്രാം  പ്രവര്‍ത്തിക്കുന്നത്.
2. .data: ഒരു സി പ്രോഗ്രാമിലെ മൂല്യം തീരുമാനിക്കപ്പെട്ട ഗ്ലോബല്‍ വേരിയബിളുകള്‍, സ്റ്റാറ്റിക് വേരിയബിളുകള്‍ എന്നിവയൊക്കെ.
3. .bss: മൂല്യം തീരുമാനിക്കപ്പെട്ടിട്ടില്ലാത്ത ഗ്ലോബല്‍ വേരിയബിളുകള്‍.
4. .stack: പ്രോഗ്രാമിലെ വിവിധ ഫങ്ഷനുകള്‍ക്ക് പ്രവര്‍ത്തിക്കാനാവശ്യമായ വിവരങ്ങള്‍. പ്രോഗ്രാമിന്റെ ആരംഭത്തില്‍ ഇതില്‍ മെയിന്‍ ഫങ്ങ്ഷനിലെ ലോക്കല്‍/ഓട്ടോമാറ്റിക് വേരിയബിളുകള്‍, റിട്ടേണ്‍ അഡ്രസ്സ്, കമാന്റ് ലൈന്‍ ആര്‍ഗ്യുമെന്റുകള്‍, എന്‍വയോണ്‍മെന്റ് വേരിയബിളുകള്‍ എന്നിവയായിരിക്കും  ഉണ്ടാവുക. മറ്റൊരു ഫങ്ങ്ഷന്‍ വിളിക്കപ്പെടുമ്പോള്‍ ആ ഫങ്ങ്‌‌ഷന്റെ ലോക്കല്‍ വേരിയബിളുകള്‍, അതിന്റെ ആര്‍ഗ്യുമെന്റുകള്‍, അതിന്റെ റിട്ടേണ്‍ അഡ്രസ് തുടങ്ങിയ വിവരങ്ങള്‍ ഉള്‍ക്കൊള്ളിച്ച് ഒരു പുതിയ ഉപ ഭാഗം  ഇതിനുള്ളില്‍ സൃഷ്ടിക്കപ്പെടുന്നു.
5. .heap: പ്രോഗ്രാം  പ്രവര്‍ത്തിക്കുന്ന സമയത്ത് അതിന് കൂടുതല്‍ മെമ്മറി ആവശ്യമായി വന്നാല്‍ അത് അനുവദിക്കാനുള്ള സ്ഥലം.
(മുകളിലുള്ള സി പ്രോഗ്രാമിങ്ങുമായി ബന്ധപ്പെട്ട പദങ്ങള്‍ വിശദീകരിക്കാന്‍ കൂടുതല്‍ സ്ഥലവും  സമയവും  വേണ്ടിവരുമെന്നതിനാല്‍ അവയുടെ വിശദീകരണം ഒഴിവാക്കുന്നു. അവ എന്താണെന്ന് സൂചിപ്പിക്കുന്ന വിക്കി ലേഖനത്തിലേക്ക് കണ്ണികള്‍ നല്‍കിയിട്ടുണ്ട്)

ആധുനിക കമ്പൈലറുകള്‍ ഇവക്ക് പുറമേ മറ്റ് പല ഭാഗങ്ങളും  എക്സിക്യൂട്ടബിള്‍ ഫയലുകളില്‍ ഉള്‍പ്പെടുത്താറുണ്ട്. ജി ഡി ബി പോലെയുള്ള ഡീബഗ്ഗര്‍ പ്രോഗ്രാമുകള്‍ക്കാവശ്യമായ വിവരങ്ങള്‍ Dwarf എന്ന ക്രമീകരണ രീതി ഉപയോഗിച്ച് ചില എക്സിക്യൂട്ടബിള്‍ ഫയലുകളില്‍ കാണും. (Elf എന്ന പേരിന്റെ കൂടെ നില്‍ക്കാന്‍ Dwarf എന്ന് പേരിട്ടതാണ്. ഇവ രണ്ടും മാന്ത്രിക ജീവികളുടെ പേരാണല്ലോ.) മറ്റുള്ള ബൈനറി എക്സിക്യൂട്ടബിള്‍ ക്രമീകരണ രീതികളിലും  ഈ ഭാഗങ്ങള്‍ ഒക്കെ ഉണ്ടാകും. Elf ഒരു ഉദാഹരണമായി എടുത്തത് യൂണിക്സ്/ലിനക്സ് സിസ്റ്റങ്ങള്‍ അത് ഉപയോഗിക്കുന്നു എന്നതിനാലാണ്. എക്സിക്യൂട്ടബിള്‍ ഫയലുകളെ കുറിച്ചുള്ള വിവരങ്ങള്‍ ലഭിക്കാനും  അവയെ അപഗ്രഥിക്കാനും  മറ്റുമായി വിവിധ പ്രോഗ്രാമുകള്‍ ലഭ്യമാണ്. ഉദാഹരണത്തിന്, എക്സിക്യൂട്ടബിള്‍ ഫയലിലെ വിവിധ സെഗ്മന്റുകളുടെ വലിപ്പം അറിയാന്‍ size, ഫയലിലെ വിവിധ ചിഹ്നങ്ങളുടെ വിവരങ്ങള്‍ ലഭിക്കാന്‍ nm, elf ഫയലുകളിലെ വിവിധ വിവരങ്ങള്‍ക്കായി readelfഎന്നിവ.

കമ്പൈലര്‍ ഒരു എക്സിക്യൂട്ടബിള്‍ ഫയല്‍ ഉണ്ടാക്കിക്കഴിഞ്ഞാല്‍ അതില്‍ പ്രവര്‍ത്തനസമയത്ത് അത്യാവശ്യമല്ലാത്ത വിവിധ വിവരങ്ങള്‍ ഉണ്ടായിരിക്കും. സാധാരണ ഉപഭോക്താക്കള്‍ക്ക് ആവശ്യമില്ലാത്ത ഈ വിവരങ്ങള്‍ ഒഴിവാക്കുന്നത് ഫയലുകളുടെ വലിപ്പം കുറക്കാന്‍ സഹായിക്കും. ഇങ്ങനെയുള്ള വിവരങ്ങള്‍ ഒഴിവാക്കുന്ന പ്രക്രിയയെ സ്ട്രിപ്പിങ്ങ് എന്ന് പറയുന്നു. strip എന്ന പ്രോഗ്രാം  ഉപയോഗിച്ച് ഇത് ചെയ്യാവുന്നതാണ്. ആദ്യം  നല്‍ലിയിരിക്കുന്ന ഫയല്‍ കമാന്റ് ഉദാഹരണങ്ങളില്‍ അവസാനം stripped എന്ന് പരാമര്‍ശിച്ചിട്ടുള്ളത് ശ്രദ്ധിക്കൂ.

യൂണിക്സ്/ലിനക്സ് സിസ്റ്റങ്ങളില്‍ പ്രോസസുകള്‍ തുടങ്ങുന്നത്, അവസാനിപ്പിക്കുന്നത് എന്നിവയെക്കുറിച്ച് അടുത്ത പോസ്റ്റില്‍.