Pages

Friday, October 8, 2010

Process බෝ කරන fork()

මේ දවස් වල සෑහෙන ගැටලු ආපු දෙයක්නේ මේ fork(). ඊළග සතියේ දෙන Bonus Assignment එකට ආයෙ fork() එනවලු. ඒක නිසා fork() ගැන පොඩ්ඩක් ලියන්නම්. මෙන්න මේ විදියට පටන් ගන්නම් Process බෝ කරන fork() ගැන. 

fork() කියන්නේ System Call එකක්. ඒකත් හරි කතාවනේ. දැන් ඊළගට System Call කියන්නේ මොකක්ද කියන එක ප්‍රශ්නේ. System Call එකක් කියන්නේ තවත් එක් function එකක්. යම් කිසි program එකක අපි මේ function නැත්තම් System Calls, යොදාගන්නේ Operating System එකේ service එකක් ලබා ගන්න. ඉතින් ඔය විදියට System Calls ගොඩක් තියනවා. එකක් තමා fork. Linux වල වගේ නම් man fork කියලා terminal එකක ගැහුවම fork() ගැන man page එක පෙන්වනවා මේ පහළ තියන රූපයේ වගේ. අනිත් System Calls ගැන විස්තරත් මේ විදියට බලාගන්න පුළුවන්. ඉතින් මේ fork() වලට පොඩි පෙර ගමනක්.



fork() කියන System call එක භාවිතා කරන්නේ අළුතින් process නිර්මාණය කිරීම සඳහා. fork(), System call එක කිසිම argument එකක් ලබාගන්නේ නැහැ. ඒත් ඒ System Call එක execute වීමෙන් පස්සේ process ID එකක් return කරනවා. fork වලින් කරන්නේ අළුත් process එකක් නිර්මාණය කරන එක කියලා කලින්ම කිව්වනේ. ඒ process එක හඳුන්වන්නේ child process එක කියලා. fork() function එක call කලෙත් යම්කිසි process එකකින්නේ.  ඒ process එක හඳුන්වන්නේ parent process එක කියලා. fork() කියලා program එක තුල function එක call වුණ තැන සිට තියන සියලුම instructions, child process එකෙන් හා parent process එකෙන් කියන දෙකෙන්ම execute වෙනවා. ඒක නිසා අපිට සිද්ධ වෙනවා fork() execute වීමෙන් පසු parent සහ child processes වෙන වෙනම හඳුනගන්න. අන්න ඒකට තමයි fork() call කිරීමෙන් පසු return වෙන value එක අපිට පාවිච්චි කරන්න වෙන්නේ. ඇත්තටම බැලුවොත් fork() එක්ක සෙල්ලම සිද්ධ වෙන්නේ මේ return value එක එක්ක තමා...

මේ return value එකට ලැබෙන අගය  ගැන කොටස් තුනකින් කියන්නම්. මේ return value එක ඍණ අගයක් නම්, එයින් කියැවෙන්නේ child process එක නිර්මාණය වීම අසාර්ථකයි කියන එකයි. fork() function එක execute වීමෙන් පසු, අළුතින් සැකසුනු process එකට, ඒ කියන්නේ child process එකට බින්දුව (Zero) කියන value එක return කරනවා. ඒ වගේම fork() function එක execute වීමෙන් පසු එම parent process එකට ධන අගයක්(Positive Value) return කරනවා. එලෙස return කරන ධන අගය, අදාල parent process එකෙන් නිර්මාණය කරන ලද child process එකේ Process ID එක වේ. මේ return value එක ගැනත් සටහනක් තියමු. මේ  return value එක, sys/types.h කියන header file එකේ define කරල තියන pid_t කියන type එකට අයිති එකක්. මේ process id එක කියවගන්න (retrieve) කරගන්න getpid() කියන function එක පාවිච්චි කරන්න පුළුවන්. fork() එක්ක program ලියනවා කියන්නේ මේ  return value, process id එක්ක කරන සෙල්ලම තමා....

මෙතන ඉඳන් කතාව පටන් ගමු උදාහරණයක් එක්කම. මේ පහත තියන උදාහරණය ඇසුරින් තමයි විස්තරයම වෙන්නේ. හරිම සරල එකක්. මේ උදාහරණය බාගන්න ඕනි නම් මෙතන ක්ලික් කරන්න. මෙන්න උදාහරණය.....


