Fija (thread)

**Fijet (Threads)** janë njësia me e vogël qe mundet te organizohen nga sistemi operativ. Këto në fakt ndodhen brenda një procesi. Më herët kemi përmendur modelin e procesit duke u bazuar ne dy koncepte: grupimi i te resurseve dhe ekzekutimi. Sa i përket te pares e dimë se procesi ka fushën e adresës, qe përmban të dhëna, gjithashtu edhe resurse tjera siç janë fajllat e hapura etj. Ndërsa sa i perket konceptit tjetër ka te beje me ekzekutimin e fijeve (threads). Fijet kanë program counter, qe tregon se ekzekutimin e ardhshëm të një fije, gjithashtu një regjistër qe nevojitet për një variabël.

## Modeli i Fijeve te Ekzekutimit 
Fijet na mundësojnë me shume ekzekutime ne një proces. Duke pasur disa fije qe ekzekutohen paralelisht, kjo është e ngjashme me atë sikur te ekzekutohen me tepër procese paralelisht. Për shkak se fijet i kane disa karakteristika te proceseve ato mund te quhen edhe si procese me peshe me te lehte (lightweight). Sa i përket konceptit “multithreading” ka te beje me atë se ne një proces mund te ndodhen me shumë fije.  

Nga figura me poshtë mund te shohim se disa procese kane nga një fije te vetme, ku çdo proces ka fushën e vete te adresimit, qe do te thotë se çdo fije qe ndodhet ne proces ka fushe te ndryshme te adresimit, ndërsa sa i përket figurës tjetër ka te beje me atë se ne një proces ndodhen tri fije, dhe këto fije ndajnë fushën e njëjte te adresimit. Ne këtë rast mundemi te shohim si funksionon multiprogramimi duke kaluar nga një proces ne tjetër, qe na jep iluzionin qe ekzekutimi i proceseve ndodhen paralelisht, e njëjta ndodhen edhe me fijet e ekzekutimit, kalimi nga një fije ne tjetrën.
 
Çdo fije brenda një procesi mund te jete mvarur nga fija tjeter, sepse ato kane nje fushe te adresimit, nje variabel te perbashket, dhe çdo fije mund te lexoje, shkruaje apo te fshije nje fije tjeter. Ndersa te proceset nuk mund qe te ndodhe kjo se ato kane fusha te ndryshme te adresimit dhe nuk mund te kene ndonjë lidhje ndermjet veti.  

Është e rëndësishme te përmendet se çdo fije ka stack-un e vet ne te cilat ruan permbajtjet te cdo procedure qe thiret. 
Ne rastin kur kemi multithreading, procesi ne fakt fillon me nje fije, duke bere thirjen e procedures nga libraria qe është create_thread, dhe ne momentin kur fije ka mbaruar procedure apo punën e saj, behet thirja e procedures nga libraria qe është thread_exit. Kemi raste edhe kur fija ka mbaruar procedurën e saj, por është e bllokuar qe te terhiqet, pasi qe duhet te prese qe mbaroe proceduren edhe ndonje fije tjetër special, ne këtë rast thirret procedura nga libraria qe është thread_wait. Gjithashtu kemi edhe thirjen thread_yeild, qe ka te beje me atë se fija dorëzohet duke i dhëne mundesin qe te procedurohet ndonje fije tjeter, pasi qe nuk kemi ndonje sinjal te kllokut (clock) qe te tregoe se ka ndërprerje (interrupt).

## Përdorimi i Fijeve te Ekzekutimit 
Fijet janë te nevojshme për procesimin paralel, pasi qe i mundesojne perdoruesit qe ne te njejten kohe te kryej me teper gjera.
Sa i përket asajt pse nuk i perdorim proceset ne vend te fijeve, pergjigjja është se fijet ndajne fushen e njejte te adresimit, nuk kemi nevoje për te menduar për nderprerjet (interrupt-et), nuk kemi nevoje per te menduar per kalimin nga nje proces ne tjeter, dhe fijet na japin mundësi me te mire për te menduar procesimin paralel. Gjithashtu fijet jane lehte per t’u formuar, lehte per t’u shkatruar, dhe jane shume me te shpejta prej proceseve. Gjithashtu fijet nuk ndikojne ne performancen.  

Te marrim një shembull nëpërmjet te cilit me se miri mund te kuptojme fijet. Te marrim “word procesor-in” qe na paraqet dokumentet, ku dhe gjithashtu mund te shkruajmë. Ne qofte se duam te skruajm ndonje lbier, nga pikepamja e autorit, me mire do te ishte qe libri te ruhet ne një fajll te vetëm, për kërkim me te lehte. Ndersa kemi edhe alternativen tjeter qe librin mund ta ndajme ne disa fajlle (psh varesisht sa kapituj ka libri). Dhe ne rast kur do te bejme ndonje nryshim te standardit, ne rastin e par qe kemi librin ne nje fajll te vetem, ndryshimi qe te behet është me lehte, ndërsa ne rastin tjeter ndryshimi duhet te behet ne cdo fajll.
 