මුල ඉදන්ම විස්තරේ පටන් ගන්නම්කෝ. sys/types.h නම් header file එක include කළ හේතුව ඉහතින් විස්තර කලානේ. ඒ වගේම unistd.h කියන header file එකත් include කරලා තියනවා. fork() function එක declare කරලා තියෙන්නේ unistd.h කියන header file එකත් එක්ක. ඊටපස්සේ main method එක යටතේ 8 වෙනි පේලියේ pid_t නම් ඉහත විස්තර කරන ලද type එකට අදාලව pid ලෙස variable එකක් හදාගෙන තියනවා. fork() function එක call කිරීමෙන් පසු return වෙන value එක ලබාගන්නේ මෙම pid නම් variable එකයි. එම variable එකේ අගය මත child හා parent වෙන් කෙරෙන ආකාරය ගැන කලින් දක්වලා තිබුනනේ. මේකෙ loop එකක් යොදාගෙන සිදු කර ඇත්තේ වැඩි වාර ගණනක් processes, run කරවීමයි. වැඩි වාර ගණනක් run කරවූ විට context switching ක්‍රියාව සිදුවීම නිසා child හා parent processes මාරුවෙන් මාරුවට සිදුවන අයුරු පැහැදිලිව බලාගන්න පුළුවන්. ඉතින් මේ උදාහරණය බොහොම සරල එකක්. ඒක බාගෙන run කරලා බලන්න. වැඩේ ඒ හැටි අමාරු නැහැ. තව උදාහරණයක් දෙන්නම්. ටිකක් ප්‍රායෝගික පැත්තක් තියන එකක්. ඕනි නම් කියන්නකෝ. ඔන්න ඔහොමයි fork()..... :)

Thursday, October 7, 2010

C වලින් If else සහ switch

ගොඩක් අය Java වල මූලික කරුණු කාරණා දන්න නිසාC ගැන විස්තර කරද්දි Java වලට සාපේක්ෂව විස්තර කරන්න උත්සහ ගන්නම්. ඒක තේරුම් ගැනීමේ පහසුවක් වේවි. මාතෘකාවේ පිලිවෙලටම වැඩේ පටන් ගන්නම්....

if.....else

මේකෙන් වෙන්නේ මොකක්ද කියලා විස්තර කරන්න අවශ්‍ය වෙන එකක් නැහැ. කෙටියෙන් විස්තර කරනවා නම්, යම්කිසි සලකනු ලබන condition එකක සත්‍ය අසත්‍ය භාවය (true & false) මත යම්කිසි statement කිහිපයක් හෝ වෙනමම method එකක execute කරවීම if else භාවිතයෙන් කරගන්න පුළුවන්. C program එකක if else පාවිච්චි වෙන විදිය ගැන මෙහිදී බලමු. Java  වලට සාපේක්ෂව මෙහි වෙනසක් නැතිම තරම්.... if else භාවිතා කරන ආකාරය ගැන උදාහරණයකින් සලකමු. 
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int x = 9;
    if ( x == 5 )
    {
//     if condition is true
        printf("You are the winner\n");
    }
    else
    {
//     if condition is false
        printf("You are the looser\n");
    }
    return 0;
}


මේ උදාහරණයෙන් පැහැදිලි වෙනවා ඇති ඔබට Java හා C වලදි, if-else භාවිතයේ වෙනසක් නොමැතිම තරම් බව. මෙම උදාහරණයට අනුව සිදු වන්නේ x වල අගය 5 ට සමාන නම් You are the winner ලෙසත් එසේ නොවේ නම් You are the looser ලෙසත් print වේ. මේ ආකාරයට if statement එකක් තුළ තවත් if statement එකක් ලිවීමේ හැකියාවද තියනවා. 


Switch

If statement කිහිපයකින් කිරීමට හැකි සමහර කාර්යයන් switch statement එකක් භාවිතයෙන් කිරීමේ හැකියාවක් තියනවා. if....else සේම Switch statement එකද C වලදී හා Java වලදී වෙනසක් නැතිම තරම්. උදාහරණයක් සලකා බලමු.
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int x = 1;
    switch (x)
    {
        case 1:
            printf("hello\n");
            break;

        case 2:
            printf("fool\n");
            break;

        default:
            printf("fellow\n");
            break;
    }
    return 0;
}

මෙහිදී සිදුවන දේ කෙටියෙන් පැහැදිලි කළොත්, if-else කිහිපයකින් කර ගැනීමට හැකි වැඩක් switch මගින් සිදු කරල තියනවා. මුලින්ම x කියල variable එකක් හදලා තියනවා. ඊට පස්සේ switch (x) කියන පේළියෙන් අපි සදහන් කරල තියනවා ඉස්සරහට කරන comparisons සියල්ල මේ x කියන variable එකත් සමග සිදුකළ යුතුයි කියලා. මේ variable එකට ගන්න පුළුවන් වෙන්නේ int එකක් හෝ char එකක් විතරයි.  ඒ වගේම මතක තියාගන්න char එකක් පාවිච්චි කරනව නම් char variable value එක single quotation ඇතුලේ ලියන්න. ඒක එහෙමයි. case කියලා තවත් keyword එකක් පාවිච්චි වෙලා තියනවා මෙතන. ඒකෙන් කරන්නේ x සදහා අපි compare කරන value එක මොකක්ද කියලා දෙන එකයි. break කියලා තවත් keyword එකක් තියනවා. අපි හිතමු මේ උදාහරණයට කියන code එක ගැන. ඒකෙ දැන් case 1 : කියන තැනින්ම true වෙන නිසා එතනින් පස්සේ තියන line එකේ සිට execute වෙන්න පටන් ගන්නවා. නමුත් case 1: නිසා execute වෙන්න ඕනි lines ටික අවසන් වෙන තැන අපි break කියන keyword එක use කලේ නැත්තම් case 1: වුණ තැන ඉදන් default කියන තැනට එනකං තියන සියලුම lines ටික execute වීම සිදු වෙනවා. break කියන keyword එක use කිරීමේ අරමුණ එයයි. default කියන්නේ නිකන් හරියට else වගේ තමා. case වල එක  value එකකටවත් true වුනේ නැතිනම් අවසානයට සිදුවන්නේ default යටතේ තියන lines ටික execute වෙන එක තමා. ඔන්න ඔහොමයි switch. මේකටම loops ගැනත් ලියන්න හිටියෙ. ඒකත් ලිව්ව නම් මේක මා ගලක් වගේ දික් වෙනවා. ඒක නිසා කතාව මතු සම්බන්ධයි. Loops සමගින් නැවත C ගැන ටිකක්....

ජය වේවා!!!

Monday, October 4, 2010

Process එකක ව්‍යුහය 1


අප ‍විසින් සකස් කරන program එකක් අවසන් වශයෙන් පරිගණකය තුළ execute වී‍ම සිදුවන ආකාරය පැහැදිලි කරන්නට මෙම ලිපියෙන් බලාපොරොත්තු වෙනවා. මේකෙදි කතා කරන්නෙ execute වී‍මට අවශ්‍ය මූලිකම ‍දේවල් ටිකක් ගැන විතරයි.

අපි program එකක් සකස් කළ විට ඒක ගොඩක් සංවිධානාත්මකව තියෙනවා. ඒක බලපු ගමන් අපට එයින් සිදුවන දේ පැහැදිලිව තේරුම් ගන්න පුළුවන්. නමුත් පරිගණකය‍ට ඒ දේ කරන්න බැහැ. එයට එකින් එක සිදු කල යුතු සියලුම දේවල් කියන්න ඕනි. මේ අපි තේරුම් ගත යුතු වැදගත්ම දෙයක්. කල යුතු ඉතාමත් සුළු පිය‍වරක් උනත් ප‍රිගණකය‍ට අපි විසින් කියන්න ඕනි. මේක මෙහෙම කියද්දි ‍හොදට දන්න දෙයක් කියල හිතුනත් ඒක එච්චර ලේසියෙන් තේරුම් යන්නෙ නෑ. ඒ ගැන හොදින් හිතල බලන්න. ඒත් ඔබ code එකක් ලියද්දි මේ හැම පියවරක්ම ලියන්නෙ නෑනෙ. ඒත් ඔබ code එක compile  කලාම compiler එක ඔබ වෙනුවෙන් ඒ දේවල් සිදු කරල දෙනවා. Assembly code එකක් ලියද්දි ඔබ මේ කරුණ ගැන හරියටම තේරුම් අරගෙන තියෙන්න ඕනි. මොකද assembly code එකක් කියන්නෙ compile  කලාට පස්සෙ ලැබෙන එකක්. NASM ‍වගේ assembler එකකින් කරන්නෙ ඔබේ assembly code එක machine code එකට හරවන එක විතරයි. (මම දන්න විදියට)

අපි සරල code එකක් භාවිතා කරල මේ ක්‍රියාවලිය පැහැදිලි කර ගනිමු.


int main() {

    int a = 10;
    int b = 5;
    int c = add(a,b);
    return 0;
   
}