Te marrim parasysh cfarë do te ndodhe ne qofte se shrytzuesi fshin nje fjali ne faqen 800, dhe pastaj ne qofte se nevojitet te fshihet diçka edhe ne faqen 600, gjate kesaj kohe kur word procesorit i behet thirje qe te fshije edhe ne faqen 600, duhet nje kohe e caktuar qe te kalohet nga faqja 800 ne faqen 600. Tash do t’i kemi ne perdorim fijet. Te supozojme se word procesori ka 2 fije, nje fije qe është interaktive me shfrytzuesin dhe nje fije tjeter per riformatimin qe ndodh ne prapavij. Fija interaktive i tregon fijes per riformatim qe te beje riformatimin e librit, ndersa nderkohe fija interaktive i lejon shfrytezuesit apo i pergjigjet shfrytezuesit ne komandat qe ben, siç është lëvizja e faqes me ane te kursorit etj. Ndersa fija tjeter nderkohe do t’a riformatoje librin dhe do t’a paraqese ate. Pra gjithashtu mund te shtojme edhe nje fije te trete qe do te n’a nevojitet per ruatjen e dokumentit qe shkruajme apo bejme dicka, por kjo fije do te beje ruatjen ne cdo kohe te caktuar, qe do te thote periodikisht.  

Kemi edhe shembull tjeter duke u bazuar ne serveret e faqeve, ku kemi te bejme me kerkimin e faqeve, ne qofte se nje faqe e kemi hapur me shpesh, ate do t’a kemi te vendosur ne kesh (cache memory). Ne rastin kur kemi ndonje kerkese ne server, kemi fijen “dispatcher” qe ben leximin e kerkesave qe vijn. Pastaj kemi edhe fijen tjeter “worker thread”, e cila nxitet nga fija dispatcher qe faqja e kerkuar te lexohet nga keshi (cache memory) dhe ne qofte se nuk është aty te lexohet ne disqe dhe blloqe tjera. 
Tash mund t’a kemi te qarte ate se per cka n’a nevojitet fijet.

## Implementimi i Fijeve te Ekezekutimit ne Pjesen e Shfrytezuesit 
Kemi dy lloje te implementimeve sa i perket fijeve, ate ne pjesen e perdoruesit (user space) dhe ne pjesen e kernel-it. Gjithashtu kemi te mundshëm edhe implementimin hibrid.  

Metoda e implementimit te fijeve ne pjesen e perdoruesit ka te beje me paketat e fijeve qe vendosen brenda saj. Ne kete rast kernel-i nuk din asgjë se çka ndodhet ne pjesen e perdoruesit, dhe gjithashtu ne kete rast keto fije munden te implementohen edhe ne sistemet operative qe nuk përmbajnë ato fije. Fijet menaxhohen ne pjesen e perdoruesit, dhe cdo process ka tabelen private per cdo fije, per te mbajtur nje rend për fijet qe ekzekutohen. Kur nje fije ben dicka ajo edhe mund qe te bllokohet lokalisht, psh duke pritur per ndodnje fije tjeter, dhe ne këtë mënyre bën thirje te procedures run-time sistemin, dhe ky sistem kontrollon ate se a duhet qe ajo fije te bllokohet, dhe ne qofte se duhet e vendos ate ne tabelen e fijeve, ku dhe merr fijen tjeter qe është gati per te ekzekutuar. Gjithashtu pjesa e perdoruesit (user space) ka një perparesi tjeter sepse ajo i lejon cdo procesi te beje rradhitjen e fijeve se kur do te ekzekutohen(scheduling). Nje nder problemet qe e ka pjesa perdoruesit ka te beje me implentimin e sistemit te thirjeve te bllokuara. Kodi per kontrollimin e thirjeve sistemore janë te vendosura ne te ashtuquajturen “jacket” ose “wrapper”.  

Një problem tjetër ne pjesen e perdoruesit(user space) e kemi se perderisa ekzekutohet nje fije, nuk mund te ekzekutohet fije tjeter deri sa ajo fije qe ekzekutohet te dorezohet vet.  

Gjithashtu një dizavantazh tjeter është se progameret tentojne qe fijet ti bejne sa me te sakta ne aplikacionet, ku fijet bllokohen shpesh, si psh ne serveret e faqeve.

## Implementimi i Fijeve te Ekezekutimit ne Pjesen e Kernel-it 
Ne implementimin e fijeve ne kernel nuk kemi tabele te fijeve (thread table) per cdo process, por kemi tabele per gjitha fijet ne sistem, ku fijet mund te krijohen, shkatrohen etj. Tabela e fijeve ne kernel permban regjistrat, gjendjen dhe informacione tjera. Kur nje fije bllokohet ne kernel, kernel ka opcionin e vet qe mundet te zgjedhe fije tjeter per ekzekutim nga i njejti proces ose ndonje proces tjeter.

## Implementimi Hibrid 
Janë bere disa përpjekje per te pasur nje implementim me te mire te fijeve duke marre perparsit te implementimit ne zonen e perdoruesit (user space) dhe perparesit ne nivelin e kernelit. Nje menyre është duke marre fijet nga kernel-i, pastaj fijet qe jane ne pjesen e përdoruesit te multipleksohen me te gjitha fijet qe jane ne kernel apo me disa prej tyre.
 
Sipas këtij dizajni kernel mund te radhise ekzekutimet vetem per ato fije qe ndodhen ne kernel. Disa nga keto mund te kene edhe fije nga pjesa e përdoruesit. Ne kete model cdo fije nga zona e kernel-it ka nje grup te fijeve nga zona e perdoruesit qe i perdor ato.

## Fijet e Ekzekutimit Pop-Up 
Fijet gjithashtu janë te nevojshme edhe për sistemet distributive. Sa i perket pop-up fijeve mund t’i sqarojme duke marrur nje shembull për ardhjen e nje mesazhi. Gjate ardhjes se një mesazhi sistemi krijon nje fije tjeter qe e mban ate mesazh, dhe kjo fie quhet pop-up thread (fije).

## Referimet 
* [1] Bekim Fetaji, majlinda Fetaji (2011) Sistemet Operative
* [2] Andrew S. Tanenbaum (2004) “Modern Operating Systems, 4/E” Prentice Hall