int add(int x, int y) {

    int z = x+y;
    return z;
   
}

ඉහත code එක compile  කලාම කලින් කිව්ව විදියට compiler එක ඔබ වෙනුවෙන් අවශ්‍ය එකතු කිරීම් කරල RAM එක තුළ එක් එක් instruction එක තැබිය යුතු memory address දක්වාම වූ සියලු විස්තර file එකකට ලියනවා. එම program එක run වෙද්දි RAM එක තුළ දත්ත පහත විදියට විහිදෙනවා කියල හිතමු.

assembly code ලිවීමේ දී සලකන විවිධ segment භාවිත කරන ක්‍රියාවලිය මදකට අමතක කරන්න. මේකෙ පැහැදිලි කරන්නෙ එක් method එකකට අදාල දත්ත එක තැනක තියෙනව කියල සලකලයි.


ඉහත පින්තූරයේ තියෙන විදියට memory address 1000-1050 වන තුරු main method එකත් 1100-1120 වන තුරු add method එකත් තියෙනව කියල හිතමු. Code එක compile කරන කොටම මොන memory address වලද program එක ලියවෙන්න ඕනි කියන එක file එකේ ලියවෙනවා. මොකද jump statement එකක් එහෙම තිබ්බොත් යන්න ඕනි මොන memory address එකටද කියන එක program එක දැනන් ඉන්න ඕනි. Code එක compile කරද්දිම memory address ලියවෙනවා නම් ප්‍රශ්නයක් තියෙනවා. Program එක compile කරන්නෙ එක වෙලාවක ඒත් ඊට පස්සෙ විවිධ වෙලා වලදි ඒක run කරනව. නමුත් ඒ හැම වෙලාවකදිම එකම memory එකේ ස්ථාන හිස්ව තියෙනවා කියල කියන්න බැහැ. මොකද එකම වෙලාවෙ program කිහිපයක් ‍වැඩ කරන්න පුළුවන්නෙ. නමුත් අපි දැනට සලකමු අපේ program එකට මුළු memory එකම භාවිත කරන්න පුළුවන් කියල. එහෙම උනොත් ඉහත  code එකේ ගැටලුවක් එ‍න්නෙ නෑ. ඒත් ඉහත  code එකේ main method එකත් add method එකත් ‍ file දෙකක ලියල තියෙනව නම් ඒ file දෙක වෙන වෙනම compile කරන්න පුළුවන්නෙ. එතකොට....????

එතකොට එක් file එකක් අනිත් file එක භාවිත කරන  memory address පිළිබද අව‍බෝධයක් නැහැ. File දෙකම එකම memory address භාවිත කරන්න ඉඩ තියෙනවා. එවිට එම program එක run වෙන්න විදියක් නැහැ. මෙම තත්වය මග හරවා ගන්නෙ linker එක භාවිතයෙන්.


file : main.c


int main() {

    int a = 10;
    int b = 5;
    int c = add(a,b);
    return 0;
   
}
                                                  


file : add.c


int add(int x, int y) {

    int z = x+y;
    return z;
   
}


main method එක main.c file එකෙත් add method එක add.c file එකෙත් තියෙනව කියල හිතමු. compiler එකෙන් මේ file දෙක main.o add.o කියල file දෙකකට වෙන වෙනම compile කරනව කියල හිතමු. linker එකෙන් කරන්නෙ මේ file දෙකේ තියෙන දත්ත තනි file එකකට අලුතෙන් ලියන එක. එහෙම ලියද්දි memory address වල ගැටලුවක් වෙන්නෙ නැති විදියට memory එකේ තැන් දෙකකට එන විදියටයි ඒක ලියන්නෙ.



program එකක් execute වෙද්දි method call කරන විදිය ඉදිරියේදී සලකල බලමු.................

Wednesday, September 29, 2010

Assembly code එකක දළ සැකැස්ම

කලින් පොස්ට් එකෙදි මාධව අතින් Assembly Program එකක් Compile කරලා Run කරන විදිහ විස්තර වෙච්ච නිසා මේ කොටසෙදි මම Assembly Program එකක දළ ව්‍යුහය ගැන කතකරන්නම්.මුලින්ම අපි හුරු පුරුදු "C" code එකක් Model එක විදිහට තියාගෙන ඒ ඔස්සේ කලපනා කරල බලමු මොකද්ද මේ "ව්‍යුහය"කියල.


int main()
{ 
     int x=5; 
     int y;
     printf("hello");
     y=x+5;
}

C program එකක function Code එකේ ප්‍රධාන කොටස් 3 ක් අඳුනගන්න පුලුවන්.
1) අපි program එක Run වෙන අතරදි භාවිතා කිරීමට බලපොරොත්තු වන  දැනටම දන්නා Values (අගයන් සහ නියත) සදහා Main Memory න් ඉඩ වෙන් කිරීම. 
       eg: int x=5;
2) අපි program එක Run වෙන අතරදි මතුවන කිසියම් දත්තයක් ගබඩා කිරීමට භාවිතා කිරීම සදහා බලපොරොත්තු වන දැනට Value එක නොදන්නා Variables සදහා Main Memory න් ඉඩ වෙන් කිරීම. 
      eg: int y;


3)ප්‍රධානම කොටස මෙයයි. program එක මගින් කරගැනීමට බලාපොරොත්තු වන සියලු කාර්යයන් සදහා අදාල instructions අඩංගු කොටස මෙයයි. 
      eg: printf("Hello"); 
            y=x+3;

ඔය කරුණු කාරණා ඔලුවෙ තියාගෙන අපි දැන් Assembly දිහාවට හැරෙමු. Assembly කියන්නෙ Low Level Language එකක් වුනාට ඒකෙ High level යැයි කියාගන්නා C කියන Languages වගේ නෙමේ ඔය ඉහත සදහන් කරපු කොටස් 3 සංවිධානාත්මකව වෙනම කොටස් වලට කඩලයි ලියන්න තියෙන්නෙ. ඕනි ඕනි විදිහට කොටස් කඩනව වගේ නෙමේ nasm හෝ වෙන ඕනිම Assembly compiler (හරියටම කිව්වොත් Assembler) එකකින් කඩපු කොටස් අඳුනගන්න පුලුවන් වෙන්ඩත් එපැයි. ඔන්න ඕක නිසා "segment .data", "segment .bss" , "segment .text" කියලා විශේෂ Key words 3 ක් අපි අදාල Section එක පටන් ගන්න කලින් ලියනවා Assemblor එකට ඔය sections අඳුනගන්න ලේසි වෙන්න.


මෙතනදි ".data" කියන Key word එක යටතේ ඇති කොටසේ ලියන්නෙ උඩ විස්තර කරපු පලවෙනි කොටසට අදාල දේවලුයි. ".bss" සහ ".text" කොටස් වල ලියන්නෙ පිලිවෙලින් ඉහත 2, 3 වලට අදාල දේවලුයි.

මේ කතාවෙච්ච සිද්ධිය පැහැදිලි වෙන්න දැන් අපි Assembly Code දිහා පොඩ්ඩක් බලමු.

-----------------------------------------------------------
segment .data 
     msg db "Hello World",10  
     len equ $-msg
segment .bss
     y resd 1 
 
segment .text  
     global _start   
 
_start:        
     mov eax,4 
     mov ebx,1 
     mov ecx,msg
     mov edx,len   
     int 80h
     mov ebx,0  
     mov eax,1  
     int 80h 
 
------------------------------------------------------------- 
 
ඒක නිසා ගොඩක් බරපතල විදියට මේක දිහා නොබල දැනට දන්න කරුණු එක්ක මේක දිහා බැලුවොත් ලේසි වෙයි මේක තේරුම් ගන්න එක. ඒ කියන්නේ මෙන්න මේ වගේ. 
මුලදිම මම කිව්වා Assembly Code  එකක තියනවා කියලා ප්‍රධාන කොටස් 3ක්. අන්න ඒ කොටස් 3ට අදාල Keywords උඩ තියන Code එකේ Highlight කරලා තියන විත්තිය පැහැදිලිව පේනවනේ.... ඒ Highlight කරලා තියෙන කොටස් වලට පහලින් තියෙන්නේ ඒ ඒ කොටසට අදාල Code කොටස්.වැඩේ තව පැහැදිලි වෙන්න නම් උඩ තියෙන Code එක copy කරල filename.asm විදිට Save කරලා මාධව කලින් සදහන් කලා වගේ,
     nasm -f elf filename.asm
     ld -s -o filename filename.o      ./filename
යන Command 3 භාවිතයෙන් program එක Execute කලහCommand line එකේ Hello World කියල print වෙනව බලාගන්න පුලුවන් වෙයි.
දැනට මේ ඇතිනේ. මේ Code එකේ ඇතුලු කොටස් වලින් කියවෙන දේ ගැන ඉස්සරහට කතාකරමු.