You are on page 1of 269

SSTEM PROGRAMLAMA ve LER C UYGULAMALARI

KAAN ASLAN

Bu notlar C ve Sistem Programclar Dernei bnyesinde verilen Sistem Programlama ve leri C Uygulamalar - I dersinde Ahmet Boa tarafndan tutulan notlardr. Notlarn hazrlanmasnda eski notlardan da yararlanlmtr. Notlar zerinde dzeltmeler yaplmamtr. nerileriniz iin mail adresim: bozcaa@yahoo.com

C ve SSTEM PROGRAMCILARI DERNE Mecidiyeky STANBUL www.csystem.org 05.04.2008

NDEKLER 1.

Sayfa

GR....................................................................................................................................7 1.1. ok Kullanlan letim Sistemleri ................................................................................7 1.2. Yazlm Gelitirme Sreci ............................................................................................8 1.3. Standartlardaki nemli Kavramlar............................................................................8 1.4. Standartlara Uyum ve Derleyici Mesajlar..................................................................9 1.5. Okunabilirlik ..............................................................................................................10 1.6. Macar Notasyonu .......................................................................................................12 2. BMSEL DLLER ve PROGRAMLAMA DLLER...................................................13 2.1. Sentaks Aklama Notasyonlar .................................................................................14 3. EVRC PROGRAMLAR ve DERLEYCLER..........................................................14 3.1. Derleme lemi ............................................................................................................15 4. PROGRAMLAMA DLLERNN STANDARTLARI.....................................................17 4.1. C Standartlar.............................................................................................................17 4.2. C99 Standartlarna Eklenen Tipik Farkllklar ........................................................18 4.3. Derleyici Eklentileri....................................................................................................19 4.4. C++ Standartlar ........................................................................................................19 5. C# ve JAVA SSTEMLERNDEK ARAKOD ALIMASI..........................................19 6. BMSEL DL..................................................................................................................21 6.1. BNF Notasyonu...........................................................................................................22 6.2. Programlama Dillerindeki Sentaks ve Semantik Kstlamalar.................................27 6.3. C de Operandlarn Yapl Sras..............................................................................28 6.4. Bildirim lemi ............................................................................................................29 7. FONKSYON GSTERCLER (POINTER To FUNCTIONS) ...................................32 7.1. Fonksiyon Gstericisi Yolu ile Fonksiyonlarn arlmas.......................................35 7.2. Fonksiyon Gstericilerinin Fonksiyon Parametresi Olarak Kullanlmas ...............36 7.3. Fonksiyonlarn Fonksiyon Adresine Geri Dnmesi Durumu ...................................37 7.4. Fonksiyonlarn Gstericilerine likin Dier Durumlar ...........................................39 7.5. Fonksiyon Gstericileri Neden Kullanlr?................................................................43 7.6. Trden Bamsz lem Yapan Yeni Amal Fonksiyonlarda Fonksiyon Gstericilerinin Kullanlmas ................................................................................................43 8. C nin STANDART TR SMLER................................................................................46 8.1. size_t Tr ..................................................................................................................46 8.2. ptrdiff_t Tr .............................................................................................................46 8.3. time_t Tr .................................................................................................................46 9. OK KULLANILAN ETL C FONKSYONLARI...................................................47 9.1. remove Fonksiyonu ....................................................................................................47 9.2. rename Fonksiyonu ....................................................................................................47 9.3. mkdir Fonksiyonu ......................................................................................................47 9.4. chdir Fonksiyonu ........................................................................................................48 9.5. rmdir Fonksiyonu.......................................................................................................48 9.6. access Fonksiyonu.......................................................................................................48 9.7. Geici Dosya Aan Fonksiyonlar ...............................................................................49 9.7.1. tmpfile Fonksiyonu .............................................................................................49 9.7.2. tmpnam Fonksiyonu ...........................................................................................49 10. HANDLE SSTEMLER ...............................................................................................52

10.1. Handle Sistemini Aan Fonksiyonlar.....................................................................52 10.2. Handle Sistemini Kullanan Fonksiyonlar..............................................................52 10.3. Handle Sistemini Yok Eden Fonksiyonlar.............................................................53 11. CACHE SSTEMLER ..................................................................................................53 11.1. Sistem Programlama Uygulamalarnda Karlalan Tipik Cache Sistemleri .....55 11.2. C nin Standart Dosya Fonksiyonlarnn Kulland Cache Mekanizmas............57 12. PROSES KAVRAMI......................................................................................................60 12.1. Proseslerin Bloke Olmas........................................................................................63 12.2. Preemptive ve Non-Preemptive ok Prosesli Sistemler........................................64 12.3. Modern letim Sistemlerindeki Koruma Mekanizmas .......................................65 12.4. Standart Dosya Fonksiyonlarnn Tamponlama lemlerinin Ayrntlar ............67 12.5. Proseslerin Adres Alan ..........................................................................................68 13. STDIN, STDOUT ve STDERR DOSYALARI ..............................................................69 13.1. Ynlendirme lemi ................................................................................................70 13.2. Stderr dosyasnn kullanlmas...............................................................................72 13.3. Stdin, stdout ve stderr dosyalarnn tamponlama mekanizmalar........................73 13.4. Stdout zerindeki tamponlamann etkisi ...............................................................73 13.5. Stdin zerindeki tamponlamann etkisi .................................................................74 13.6. C nin Stdinden Okuma Yapan Fonksiyonlar ......................................................75 13.6.1. getchar Fonksiyonu.............................................................................................76 13.6.2. gets Fonksiyonu...................................................................................................76 13.6.3. scanf Fonksiyonu ................................................................................................79 13.7. Stdin Tamponunun Boaltlmas............................................................................82 13.8. gets Fonksiyonu Yerine fgets Fonksiyonunun Kullanlmas .................................84 14. ALGORTMA ANALZ...............................................................................................84 14.1. Algoritmann Karmakl ....................................................................................86 15. TEMEL VER YAPILARI ............................................................................................88 15.1. Kuyruk Veri Yaps ..............................................................................................889 15.1.1. Kuyruk Veri Yapsnn Kullanm Alanlar ........................................................89 15.1.2. Kuyruk Veri Yapsnn Gerekletirilmesi ........................................................90 15.1.2.1. Dizi Kaydrma Yntemi ile Kuyruk Yapsnn Gerekletirilmesi90 15.1.2.2. Dngsel Yntem ile Kuyruk Yapsnn Gerekletirilmesi...93 15.1.2.3. Bal Liste Yntemi ile Kuyruk Yapsnn Gerekletirilmesi...............95 15.2. Veri Yaplarnn Trden Bamsz Hale Getirilmesi.............................................96 15.3. Bal Listeler...........................................................................................................98 15.3.1. Bal Listelerin Kullanm Alanlar.....................................................................99 15.3.2. Bal Listeler ile Dizilerin Karlatrlmas ......................................................99 15.3.3. Tek Bal ve ift Bal Listeler ........................................................................100 15.3.4. Bal Listelerin Gerekletirilmesi ...................................................................101 15.3.5. Tek Bal Listelerin Handle Teknii ile Gerekletirilmesi ............................102 15.3.6. Bal Listenin Dolalmas ................................................................................103 15.3.7. Bal Listenin Sonuna Eleman Eklenmesi .......................................................104 15.3.8. Bal Listeye Eleman Insert Edilmesi ..............................................................105 15.3.9. Listeden Eleman Silinmesi................................................................................106 15.3.10. Bal Listelerin Genelletirilmesi .....................................................................108 15.3.11. Genel Bal Liste Oluturulmasnda Dier Bir Yntem.................................110

15.4. Stack Sistemleri ....................................................................................................112 15.4.1. Stack Sistemlerinin Kullanm Alanlar ............................................................112 15.4.2. Stack Sisteminin Gerekletirilmesi .................................................................113 15.5. Hash Tablolar ......................................................................................................116 15.5.1. Sral Yoklama Yntemi (Lineer Probiny).......................................................117 15.5.2. Hash Fonksiyonlar...........................................................................................118 15.5.3. Hash Tablolarnn Kullanm Alanlar..............................................................118 15.5.4. Hash Tablolarnn Gerekletirilmesi ..............................................................119 15.6. Arama lemlerinin Temelleri ..............................................................................121 15.7. Aa Yaplar ........................................................................................................123 15.7.1. Dengelenmemi kili Aacn Oluturulmas ....................................................126 16. ZYNELEMEL ALGORTMALAR VE KEND KENDN AIRAN FONKSYONLAR...................................................................................................................128 16.1. zyinelemeli Fonksiyon rnekleri ......................................................................129 17. PROSESLER ARASINDA ALTLIK STLK LKS .........................................145 17.1. Proseslerin evre Deikenleri (Environment Variables) ..................................146 17.2. Prosesin Default alma Dizini.........................................................................1499 18. PROSESLER ARASI HABERLEME.......................................................................151 18.1. A Kavram ve Tarihsel Geliimi.........................................................................152 18.2. Protokol Kavram ve Protokol Katmanlar .........................................................153 18.3. TCP/IP Protokol Ailesi .........................................................................................156 18.3.1. TCP ve UDP Protokolleri .................................................................................156 18.4. Client-Server alma Modeli ..............................................................................158 18.5. Soket Arayz.......................................................................................................159 18.6. WinSock Arayz.................................................................................................160 18.6.1. WinSock Arayz in lk ve Son lemler......................................................160 18.7. Server Programnn Organizasyonu ....................................................................162 18.7.1. socket Fonksiyonu.............................................................................................163 18.7.2. bind Fonksiyonu ...............................................................................................164 18.7.3. listen fonksiyonu ...............................................................................................166 18.7.4. Accept Fonksiyonu............................................................................................167 18.8. Client Programn Organizasyonu ........................................................................168 18.8.1. Connect Fonksiyonu .........................................................................................169 18.8.2. Server IP adresini sockaddr_in yapsna yerletirilmesi .................................170 18.8.3. Send ve Receive lemleri .................................................................................172 18.8.4. Soketin Kapatlmas..........................................................................................174 18.9. Client-Server Uygulamalarda Dzenli Bilgi Gnderilip Alnmas .....................175 18.10. ok Clientli Uygulamalar ....................................................................................177 19. THREADLER ..............................................................................................................179 19.1. Threadli almann Avantajlar .........................................................................180 19.2. Threadlerin Bellek Alanlar .................................................................................180 19.3. Threadler zerinde lemler ................................................................................181 19.4. Windows Sistemlerinde Thread lemleri............................................................181 19.4.1. CreateThread Fonksiyonu................................................................................181 19.4.2. Threadlerin Sonlandrlmas ............................................................................183 19.5. Threadlerin Senkronizasyonu ..............................................................................184

19.5.1. Kritik Kodlarn Oluturulmas ........................................................................184 19.5.2. Windows Kernel Senkronizasyon Nesneleri ....................................................187 19.5.3. WaitForSingleObject Fonksiyonu....................................................................187 19.6. Event Nesnelerinin Kullanm ..............................................................................188 19.7. retici Tketici Problemi ................................................................................. 18989 19.7.1. retici Tketici Probleminin Event Nesneleri le zm.............................189 19.7.2. Semafor Nesneleri .............................................................................................190 19.7.3. ok Tamponlu retici-Tketici Problemlerinin Semafor Nesneleri le zmlenmesi ..................................................................................................................192 19.8. Mutex Nesneleri ....................................................................................................193 19.9. ok lemcili alma ...........................................................................................194 19.10. volatile Nesnelerin ok Threadli almalarda nemi ......................................197 19.11. Windows Sistemlerinde Thread izelgelemesi ....................................................198 20. DERLEYCLERN KOD OPTMZASYONU.........................................................199 20.1. l Kod Eliminasyonu (Death Code Elimination)..............................................200 20.2. Gereksiz Kodlarn Elemine Edilmesi ...................................................................201 20.3. Ortak Alt fadelerin Elemine Edilmesi (Common Subexpression Elemination)202 20.4. Sabit fadesi Yerletirme (Constant Folding) ......................................................202 20.5. Sabit fadelerinin Yaydrlmas (Const Propegation)..........................................203 20.6. Ortak Blok (Basic Block)......................................................................................203 20.7. Gstericilerin Eliminasyonu.................................................................................204 20.8. Inline Fonksiyon Am.........................................................................................205 20.9. Dng Deimezleri (Loop Invariants) ................................................................206 20.10. Dng Am (Loop Unrolling) ............................................................................207 20.11. Dng Ayrmas (Loop Splitting).........................................................................208 20.12. Kod retimi Aamasnda Yaplan Optimizasyonlar...........................................208 20.13. Yazma Tahsisat (Register Allocation)...............................................................209 20.14. Komut izelgelemesi (Instruction Scheduling) ...................................................209 20.15. Derleyicilerin Optimizasyon Seenekleri .............................................................209 20.15.1. Microsoft Derleyicilerindeki Optimizasyon Seenekleri .................................210 20.15.2. GCC Derleyicilerindeki Optimizasyon Seenekleri.........................................211 21. BELLEK LEMLER ................................................................................................212 21.1. kincil Bellekler.....................................................................................................214 21.2. Disk lemleri ........................................................................................................214 21.3. Disk IO lemi .......................................................................................................216 21.4. Sektr Transferi leminin Programlama Yolu ile Gerekletirilmesi ...............217 21.5. Sektrlerin Numaralandrlmas ..........................................................................218 21.6. letim Sistemlerinin Dosya lemlerine likin Disk Organizasyonlar .............218 21.7. Cluster yada Blok Kavrami.....219 21.8. eitli letim Sistemlerinin eitli Disk Organizasyonlar......222 21.9. Disk Organizasyonlar Fat Trevi Dosya Sistemlerinin Disk Organizasyonlar222 21.10. Boot Sektr....223 21.11. Sektr okuma yazma ilemleri....227 21.12. BPB blmnn Elde Edilmesi.......228 21.13. Fat Blm................................................................................................................229 21.14. Fat Elemanlarndan bir catch sisteminin oluturulmas.......231

21.15. Cluster Okuma Yazma lemleri.....234 21.16. Rootdir Blm ve Dizin Organizasyonu...235 21.17. Alt Dizinlerin Organizasyonu ve Yol fadesinin zlmesi lemi..237 21.18. Formatlama lemi238 21.19. Fat Dosya Sistemine likin Disk Organizasyon Bozukluklar.239 21.20. Disk Blmleme Tablosu ve Disk Blmlerinin Anlam..240 21.21. letim Sistemimin Yklenmesi ve Boot lemi..243 21.22. I-Node Dosya Sistemlerine likin Disk Organizasyonun Genel Yaps..245 22. KESME LEMLER..247 22.1. IRQ Kaynaklar..249 22.2. IRQ Kesme Kodlarnn Set Edilmesi....................................................................254 22.3. Yardmc lemciler.....254 22.4. Paralel Port Kullanm............................................................................................257 22.5. Paralel Portta Veri Transferi.259 22.6. Seri Haberleme...261 22.7. Hatalarn Belirlenmesi zerine Yntemler...264 22.8. assert Makrosunun Kullanm ve Projelerin Delay ve Release Versiyonlar.265 22.9. Deiken Syda Parametre Alan Fonksiyonlar.267

1. GR
yi bir C programcs en az u zelliklere sahip olmaldr:

Hkimiyet: Programc, C dilinin kurallarna hkim olmaldr. Uygulama konularnda deneyim: yi bir C programcs pek ok uygulama konusunda bilgi ve deneyim sahibi olmaldr. Analiz yetenei: yi bir C programcs problemi iyi bir biimde modellemeli, admlarna ayrmal ve kodlama srasnda ciddi problemlerle karlamadan kodlamay bitirmelidir. Fiziksel ve ruhsal kondisyon: yi bir C programcs, uzun sre hatta sonulandrana kadar bir projede alabilecek kadar kondisyon sahibi olmaldr. Bazen ayn projede aylarca almak gerekebilir.

1.1. ok Kullanlan letim Sistemleri

Win16 sistemleri, Windows 3.x sistemleridir ve artk neredeyse tamamen kullanmdan kalkmlardr. Win32 sistemler ise; Windows 95, 98, ME, NT, 2000, XP dir. Win32 sistemleri 95 grubu ve NT grubu sistemler olmak zere 2 gruba ayrlabilirler. Windows 95, 98, ME iin 95 grubu, NT, 2000 ve XP iin NT grubu iletim sistemleri denilebilir. UNIX, AT&T Bell laboratuarlarn da oluturulmutur. Kaynak kodlar, bir aratrma projesi olarak oluturulup serbest olarak datld iin, eitli kurum ve kurulular tarafndan ezamanl olarak kullanlm ve gelitirilmitir. En nemlileri: Berkeley BSD, Sun Solaris, HP-UNIX sistemleri, SCO-UNIX ve Linux sistemleridir. Bu sistemlerin hepsi, farkllklar olmasna ramen, benzer mimarilere sahiptir. UNIX sistemleri bir arabirim erevesinde standart hale getirilmeye allmtr. POSIX (Portable Operating System Interface for UNIX) UNIX standartlarna verilen isimdir.

1.2. Yazlm Gelitirme Sreci

Kk yazlmlarda sezgisel yntemler kullanlabilir ancak byk yazlmlarda, gelitirilme srecinin ok kii tarafndan yapld durumlarda bir sistematik izlenmelidir. Genellikle sezgisel ya da bilinli olarak izlenen sistematik aamalardan oluur. Bu aamalar unlardr: 1. Sistem Analizi: ncelikle yazlmn ne yapmas gerektii, yani yazlmdan istenenler iyi tespit edilmelidir. Bu aamada genellikle istekler yanl, eksik ya da belirsiz bir biimde belirlenir. 2. Belirlemelerin Yaplmas: Sistemin analizi yapldktan sonra istenen eylerin spesifikasyon biiminde resmi ya da yar resmi olarak belirtilmesi gerekir. 3. Tasarm: Bu aamada yazlmn tasarm yaplr yani proje hangi modllerden oluacaktr, bu modller ne i yapacaktr, hangi programlama dil ve aralar kullanlacaktr gibi sorular cevaplanr. 4. Kodlama: Bu aamada, tasarm yaplm olan yazlmn gerek kodlamas yaplr.

5. Test: Yazlmn aa seviyeli ve yksek seviyeli testleri kodlama aamasna paralel olarak yrtlr. 6. Bakm: Yazlm kullanlmaya baladktan sonra eitli ksmi gelitirmeler, dzeltmeler yaplabilir ve kullanm hizmetleri verilebilir

1.3. Standartlardaki nemli Kavramlar

Implementation-Defined (Implementation-Dependent) Behavior: Bir durum standartlarda bu ekilde belirtilmise, bu konu derleyicileri hazrlayanlarn inisiyatifine braklmtr. Bu durumlar derleyiciyi yazanlar tarafndan belgelenmek zorundadr. rnein int trnn uzunluu implementation dependent biimindedir. Minimum limitleri verilmitir ama gerek uzunluk derleyiciyi yazanlara braklmtr. Derleyiciyi hazrlayanlar bu seimi nasl yaptklarn belirtmek zorundadrlar. Undefined Behavior: Yorumlanmas derleyiciden derleyiciye deiebilen ve genellikle anlamsz olan durumlar belirtir. Bu durumlara kar derleyicinin davran standartlarda undefined behavior olarak belirtilmitir. Derleyiciyi hazrlayanlar bu tr ilemleri nasl yorumladklarn belgelemek zorunda deillerdir. rnein:
result = ++a + ++a;

Tipik bir undefined behavior durumudur. Unspecified Behavior: Implementation-dependent behavior a benzer, birka olaslk sz konusuyken, derleyicinin hangi olasll tercih ettiinin belirsiz olduu durumdur. Olaslklar snrldr, seeneklerin hepsi mantkldr, ancak derleyiciyi hazrlayanlar seimlerini belgelemek zorunda deildirler. Diagnostic Message: Standartlara gre belirtilen sentaks ve semantik kurallarna uymayan durumlar derleyici tarafndan tespit edilerek bir mesaj olarak gsterilmelidir. Bu mesaja diagnostic message denir. Standartlarda, mesajn ne olmas gerektii, yani uyar ya error olmas gerektii belirtilmemitir. Yalnzca bu tr durumlarda bir mesaj vermesi gerektii belirtilmitir.

1.4. Standartlara Uyum ve Derleyici Mesajlar

C90 ve C99 standartlarnda C programlama dilinin kurallar sentaks ve semantik bakmndan aklanmtr. Bu standartlar, bir programn kurallara uymamas durumunda derleyicinin hangi kuraln ihlal edildiine dair bir tehis mesaj vermesi gerektiini belirtmilerdir. C90 ve C99da yanl yazlm bir programn derlenmemesi gerektii veya doru yazlm bir programn da derlenmesi gerektii hakknda bir ey sylenmemitir. Yalnzca kurallara uyulmamas halinde derleyicinin bir tehis mesaj verilmesi gerektii belirtilmitir. Bu durumda standartlara uygun bir derleyici kurallara uyulmad durumda, ilemi uyar ile geitirerek derleme ilemini yapabilir ya da error vererek derleme ilemini yapmayabilir. Normalde derleyicinin warning ve error mesajlar geersiz kodlarda kullanlmaktadr. rnein bir gstericiyi dorudan bir int deikene atamak geersiz bir durumdur. Hemen hemen tm derleyiciler bu durumda warning verseler de aslnda derleme ilemini yapmayabilirler. Bir adresin farkl trden bir gstericiye dorudan atanmas standartlarca geerli olmadna gre derleyicinin vermesi gereken mesaj uyar veya error olabilir
char s[10]; int *pi = s;

Aslnda uygulamada baz mesajlar tipik uyar olarak deerlendirmektedir. C++ standartlarnda, kurallara uyulmamas durumunda bir mesajn yan sra programn da derlenmemesi gerektii belirtilmitir. Bylece C de uyar ile geitirilen pek ok durum C++'da error durumuna ykseltilmitir

1.5. Okunabilirlik

Bir programa bakldnda ne yaplmak istendiinin koly biimde anlalmasna okunabilirlik denir. Okunabilirlii salamak byk lde programcnn sorumluluu altndadr. Okunabilirlii salamak iin dikkat edilecek temel noktalar unlardr. 1. Kodun genel yerleimi (tablamalar, indentler) dzgn ve tutarl olmaldr. Tablama konusunda eitli yaygn kullanlan biimler vardr. 2. Programn kk mantksal lmleri satr boluklar verilerek bloklanabilir.

10

3. Kaynak kodun gerekli yerlerine aklamalar yerletirilmelidir. Aklamalar ksa cmleler biiminde olmal ve kritik noktalara yerletirilmelidir. Aklamalar kk soru cmleleri biiminde oluturulabilir veya bloklarn balarna yerletirilebilir. 4. Balk dosyalarnn ve kaynak dosyalarnn bana balk ksm yerletirilmelidir. rnek bir balk ksm u ekilde olabilir:
/***** FILE AUTHOR LAST UPDATE PLATFORM TRANSLATOR : : : : : general.h Kaan ASLAN 22/11/2002 Any Any

This is the general header file prepared for project groups of the C and System Programmers Association (CSD) Copyleft (c) 1993 by C and System Programmers Association (CSD) All Rights Free *****/

5. Program ierisindeki sabitler anlaml bir biimde sembolik sabitler biiminde ifade edilmelidir. rnein:
if (n == PERSONELSAYISI) { /*****/ }

6. Deikenler anlaml bir biimde isimlendirilmelidir. Deiken isimleri hangi konuya ilikin olduu hakknda fikir vermelidir. simlendirmede tutarllk olmaldr. Programn farkl blmlerinde ayn isimler ayn anlam ifade edecek biimde kullanlmaldr 7. Kullanlan tr isimleri konuya uygun bir biimde seilebilir yani tr isimleri de onlarn hangi konuda kullanldn aklayacak biimde olabilir.

11

1.6. Macar Notasyonu

Macar notasyonu, temel olarak bir deikenin isimlendirilmesine ilikin kurallar ieren bir belirlemeler topluluudur. Charles Simone tarafndan oluturulmutur. Microsoft API

programlama sisteminde ve SDK (software development kit) ierisinde bu notasyonu kullanmaktadr. Macar notasyonunun en nemli zellii deiken isimlerinin, deikenin trn belirten bir nekle balatlmasdr. Macar notasyonunun ana noktalar unlardr. Fonksiyon isimleri, her szcn ilk harfi byk olacak ekilde nce bir fiil, sonra nesnesi gelecek ekilde isimlendirilir. Her deiken, hangi trden olduunu belirten neklerle balatlr. nekler kk harflerden oluturulur, neklerden sonra her szcn ilk harfi byk yazlr.

nek c l d s f u b f

Tr char long double short float unsigned int BOOL flag

nek p pc pl pv psz (zero terminated string b w dw

Tr pointer char * long * void * Yaz gsteren char * BYTE WORD DWORD

rnein:
DWORD dwMaxSector; long lResult; BOOL bValid; PSTR pszName;

12

PVOID pvBlock;

Maalesef Macar notasyonunda isimler uzama eilimindedir. int trden deikenler, dizi isimleri, yap isimleri genellikle nek almazlar, bunun yerine ilk szcn tamam kk harflerle yazlr, varsa sonraki szcklerin ilk harfleri byk yazlr. Yap trnden nesneler bazen yapnn trne ilikin kk nekler alrlar. rnein:
RECT rectWindowPos; POINT ptLeftTop;

Genellikle global deikenler g_ , statik deikenler s_ ve C++ dilinde snfn veri elemanlar m_ ile balayarak isimlendirilirler. Bu eklerden sonra tr belirten bir nek daha getirilir. Macar notasyonu ok kat uygulandnda bazen uzun ve can skc hale gelebilir. Programclar baz gevetmeler yaplabilir. rnein baz nemli deikenlerin nne tr belirten nekler getirilir. Macar notasyonu ile yazlm bir rnek program:
#include <stdio.h> #include <general.h> PVOID CopyMemory(PVOID pvDest, PCVOID pvSource, DWORD dwSize) { PBYTE pDest = (PBYTE) pvDest; PBYTE pSource = (PBYTE) pvSource; while (dwSize-- > 0) *pDest++ = *pSource++; return pvDest; } int main(void) { char szCity1[50] = "Ankara"; char szCity2[50]; CopyMemory(szCity2, szCity1, strlen(szCity1) + 1); puts(szCity2); return 0;

2. BMSEL DLLER ve PROGRAMLAMA DLLER

13

Doal diller ile programlama dilleri birbirine ok benzer. Bir dilin tm kurallarna gramer denir. Gramer = Sentaks + Semantik + Morfoloji + Etimoloji Sentaks, doru yazlm kurallardr. Semantik, doru yazlm olan yazlarn ne anlama geldii hakkndaki kurallardr. Sentaks kurallar matematiksel formller ile aklanyor ise bu dillere biimsel (formal) diller denir. Programlama dilleri biimsel diller grubuna girer. Doal diller ok fazla iki anlaml eler ierdiinden dolay kesin bir sentaks ifadesi matematiksel bakmdan mmkn deildir. Biimsel diller zerinde en nemli almalar Noam Chomsky tarafndan yaplmtr (50li yllarda). BNF Sentaks ifade etmek iin kullanlr.

2.1. Sentaks Aklama Notasyonlar

Programlama dillerinin ou Chomsky kategorisine gre balam-bamsz(context-free) dillerdir. Balam-bamsz dillerin sentaks gsterimi iin eitli yntemler nerilmitir. En ok kullanlan BNF (Backus Nover Form) denilen yntemdir. ISO bunu EBNF(Extended BNF) olarak standardize etmitir.
Anahtar Notlar: C derslerinde [ ] ve < > teknii kullanld. < > ierisinde bulunan eler kesinlikle bulunmas gereken elerdir. [ ] ierisinde bulunanlar istee bal eleri belirtir. if (<ifade>) <deyim> [else <deyim> ] Anahtar Notlar: Formal Language, Auto Theory ismi verilen ana konular biimsel dillerin teorik temelini konu almaktadr.

3. EVRC PROGRAMLAR ve DERLEYCLER

14

Bir dilde yazlm bir program edeer olarak baka bir dilde yazlm programa dntren programa evirici program denir. Bir evirici programda hedef dil aa seviyeli bir dil (saf makine dili, ara kod, sembolik makine dili) ise bu eit eviri programlara derleyici (compiler) denir. Derleyiciler bir eit evirici programlardr. Bir programlama dilinde yazlm program zerinde herhangi bir ilem uygulayan programlara dil ilemcileri(language processors) denir.

Compiler

Baka bir sistem iin kod reten derleyicilere apraz derleyici (cross compiler) ismi verilir. rnein PC de kod yazp daha sonra PIC lerde altrdmz kodlar derleyen derleyiciler bu gruba girer. Baz dil ilemcileri kaynak kodu okuyup hi hedef kod retmeden o anda yorumlayp altrabilmektedir. Bu tr programlara yorumlayc (interpreter) denir. BASIC, Lisp, AWK gibi dillere ynelik ilemciler yorumlayc yntemler ile almaktadr. Yorumlayclarn derleyicilere gre ok daha kolay yazlmas gibi bir avantaj bulunurken, programlar daha yava altrmas gibi bir dezavantaj bulunur. Programlarn hzl almasnn nemli bir faktr olmad durumlarda yorumlayclar kullanlr. Yorumlayclar birer evirici program deildir.
Anahtar Notlar: IDE yazlm gelitirmeyi kolaylatran, kendi ierisinde editr, menleri ve eitli aralar olan yardmc programlardr. lk IDE yazan firma Borland tr(Borland 1.0). Microsoft un IDE si Visual Studio isimli rndr. KDevelop Linux ta kullanlan bir IDE dir. Eclipse, Netbeans, Dev-C++ IDE lerini de sk kullanlan IDE ler arasnda sayabiliriz.

3.1. Derleme lemi

15

Derleyici eitli modllerin birleiminden oluan bir program olarak dnlebilir. Derleme ilemi srasnda ilk aama kaynak kodlarn atomlarna(tokens) ayrlmasdr(lexical analysis, tokenizing). Atomsal analiz sonucunda elde edilen atomlar sentaks analizi yaplarak modle yollanr. Bu modl gelen atomlara bakarak programn geerli olup olmadna bakar. Derleyicinin bu ksmna parser (syntax analyzer) denir. Sentaks analizi srasnda program gramere uygun deilse hata mesajlar retilir. Sentaks analizi srasnda derleyici program ilenebilir veri yapsna dntrr. Buna ayrtrma aac(pars tree) denilmektedir. Sentaks analizinden sonra semantik analiz uygulanr. Doru yazlm her program(sentaksa gre) geerli deildir. Semantik analiz aamasnda eitli semantik kurallara uygunluk kontrol edilir. rnein ayn isimli deikenlerin tanmlanmamas, bir fonksiyonun ayn miktarda girdi ile arlmas, bir gstericiye ayn trden adres atanmas semantik kuraldr. Bu modl (lexical analysis, syntax analysis, semantic analysis), derleyicinin n yz(front end) dr. n yz genel anlamada analiz ii yapar. Pek ok derleyicide bir sonraki modlde ara kod retimi yaplr. Ara kod ayrtrma aacnn hedef koda daha yakn bir biimidir. (Ara-kod retimi, Intermediate Code Generation) Derleyicinin bir sonraki modlnde programcnn yazd kod iyiletirilir. Buna kod optimizasyonu (code optimization) denir. Derleyicinin son modlnde iyiletirilmi koda baklarak hedef kod retilir. (code generation) Derleyicilerin n yzleri analiz arka yzleri senteze yneliktir. Derleyicilerin modllere ayrlmasndan nemli faydalar salanmtr. rnein M tane dil iin N tane ilemciye ynelik derleyici yazlmak istensin. Normalde M*N tane derleyici yazlmas gerekirken bu modllerin kullanm sayesinde M+N tane derleyici yeterli olur. Her dil iin bir n yz ve her bir ilemci iin bir arka yz yazmak yeterli olur. Derleyici piyasasnda kod optimizasyonu ve retimi en nemli unsurdur. Bu yzden bu modlleri iyi tasarlanan derleyiciler mteriler tarafndan daha ok rabet grr. Derleyiciler ok iyi test edilmelidir. nk dier sistem programlar da bunlar kullanlarak oluturulmaktadr.

16

Atom Analiz

Sentaks Analiz

Semantik Analiz

Ara-kod retimi

Kod Optimiz.

Kod retimi

n Yz Front End

Orta Yz Middle End

Arka YzBack End

Derleme Srecine likin Anahtar Szckler: Translator, Compiler, Language Processor, Lexical Analysis, Code Optimization, Code Generation, Pars Tree, Parsing, Front End, Back End, Compiler Parting, Cross Compiler, Compiler Development Project, gcc, lcc, tcc
Anahtar Notlar: Assembler monte eden anlamna gelir. Kaynak kodu sembolik makine dili, hedef kodu saf makine dili olan evirici programlara sembolik makine dili derleyicisi(assembler) denir.

4. PROGRAMLAMA DLLERNN STANDARTLARI


Standartlar bir dilin gramerini anlatan resmi dokmanlardr. Standartlar standardizasyon kurumlar tarafndan oluturulabildii gibi dili tasarlayan kiiler tarafndan ya da irketler tarafndan da oluturulabilir. Standartlarda dilin sentaks kurallar genelde BNF ya da trevleri ile ifade edilmektedir. Semantik kurallar hukuk diline benzeyen cmlelerle aklanr.

4.1. C Standartlar

17

C programlama dili 1970 71 yllarnda Dennis Ritchie tarafndan, Unix tabanl iletim sistemleri zerinde sistem programlama uygulamalar gelitirme arac olarak kullanlmak zere oluturuldu. 1973 ylnda UNIX, C ile tekrar yazld. C nin bir programlama dili olarak yaygnlamas ise 1980 1990 arasnda olmutur. ANSI, 1983te balad C yi standartlatrma almalarn 1989da tamamlad. Buna paralel, 1990da ISO tarafndan da standartlatrld. Bu standart, ISO/IEC 9899:1990dr ve ksaca C90 olarak bilinir. C en son, ISO tarafndan 1999 ylnda standartlatrlmtr. Bu standardn kodu 9899:1999dur ve ksaca C99 denir. Maalesef, bu son srm henz derleyiciler tarafndan tam olarak desteklenmemektedir. C99a C++tan zenilerek baz zellikler eklenmitir. Standart C fonksiyonlarnn neler olduu standartlarda belirlenmitir. Ancak derleyiciler, bu fonksiyonlarn dnda pek ok zel fonksiyon bulundurabilirler. Bu fonksiyonlardan bazlar derleyicilerin ounda bulunmaktadr. (itoa(), strupr(), strlwr()...gibi.)

4.2. C99 Standartlarna Eklenen Tipik Farkllklar

Yerel diziler deiken uzunlukta olabilir. Yerel deikenler bloun herhangi bir yerinde bildirilebilir.
int n; scanf("%d", &n); int a[n];

// ile satr sonuna kadar yorumlama yapma standartlatrlmtr. Normalde C90 standartlarnda yorum satrlar iin sadece /**/ kullanlabilir. long long ve _Bool trleri oluturulmutur (16 byte). restrict gstericiler kavram vardr. Yaplara ve dizilere ilk deer verirken ayrk elemanlara deer atanabilir.
struct SAMPLE s = {.a = 10, .c = 20};

18

Fonksiyonlarn geri dn deeri tr belirtme zorunlu hale getirilmitir. (implicit int kural kalkmtr.) Dizi ve yap trne tr dntrmesi uygulanabilmektedir.
struct sample s; s = (struct sample) {1, 2, 3};

Yeni standart C fonksiyonlar eklenmitir. nilemci komutlar iyiletirilmitir. Inline fonksiyonlar C99 a eklenmitir.

4.3. Derleyici Eklentileri

Bir C derleyicisi standartlara uygun olmas yan sra ek bir takm zelliklere sahip olabilir. Bu zelliklere derleyicilerin eklentileri (extensions) denilmektedir. Pek ok C derleyicisi ek birtakm ktphanelere ve anahtar szcklere sahiptir. Eer bu eklentiler geerli bir program geersiz hale getirmiyorsa derleyici standartlara uygundur. Aksi durumda standartlara uygun deildir.
Anahtar Notlar: C de ba _ ile balayan global faaliyet alanndaki tm isimler, ba __ ile balayan yerel ve global faaliyet alanndaki tm isimler ve ba _ ve sonraki ilk harfi byk olan tm isimler programcnn kullanm iin yasaklanmtr. Derleyiciler eklentilerini bu isimlerle semektedirler. Eer programc bu isimleri kullanrsa tanmsz davran (undefined behavior) olur. Pek ok derleyicide eklentiler eitli seeneklerle pasif hale getirilmektedir. Eer eklentiler aktifken standartlara uygunsuzluk karyor, fakat pasif iken karmyorsa bu derleyiciye standartlara uygundur diyebiliriz.

Derleyicilerin eklentilerini kullanmak tanabilirlii azaltr. rnein Linux iletim sistemi gcc derleyicisinin pek ok eklentisini kullanmaktadr. Bu durumdan dolay Linux gcc dnda bir derleyici ile derlenememektedir.

4.4. C++ Standartlar

19

C++ standartlar 1998 ylnda oluturuldu. ISO/IEC 14482:1998 kod ismi ile bilinir. 2003 ylnda dil zerinde bir takm dzeltmeler yaplm, dile yeni kurallar eklenmemitir. Bu standartlara ISO/IEC 14882:2003 kod ismi verilmitir. Son standart budur. C++ iin 2008 yl ierisinde bitirilmesi hedeflenmi olan yeni standartlar zerinde allmaktadr.

5. C# ve JAVA SSTEMLERNDEK ARAKOD ALIMASI


C# ve Java alma ortamlarndaki derleyiciler dorudan makine kodlar retmemektedir. Hibir ilemcinin makine kodu olmayan ve ismine ara kod denilen sahte makine kodlar retmektedir. rnein C# ta bir program derlendiinde belirli bir link aamas olmadan dorudan EXE uzantl bir dosya elde edilir. Fakat bunun ierisinde Intel makine kodlar deil sahte makine kodlar bulunmaktadr. .NET ve Mono ortamnda C# derleyicisinin oluturduu ara koda ILASM (Intermediate Language ASM) denilmektedir. Java dnyasnda Java Byte Code olarak isimlendirilmektedir. Gerek .NET, gerekse Java dnyasnda bu ara kodlar dorudan altrlamaz. Bir altrma ortamnn bu kodu yorumlayarak altrmas gerekir. Bu altrma ortamna .NET dnyasnda CLR(Common Language Routine), Java dnyasnda JVM(Java Virtual Machine) denir. Programn yorumlanarak baka bir yazlm tarafndan altrlmas performans kaybna yol amaktadr. Bunun yan sra ara kod ile almann nemli faydalar da bulunur. Binary Portability: altrlabilen kodun tanabilirlii salanm olur. Bylece bir program baka sistemlere gtrlerek altrlabilir. Tabi altrma ortamnn o sistemde kurulu olmas gerekir. Language Interoperability: Ara kodlu alma, diller arasnda entegrasyona iyi bir biimde destek vermektedir. rnein .NET ortamnda biz bir projeye C# ile balayp, projeyi VB.net ile devam ettirip, C++.net ile sonlandrabiliriz. Bir programda yazlm kodlarn baka bir kodla kullanlmas dual code temelinde ok zordur. Bunun iin Microsoft Com yntemini tasarladysa da bu yntem etkin olmaktan uzaktr. Kodlarn yorumlanarak almas daha gvenli bir alma sunmaktadr.

JIT: altrma ortamnn ara kodu yorumlamas nasl yaplmaktadr?

20

Ara kod komut komut yorumlanmaz. Fonksiyon fonksiyon yorumlanmaktadr. Bir fonksiyon ilk arldnda fonksiyon doal koda dntrlr ve daha sonra altrlr. Dntrlen fonksiyon bir cash sisteminde biriktirilir. Bu altrma srecine JIT(Just In Time Compilation) denir.

6. BMSEL DL
Teorik bakmdan biimsel bir dil, ismine terminal semboller denilen bir kmenin elemanlarndan oluturulan bir kmedir. Terminal semboller genellikle L sembol ile ifade edilir.
rnein:

sembol ile ifade edilir. Dil ise

= {a, b, c}
te terminal sembollerinin istenildii kadar birletirilmesi ile elde edilen kmelere dil denilmektedir.
rnein:

= {a, b, c}
L1 = {aaaa, bbab, ac} L 2 = {aaaaa, bbbbb, c} L3 = {a, ab, ba, aba, bab, aaab, baaa}

Bir dildeki terminal semboller snrl olmak zorundadr. Fakat dil ierisindeki elemanlar sonsuz sayda olabilir. Bu durumda elemanlar tek tek kme parantezi ierisinde yazmak mmkn olmaz.
rnein:

21

C bir dildir ve sonsuz sayda C program yazlabilir. C program iin

kmesi, C programnda

kullandmz tm karakterlerdir. C dili de tm geerli C programlarnn kmesidir. Biz C dilini

kme parantezleri ierisinde yazmaya alsak, geerli tm C programlar bu kme parantezi ierisine yerletirilmesi gerekir. L = {CP1, CP 2, CP3,...}
Tm C programlar sonsuz sayda olduuna gre C dilini bu ekilde tanmlamak mantkl deildir.

Basit bir dil kme parantezi ile yazlabilir. Fakat bir programlama dili iin baka yntemler bulunmaldr. te BNF ya da EBNF gibi notasyonlar temel olarak yukardaki gibi bir L kmesini tanmlamakta kullanlmaktadr. Biimsel dillerin bu konu ile uraan blmne Generate Grammar diyoruz. lk kurumsal almalar Chomsky tarafndan yaplm ve diller 5 gruba ayrlmtr.

6.1. BNF Notasyonu

BNF notasyonu zellikle balam-bamsz (context-free) dilleri retebilmek iin dnlm olan bir yntemdir. Bu yntemde bir kk sembol, bir grup ana sembol ve bir grup terminal sembol kullanlr. Kk sembolden balanarak eitli retim kurallar ile terminal sembollere kadar inilir. te dil kk sembolden balanarak oluturulan tm kmeyi kapsamaktadr. Ara sembol kurallar : ile aklanr. Veyalar ayr satrlara yazlabilir ya da ayn satrda | sembol ile ayrtrlabilir. Terminal semboller genellikle tek trnak ierisinde yazlr. Fakat birok programlama dilinin standard koyu veya italik yazm kullanr. Kk sembol ara semboller kmesi ierisinde bulunan bir semboldr. Dilin tm elemanlar kk sembolden balanarak ara sembollerden geilerek btn ara sembollerden kurtularak elde edilen terminal semboller kmesidir.
rnein:

= {a, b, c}
V = {X , Y , Z} S = {X }

22

X: YZ Y: a | Ya Z: b Y sembolnden hareketle dilin birka elemann retelim: X YZ Y a Y a b Y a a b a a a b aaab

number: digit | digit number digit: 0 | 1 | 2 | 3 | 4 | 5 |6 | 7 | 8 | 9

Burada kk sembol number, terminal semboller 0,1,,9 karakterleridir. Bu durumda 7, 17, 997, 49, 017 bu dilin elemandr.

dev: Number isimli bir BNF gramerini yaznz. Fakat ba 0 ile balayan saylar bu dilin eleman deildir. (0 bu dilin elemandr.) rnek olarak expression isimli bir dili BNF notasyonu ile tanmlamaya alalm.
Expression: Additive Expression Additive: Additive + Multiplicative | Additive - Multiplicative | Multiplicative

Multiplicative: Multiplicative * Primary | Multiplicative / Primary | Primary

Primary: Number | Variable

Soru: 3 + 5 * 8 ifadesi expression dilinin bir eleman mdr?

23

Soru: a + b + c bu dilin bir eleman mdr? Yant evet

Expression Additive Additive Multiplicative Primary + Multiplicative Primary Primary Variable + Multiplicative

Variable c

Soru: a * b * c bu dilin bir eleman mdr? Yant evet. Grld gibi verilen dilde * ve / ileminin + ve ilemine gre ncelii vardr. Bu ncelik gramerden kan doal bir sonutur. Gerekten de C standartlarnda operatr nceliinden bahsedilmez. Zaten BNF gramerinden kan doal sonu ncelik tablosunu oluturmaktadr. imdi yukarda expression dilini paranteze ncelik verecek ekilde gelitirelim:
Expression: Additive

24

Additive: Additive + Multiplicative | Additive - Multiplicative | Multiplicative Multiplicative: Multiplicative * Primary | Multiplicative / Primary | Primary Primary: Number | Variable | (Expression)

Soru: (3 + 5) * 8 bu dilin bir eleman mdr? Evet.

Soru: (3 + 5) * (8 2) Expression dilinin bir eleman mdr? Evet elemandr. Burada primary * primary durumuna gelinebilir. Sonra primary kural 3+ 5 ve 8 2 biiminde alabilir. imdi yukarda expression dilini ! operatrne ncelik verecek ekilde gelitirelim:

Expression: Additive Additive: Additive + Multiplicative | Additive - Multiplicative | Multiplicative Multiplicative: Multiplicative * Primary | Multiplicative / Primary | Unary Unary:

25

! Primary | Primary Primary: Number | Variable | (Expression)

Soru: !(a + b) * c Expression dilinin bir eleman mdr? Evet elemandr. Burada grld gibi a + b nin sonucu ! operatrne sokulup c ile arplmtr. Soru: !!!a Expression dilinin bir eleman mdr? Hayr deildir. Expression dilinin bunu aabilmesi iin aadaki gibi bir dzeltme yapmamz gerekir:

Unary: ! Unary | Primary

Grld gibi soldan saa ya da sadan solalk da BNF notasyonundan kartlan doal bir sonutur. a+b+c ilemi a+b ile c nin toplanaca anlamna gelir. nk bunu a ile b nin toplanaca biiminde aamayz. Yukardaki gramere iaret ve iaret + operatrleri de eklenebilir.
Unary: + Unary | - Unary | ! Unary | Primary

imdi bu gramere parametreli fonksiyon armay ekleyelim.


Expression: Additive Additive: Additive + Multiplicative | Additive - Multiplicative | Multiplicative Multiplicative: Multiplicative * Primary | Multiplicative / Primary | Unary Unary: + Unary | - Unary | ! Primary | Primary Primary: Number | Variable | (Expression) | Variable ( Arguman_List ) Argument_List:

26

Expression, Expression , Argument_List

Soru: !Foo(3,5) +Bar(a,b) ifadesi expression dilinin bir eleman mdr? Yant evet. Soru: Func( a+5, Bar(x,y) ) ifadesi expression dilinin bir eleman mdr? Yant evet. Yukardaki dil olduka bilinli oluturulmutur. Hlbuki bazen yanllkla bir ifade birden fazla yoldan geilerek alabilir. Byle gramerlere iki anlaml (ambiguous) gramer diyoruz.
Expression: Additive Additive: Additive + Additive | Additive - Additive | Multiplicative Multiplicative: Multiplicative * Multiplicative | Multiplicative / Multiplicative | Primary Primary: Number | Variable

Bu gramerde a + b * c gibi bir ifade a + b nin sonucu c ile arplacak ya da a ile b * c nin sonucu toplanacak ekilde alabilir. O halde gramer iki anlamldr ve bir ie yaramaz.

6.2. Programlama Dillerindeki Sentaks ve Semantik Kstlamalar

Bir programlama dillerindeki geerli tm programlar BNF notasyonu ile aklamak mmkn olmayabilir. BNF yalnzca sentaks asndan geerlilii aklamaya yeterlidir. Sentaks geerliliinden sonra semantik kurallar da kontrol etmek gerekir. rnein aadaki C program standartlarda belirtilen C kurallarna uyar. Fakat semantik kurallara uymamaktadr.
int main() { int a, a; /***********************/ return 0; }

27

6.3. C de Operandlarn Yapl Sras

C de ,

&&, ||, ? : operatrlerinin yapl sras derleyicileri yazanlarn isteine

braklmtr. rnein;
func1() + func2() + func3()

Burada BNF gramer kurallarna gre kesinlikle func1() + func2() toplamnn sonucu, func3() ilevinin geri dn deeri ile toplanacaktr. Fakat burada ilk nce func1 ilevinin arlmas gerektiine dair bir standart yoktur. Yani derleyici srasyla func1, func2 ve func3 fonksiyonlarn arabilecei gibi (genelde byledir), tersten ya da rasgele fonksiyonlarn arp daha sonra dndrdkleri deerleri srasyla toplayabilir. Btn bunlara ramen gene de func1() + func2() toplamnn func3() deeri ile toplanaca gerei deimez. C derslerinde grdmz fonksiyon arma operatrnn soldan saa olduu bilgisi gerek ddr. rnein:
a * b + c * d

Burada a*b ile c*d nin sonular toplanacaktr. Fakat + ve * operatrlerinin de operandlar deiik srada ele alnabilir. Derleyici nce c*d yi sonra a*b yi yapp sonular toplayabilir. O halde * operatrnn de soldan saa doru olduu bilgisi, gerei tam yanstmamaktadr. Operandlarn ele alnmas C ve C++ da derleyiciyi yazanlarn inisiyatifine braklmtr. (unspecified belgelenmesi zorunlu deil.) Fakat C# ve Javada sol taraftaki operandn nce alnaca garanti edilmitir. rnein:
a() * b() + c() * d()

C# ve Javada nce a sonra b sonra c ve en son d arlacaktr. Yani ilemler kesinlikle yle yaplacaktr:
i1 i2 i3 i4 i5 i6 i7 : : : : : : : a() b() i1 * i2 c(); d(); i4 * i5 i3 + i6

28

#include <stdio.h> int func1() { printf("func1()\n"); return 1; } int func2() { printf("func2()\n"); return 2; } int func3() { printf("func3()\n"); return 3; } int func4() { printf("func4()\n"); return 4; } int main() { int result; result = func1() + func2() + func3() + func4(); return 0; } kt: Func1() Func2() Func3() Func4() Press any key to continue . .

Burada func1, func2, func3 ve func4 fonksiyonlar sras ile arlmtr.

6.4. Bildirim lemi C deki bildirim ileminin BNF kural yledir:

29

Declaration: Declaration-specifers init-declarator-listopt;

Declaration specifers tr belirten szc, const, volatile, static gibi belirleyicileri ierir.
const int a; /* const ve int declaration-specifers bildirir. */

init-declarator-list, init-declarator, init-declarator-list ve init-declaratorlerden oluur.


init-declarator-list: init-declarator | init-declarator-list, init-declarator

init-declarator ise declarator ve initializer kavramlarn aklar.


init-declarator: declarator | declarator initializer

int a = 10, b, c = 20; aklayacak olursak; int = declaration specifers a = declarator 10 = initializer b = declarator c = declarator 20 = initializer

Bir bildirim kabaca 3 paradan oluur: Bildirim belirleyicileri (declaration-specifers), declarator ve ilk deer (initializer). Bildirim belirleyicileri ve ilk deerin dndaki tm atomlar declarator u olutururlar.

rnein;
int *p[10]; int = bildirim belirleyicileri

*p[10]= declarator

rnein;
void Func(int a, int b);

30

void = bildirim belirleyicileri Func(int a, int b) = declarator

Bildirim belirleyicilerindeki tr, declaratrn trdr. Bazen C programclar neyin declaratrn paras olduunu, neyin bildirim belirleyicisi olduunu armaktadr. rnein * atomu tre ilikin deil, declaratre ilikindir. rnein;
int* a, b;

Burada a bir gsterici, b adi bir int nesnedir. Bu nedenle * ayracnn declaratre yakn durmas daha anlamldr. int*a, b; veya byi de gsterici yapmak istiyorsak int *a, *b yapmak gerekir. const ve volatile belirleyicileri * n solunda ise bildirim belirleyicisine ilikindir ve tm declaratrleri etkiler.

rnein;
const int*a, b; /*burada *a const int ve b de const int tir. */

Bildirim belirleyicilerinin yazlm srasnn hibir nemi yoktur. rnein;


int short unsigned x;

const ve volatile declaratre ilikin de olabilir. rnein;


int* const a, b;

a kendisi const olan bir gstericidir, b ise const olmayan bir nesnedir.
int Func(void), *p, a[9];

Burada Func() n geri dn deeri de, p gstericisi de ve a dizisi de hepsi int trndendir. C de bildirim belirleyicilerinde tr belirten szck kullanlmazsa (type specifers) kullanlmazsa, tr int olarak alnr. const x; Bu bildirim C 90da geerlidir ve int olarak alnr. Bu kural c 99 ve c++da kaldrlmtr. Ayn ekilde func(void) C 90da geerlidir ve geri dn deeri int olarak alnr. Bu kural C99 ve C++da kaldrlmtr.

31

7. FONKSYON GSTERCLER (POINTER To FUNCTIONS)


Yalnzca nesnelerin deil, fonksiyonlarn da adresleri vardr. Fonksiyon adreslerinin yerletirildii gstericilere fonksiyon gstericileri denir. Fonksiyon gstericisi aadaki gibi bildirilir:
(<tr>) (*<gsterici ismi>)( [parametre bildirimi] );

rnein;
void (*pf1) (int); int (pf2) (int, long); void (*pf3) ();

Fonksiyon gsterici deklaratrnde , * ifadesinin parantez ierisine alndna dikkat edilmelidir. Eer burada parantez kullanlmazsa deklaratr prototip anlamna gelir. rnein;
int *p (void); /*fonksiyon prototipi*/ int (*p) (void); /*fonksiyon gstericisi*/

Bir fonksiyonun adresi denilince, fonksiyonun makine komutlarnn bellekteki balang adresleri anlalr. rnein;

int Add(int a, int b) { return a + b; }

Derleyicimiz bu fonksiyonu aadaki gibi makine diline evirmi olsun.


_Add proc nec push ebp move ebp esp move eax [ebp + 8] add eax [ebp + 12] Ppop ebp rex _Add andp /*fonksiyonun balang adresi*/

32

Fonksiyonun arlmas srasnda call makine komutu aslnda fonksiyonun balang adresini almaktadr. rnein;
push 20 push 10 call _Add add esp, 8 mov result, eax Anahtar notlar: Pek ok C derleyicisinde sembolik makine dili C kodlarnn arasna serpitirilerek yazlabilmektedir. phesiz bu standart bir zellik deildir ve derleyicilerin bir eklentisidir. int add(int a, b) { _asm { mov eax, [ebp, 8] add eax, [ebp + 12] } }

rnein biz toplama ilemini yapan bir fonksiyonu inline assembly kullanarak yapabiliriz.
#include <stdio.h> int Add(int a, int b) { _asm { mov eax, a add eax, b } } int main(void) { int result; result = Add (10,20); printf("%d\n", result); return 0; }

Bir fonksiyon gstericisi her trden fonksiyon gstericisinin adresini tutamaz. Yalnzca geri dn deeri ve parametrik yaps belirli biimde olan fonksiyonlarn adreslerini tutabilir. rnein;
int (*pf) (int, int);

33

Bu fonksiyon gstericisi geri dn deeri int ve parametreleri int, int olan fonksiyonlarn adreslerini tutabilir. Deklaratrde parametre deiken isimleri yazlabilir fakat hi tercih edilmemektedir. rnein;
int (*pf) (int a, int b);

Deklaratrde parametre parantezinin iinin bo braklmas ile void yazlmas arasnda nemli bir fark vardr.
int (*pf)(); int (*pf)(void);

Parametre parantezinin ii bo braklrsa bu gsterici geri dn deeri uymak zere, parametrik yaps nasl olursa olsun her trden fonksiyonun adresi atanabilir. Hlbuki parametre parantezinin iine void yazlrsa bu durumda gstericiye parametresi olmayan fonksiyonlarn adresleri atanabilir. Bunun tarihsel nedenleri vardr.
Anahtar notlar: 70li ve 80li yllarn ilk yarsnda Cde prototip kavram yoktu. Prototip Cye sonradan eklenmitir. Bu durumda fonksiyonu armadan nce yaplan ileme, fonksiyon prototipi deil, fonksiyon bildirimi (function decleration) denir. O yllarda henz parametre parantezinin iine tr yazlmyordu ve fonksiyon bildirimleri aadaki gibi yaplyordu:

rnein;
double pow(); double sqrt(); Bu durumda derleyiciler fonksiyon arrken parametreleri sayca kontrol etmiyordu. Daha sonra Cye prototip konusu eklenmitir. te parametre parantezinin ierisine trler yazlmaya balandnda eski kodlarn geerliliini korumak iin eski fonksiyon bildirimlerinin anlam eskisi gibi braklmtr. Yani biz prototipde parametre parantezinin ierisini bo brakrsak C derleyicisi bu prototip bildiriminin eskiden kalma bir fonksiyon bildirimi olduunu kabul eder ve buna parametre kontrol uygulamaz. Ite o devirlerde fonksiyon gsterici bildiriminde parametre parantezinin ii zaten bo braklyordu.

rnein;
int (*p)(); O zamanlarda geri dn deeri int olan fakat parametrik yaps ne olursa olsun her trden fonksiyonun adresini atayabiliyordunuz. te prototip sonrasnda bu bildirimin anlam da eskisi gibi braklmtr. Ancak C++ Cdeki bu eskiye doru olan bozukluu desteklememitir. C++da parametre parantezinin iinin bo braklmas ile void yazlmas arasnda bir fark yoktur.

34

Cde yalnzca bir fonksiyonun ismi fonksiyonun bellekteki balang adresini belirtir. Zaten fonksiyon arma operatr, operand olarak fonksiyon adresi almaktadr. rnein;
void func(void) { /*****/ } void (*pf) (void); pf = func();

7.1. Fonksiyon Gstericisi Yolu ile Fonksiyonlarn arlmas pf bir fonksiyon gstericisi olmak zere, arma ilemi (*pf) (void) ya da pf() eklinde yaplabilir. Her ikisi de geerli ve dorudur.rnein;
#include <stdio.h> void Message(void) { printf("message\n"); } int main(void) { void (*pf)(void); pf = Message; pf(); return 0; } /*************************************/ #include <stdio.h> void Message(void) { printf("message\n"); } int main(void) { int (*pf)(const char *, ...); pf = printf; pf("test\n"); return 0; }

35

7.2.

Fonksiyon Gstericilerinin Fonksiyon Parametresi Olarak Kullanlmas

Bir fonksiyonun belli bir durumda bizim istediimiz bir fonksiyonu armasn salayabiliriz. Byle fonksiyonlar, genel ilemler yapacak biimde ktphaneye yerletirilebilirler. Bir fonksiyonun parametresinin tr fonksiyon gstericisi olabilir. Bu durumda bir fonksiyon ayn trden bir fonksiyon ismi ile arlmaldr. rnein her malloc() armasndan sonra kontrol engellemek iin, kontrol kendi ierisinde yapan bir mymalloc() fonksiyonu tasarlanabilir. Ancak bu fonksiyonun genel olup, ktphaneye yerletirilebilmesi iin baarszlk durumunda, ne yaplacann dardan belirlenebilmesi gerekir. Bu belirleme, mymalloc() fonksiyonuna ilave bir fonksiyon gstericisi parametresi geirilerek yaplabilir.
#include <stdio.h> #include <stdlib.h> void *mymalloc (size_t size, void(*pfailure)(void)) { void *pblock; do { pblock = malloc(size); pblock = NULL; if (pblock) break; pfailure(); } while (pblock == NULL); return pblock; } void handler(void) { printf("Not enough memory!..\n"); exit(EXIT_FAILURE); } int main(void) { int *ptr = (int *)mymalloc(10 * sizeof(int), handler); /************** ******************/ free(ptr); return 0; }

36

7.3. Fonksiyonlarn Fonksiyon Adresine Geri Dnmesi Durumu

Bir fonksiyonun geri dn deeri bir fonksiyon adresi olabilir. Bu tr fonksiyon bildirimi biraz karmaktr. Deklaratrde * parantez ierisine alnr. Parantezin soluna geri dn deerine ilikin fonksiyonun geri dn tr sana geri dn deerine ilikin fonksiyonun parametrik yaps yazlr. rnein kendi parametresi int olan geri dn deeri int, parametresi long olan bir fonksiyon adresine geri dnen func fonksiyonu yle yazlr: rnein;
1234{ } Func(int a) (*Func(int a)) int (*Func(int a)) int (*Func(int a)) (long)

rnein;
int a, b[9], (*Func(void))(void);

Burada a int trden bir nesne, b int trden bir dizi, func ise, parametresi void, geri dn deeri int trden bir fonksiyon adresi olan fonksiyonun prototipidir. rnein: Parametresi int, geri dn deeri void parametresi long long biimindeki bir fonksiyon adresi olan Foo fonksiyonunu yaznz:
void (*Foo(int a))(long, long)

rnein:
#include <stdio.h> void Message(void) { printf("Message\n"); } void (*Test(void)) (void) { return Message; } int main(void) { void (*pf)(void);

37

pf = Test(); pf(); Test()(); return 0; }

Bazen daha karmak bildirimlerle seyrek de olsa karlalmaktadr. rnein aadaki gibi bir fonksiyonu yazmaya alalm: 1- Fonksiyonun ismi Foo ve parametresi int trdendir. 2- Fonksiyonun geri dn adresi bir fonksiyon adresidir. 3- yle bir fonksiyonun adresidir ki, bu fonksiyonun parametresi long, geri dn deeri parametresi void geri dn deeri void olan bir fonksiyon adresidir. Yukardaki aklama tek cmle ile yle ifade edilebilir: Parametresi int geri dn deeri, parametresi long geri dn deeri, parametresi void geri dn deeri void olan bir fonksiyonun adresi olan Foo fonksiyonunu yazn.

void (*(*Foo(int a))(long))(void) { /************/ }

Bu fonksiyonun atanaca gsterici aadaki ekilde tanmlanabilir.


int main(void) { void (*(*pf)(long))(void); pf = Foo(0); }

rnein;
#include <stdio.h> void Tar(void) { prinf("Tar\n"); } void (*Bar(long a))(void) { return Tar; } void (*(*Foo(int a))(long))(void) {

38

return Bar; } int main(void) { void (*(*pf)(long))(void); pf = Foo(0); pf (0)(); //Foo(0)(0)(); return 0; }

7.4.

Fonksiyonlarn Gstericilerine likin Dier Durumlar

Her eleman bir fonksiyon adresi tutan bir fonksiyon gsterici dizisi tanmlanabilir.

rnein;
#include <stdio.h> void Func1() { printf("Func1\n"); } void Func2() { printf("Func2\n"); } void Func3() { printf("Func3\n"); } int main(void) { int i; void (*pf[])(void) = {Func1, Func2, Func3, NULL}; for (i = 0; pf[i] != NULL; ++i) { pf[i](); } return 0; }

rnek:
#include <stdio.h> #include <string.h> /* Symbolic Constants */

39

#define MAX_CMD_LINE #define MAX_CMD_PARAM /* Type Declarations */ typedef struct tagCMD { char *pCmdName; void (*pf)(void); } CMD; /* Function Prototypes */ void Dir(void); void Del(void); void ParseCmdLine(void);

512 32

/* Global Data Definitions */ char g_cmdLine[MAX_CMD_LINE]; CMD g_commands[] = {{"dir", Dir}, {"del", Del}, {NULL, NULL}}; char *g_params[MAX_CMD_PARAM]; int g_paramCount; int main(void) { int i; for (;;) { printf("CSD>"); gets(g_cmdLine); ParseCmdLine(); if (g_paramCount == 0) continue; if (!strcmp(g_params[0], "quit") || !strcmp(g_params[0], "exit")) break; for (i = 0; g_commands[i].pCmdName != NULL; ++i) if (!strcmp(g_params[0], g_commands[i].pCmdName)) { g_commands[i].pf(); break; } if (g_commands[i].pCmdName == NULL) printf("'%s' is not recognized as an internal or external" "command, operable program or batch file.\n", g_params[0]); } return 0; } /* Function Definitions */ void ParseCmdLine(void) { char *pStr; int i = 0; for (pStr = strtok(g_cmdLine, " \t"); pStr != NULL; pStr = strtok(NULL, " g_params[i++] = pStr; g_paramCount = i;

\t"))

40

} void Dir(void) { printf("Dir\n"); } void Del(void) { if (g_paramCount == 1) { printf("The syntax of the command is incorrect.\n"); return; } }

Fonksiyon gstericileri ile kolay alabilmek iin ve birtakm karmak bildirimleri kolaylatrabilmek iin typedef ileminden faydalanabiliriz. rnein;
typedef void (*PF) (void); PF p;

ile
void (*p)(void);

ayn anlamldr. rnein;


PF Func(int a); { ... }

ile
void (*Func(int a)) (void)

ayn anlamldr. Daha karmak bildirimleri kolaylatrabiliriz: rnein;


typedef void (*PF) (void); typedef PF (*PFF) (int); PFF Func(long a) { ... } ile

41

void (*(*Func(long a))(int))(void) { ... }

ayn anlamldr. rnein;


PF a[10]; /*10 elemanl PF trnden bir dizidir.*/

rnein;
#include<stdio.h> #include<string.h> typedef void (*PF) (void); void Message(void) { printf("Message\n"); } PF Func(void) { return Message; } int main (void) { PF (*pf)(void); pf = Func; pf()(); return 0; }

rnek;
#include<stdio.h> #include<string.h> typedef void F(void); typedef F *PF; int main (void) { PF pf; /*ya da return 0; } F *pf; geerlidir*/

42

7.5.

Fonksiyon Gstericileri Neden Kullanlr?

Fonksiyon gstericilerinin en nemli kullanm alan fonksiyonlar genelletirmektir. rnein;


void Foreach(int *pi, int size, void (*pf)(int *)) { int i; for (i = 0; i < size ; ++i) { pf(&pi[i]); } } void foo(int *pi) { *pi *= 2; } void disp(int *pi) { printf("%d\n", *pi); } int main (void) { int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; forEach(a, 10, foo); forEach(a, 10, disp); return 0; }

Yani bir fonksiyon bir ii yaparken bir fonksiyon aryor olablir. Biz o fonksiyona deiik iler yaptrabiliriz.

7.6.

Trden Bamsz lem Yapan Yeni Amal Fonksiyonlarda Fonksiyon Gstericilerinin Kullanlmas

Aslnda fonksiyon bir dizinin balang adresini , bir elemannn boyunun uzunluunu ve dizinin eleman saysn parametre olarak alrsa dizinin her elemanna eriilebilir. Fakat elemanlar karlatramaz. nk onlarn trn bilememektedir.

43

Ancak dizinin trn fonksiyonu aran kii bilmektedir. O halde fonksiyon karlatrma yaptraca zaman bunu fonksiyon gsterici yolu ile fonksiyon arma yaptrabilir. rnein trden bamsz sort ilemi yapan fonksiyon yle yazabilriz:

void Sort (void *pvArray, unsigned size, unsigned witdh, int (*Compare)(const void *, const void*)) { unsigned i,j,k; char *pcArray = (char*) pvArray, *pc1, *pc2, temp; for(i = 0; i < size; ++i)s for (k = 0; k < size - i - 1; ++k) { pc1 = pcArray + witdh * k; pc2 = pcArray + witdh * (k + 1); if (Compare(pc1, pc2) > 0) for (j = 0; j < witdh; ++j) { temp = pc1[j]; pc1[j] = pc2[j]; pc2[j] = temp; } } } int compareInt(const void *pv1, const void *pv2) { const int *pi1 = (const int *)pv1; const int *pi2 = (const int *)pv2; if(*pi1 > *pi2) return 1; if(*pi1 < *pi2) return -1; return 0; } int main() { int a[10] = {10, 30, 68, 94 , 78, 5, 6, 7 ,19, 89}; int i; Sort(a, 10, sizeof(int), compareInt); for(i = 0; i < 10; ++i) printf("%d ", a[i]); putchar('\n'); return 0; }

Ayn fonksiyon ile bir yapy sraya dizelim:

44

typedef struct tagPERSON { char name[32]; int no; }PERSON;

int Compare(const void *pv1, const void *pv2) { const PERSON *p1 = (const PERSON *) pv1; const PERSON *p2 = (const PERSON *) pv2; return strcmp(p1->name, p2->name); } int main() { PERSON people[] = { {"Kaan Aslan", 123},{"Ali Serce", 576}, {"Necati Ergin", 231}, {"Metin Kaya", 78}, {"Gurbuz Aslan", 643}, {"Guray Sonmez", 322} }; int i; Sort(people, 6, sizeof(PERSON), Compare); for(i = 0; i < 6; ++i) printf("%s\t\t\t\%d\n", people[i].name, people[i].no); putchar('\n'); return 0; }

Karlatma fonksiyonu programc tarafndan 1.deer 2.deerden bykse hernagi + bir deere, kkse herhangi bir deere ve eitse 0 deerine geri dnecek ekilde yazlmaldr. Cnin standart qsort fonksiyonu tamamen yukarda yazdmz Sort fonksiyonunun parametrik yapsna sahiptir.Ancak qsort genellikle quicksort algoritmasn kullanmaktadr.
qsort(people, 6, sizeof(PERSON), Compare);

ile program altrldnda da ayn kty vermektedir.

45

8. C nin STANDART TR SMLER


eitli balk dosyalarnda standart baz tr isimleri bildirilmitir. Bu isimlerin hepsi -t son eki ile isimlendirilmitir.

8.1. size_t Tr Bu tr stdio.h , stdlib.h ve temel dier balk dosyalarnda bildirilmitir. Standartlara gre bu trn hangi tr olarak typedef edilecei, iaretsiz tamsay tr olmak koulu ile derleyiciyi

yazanlarn isteine braklmtr. Pek ok sistemde size_t unsigned int biiminde typedef edilmitir. Standartlarda pek ok fonksiyonda size_t tr kullanlmtr. rnein;
void * malloc(size_t size); size_t strlen(const char *str);

Grld gibi aslnda malloc() parametresi ilgili sistemde size_t neye typedef edilmise o trdendir. size_t tr genellikle allan sistemdeki bellek uzunluunu belirtilecek ekilde alnr. Bu nedenle dizi uzunluklar, size_t ile ifade edilmektedir. rnein qsort fonksiyonunun prototipi yledir:
void qsort (void *pArray, size_t size, size_t width, int(*Compare)(const void *, const void*));

8.2. ptrdiff_t Tr Standartlara gre bu tr iaretli bir tamsay tr olarak typedef edilmek zorundadr. stdio.h , stdlib.h ve temel dier balk dosyalarnda bildirilmitir. Ayn trden iki adres bilgisi kartlrsa elde edilen sonu bu trdendir.

8.3. time_t Tr Standartlara gre bu tr saysal bir tr olarak typedef edilmek zorundadr. Tipik olarak time.hda bildirilmitir.

46

Anahtar notlar: Cnin tm standart tr isimleri minimal dzeyde stddef.h ierisinde include edilmitir.

9. OK KULLANILAN ETL C FONKSYONLARI


9.1. remove Fonksiyonu Bu fonksiyon bir dosyay silmek iin kullanlr. Prototipi yledir:
int remove(const char *path);

Fonksiyon parametre olarak dosyann yol ifadesini alr, baarl ise 0 deerine, baarszsa -1 deerine geri dner. Prototipi <stdio.h> ierisindedir.

9.2. rename Fonksiyonu

Bir fonksiyonun ismini deitirmek iin kullanlr. Standart bir fonksiyondur. Prototipi aadaki gibidir:
int rename(const char *oldname, const char *newname);

Fonksiyon, baarl ise 0 deerine, baarszsa -1 deerine geri dner. Prototipi <stdio.h> ierisindedir.

9.3. mkdir Fonksiyonu

Bu fonksiyon standart bir fonksiyon deildir. MS derleyicilerinde _mkdirdir. GCC derleyicilerinde mkdir isminde bulunur. Bir POSIX fonksiyonudur. Fonksiyon prototipi MS

derleyicilerinde <direct.h>, GCC derleyicilerinde <unistd.h> iinde bulunur. Dizin oluturmada kullanlr.
int _mkdir(const char *path);

47

9.4. chdir Fonksiyonu

chdir fonksiyonu deitirmede kullanlr. MS derleyicilerinde _chdir isminde, GCC derleyicilerinde chdir isminde kullanlr. Porototipi aadaki gibidir:
int _chdir(const char * dirname);

9.5. rmdir Fonksiyonu

rmdir fonksiyonu, dizin silmek iin kullanlr. Fakat dizinin iinin bo olmas gerekir. MS derleyicilerinde _rmdir isminde, GCC derleyicilerinde rmdir isminde kullanlr. Prototipi aadaki gibidir:
int _rmdir(const char * _Path);

9.6.access Fonksiyonu

Pek ok uygulamada bir dosyann diskte daha nce olup olmadna baklmaktadr. rnein bir editr yazma projesinde kullanc dosyay kaydedecei zaman verdii isme sahip bir dosya diskte bulunabilir. Bunu editr programnn File already exists, overwrite? gibi bir mesaj ile kullancya bildirmesi gerekir. Dosyann diskte olup olmadn kontrol etmek iin dosyann r yada r+ modunda almaya allmas tavsiye edilmez. nk, ok zayf bir olaslk da olsa, dosya diskte olduu halde baka nedenlerle alamam olabilir.
if ((f = fopen(name, "r")) == NULL);

48

access() fonksiyonu bir dosyann diskte olup olmadn ve dier baka eriim haklarna sahip olup olmadn tespit etmek iin kullanlr. Standart bir fonksiyon deildir, bir POSIX fonksiyonudur. MS derleyicilerinde _access, GCC derleyicilerinde access isminde bulunur.

Fonksiyon prototoipi MS derleyicisilerinde <io.h>, GCC erleyicilerinde <unistd.h> iinde bulunur. Prototipi aadaki gibidir:
int _access( const char *path, int mode);

Fonksiyonun 1. parametresi dosyann diskteki yerini ve ismini, 2. parametresi ise varl test edilecek zellii belirtir. 2. parametre aadakilerden birisi olabilir: 0 1 2 3 dosyann var olup olmadn, alabilir dosya olup olmadn, yazlabilir olup olmadn, okunabilir olup olmadn test eder.

Bir dosyann olup olmadn test etmek iin 2. parametre 0 yaplr, fonksiyonun geri dn deeri 0 ise test olumlu (var), 0 d ise olumsuz (yok) anlamna gelir.
printf ("Filename to be saved :"); gets(fname); if (!access(fname, 0)) { printf("File already exists! Overwrite? [Y/N]"); if (tolower(getch()) != 'y') exit(EXIT_FAILURE); } savefile(fname);

9.7. Geici Dosya Aan Fonksiyonlar

Bazen bir takm ara sonularn yazlaca ksa mrl bir dosyann almasna gereksinim duyulur. Bu tr dosyalar ou kez ilem bitince programc tarafndan silinirler. Bu tr dosyalar yaratlrken tipik sorun zaten var olan bir dosyann ismi ile akma durumudur. Programcnn bunu garanti altna almas gerekmektedir.

49

9.7.1. tmpfile Fonksiyonu

Prototipi <stdio.h> iinde yer alan standart bir fonksiyondur. Prototipi aadaki gibidir:
FILE *tmpfile(void);

Fonksiyon diskte olmayan bir dosya ismi uydurarak w + b modunda bir dosyay oluturur ve aar. Alm olan dosyaya ilikin dosya bilgi gstericisi ile geri dner. fclose() ilemi

uygulandnda dosya otomatik olarak silinmektedir. Fonksiyon, baarszsa NULL deerine geri dner.

rnein;
int main() { FILE *f if((f = tmpfile()) == NULL) { printf("cannot create tmprory file!..\n"); exit(EXIT_FAILURE); } return 0; }

9.7.2. tmpnam Fonksiyonu

Bu fonksiyon dosya amaz, yalnzca diskte olmayan bir dosyann ismini retir. Prototipi aadaki gibidir:
char *tmpnam( char *str);

Fonksiyon parametre olarak yol ifadesinin yerletirilecei char trden dizinin adresini alr. Parametre NULL geilebilir. Bu durumda fonksiyon elde ettii yol ifadesine kendi ierisinde yaratt static bir diziye yerletirir. Bu static dizinin adresi ile geri dner. Parametre NULL girilmemise, geri dn deeri girilen parametrenin aynsdr.
int main() { char *path; path = tmpnam(NULL); puts(path); return 0;

50

Fonksiyon yinede baarsz olabilir. Bu durumda NULL deeri ile geri dner.
#include #include #include #include #include #define <stdio.h> <string.h> <stdlib.h> <io.h> <ctype.h> MAX_LINE_LEN 2048

int main(int argc, char *argv[]) { FILE *fs, *fd; char *pTempName; char line[MAX_LINE_LEN]; if (argc != 2) { printf("Wrong number od arguments!...\n"); exit(EXIT_FAILURE); } pTempName = tmpnam(NULL); if (pTempName == NULL) { printf("Cannot get temp file name!..\n"); exit(EXIT_FAILURE); } if ((fs = fopen(argv[1], "r")) == NULL) { printf("Cannot open file: %s\n", argv[1]); exit(EXIT_FAILURE); } if ((fd = fopen(pTempName, "w")) == NULL) { printf("Cannot open temporary file!..\n"); exit(EXIT_FAILURE); } while (fgets(line, MAX_LINE_LEN, fs) != NULL) { int i; for (i = 0; isspace(line[i]); ++i) ; if (line[i] != '#') fprintf(fd, "%s", line + i); } fclose(fs); fclose(fd); if (remove(argv[1]) == -1) { printf("Cannot remove file: %s\n", argv[1]); exit(EXIT_FAILURE); } if (rename(pTempName, argv[1]) == -1) { printf("Cannot rename file!...\n"); exit(EXIT_FAILURE);

51

} printf("Ok...\n"); return 0; } ANAHTAR NOT: Sistem programlama faaliyetinde sistemin o anki durumuna bal olarak pek ok hata kayna sz konusu olabilir. Bu nedenle sisteme zg ilemlerde sk bir kontrol yaplmaldr. Hi olmazsa, baarszlk tespit edilip nedeni yazdrlmaldr.

10. HANDLE SSTEMLER


Bir veri yapsna erimek iin kullanlan tekil bilgilere handle denir. Handle adeta veri yapsna erimek iin kullanlan bir anahtardr. Handle ou kez dorudan veri yapsn gsteren bir adrestir. Bazen handle basit bir index olabilir. rnein global bir yap dizi sz konusudur, handle bu dizide index grevi grr. Bazen ise handle ifrelenmi bir deer biiminde olabilir. Biz handle bir fonksiyona parametre olarak gndeririz. Fonksiyon, bu handle ileme sokarak gerek anahtar deeri elde eder. Handle sistemlerinde genel olarak 3 tr fonksiyon bulunur:

10.1. Handle Sistemini Aan Fonksiyonlar Bu tr fonksiyonlar genellikle createxxx ya da openxxx eklinde isimlendirilirler. Handle sistemini oluturan ya da aan fonksiyonlar, kendi ilerinde nce handle alann tahsis ederler, sonra bu alandaki, nemli elemanlara ilk deerlerini verirler ve handle deeri ile geri dnerler

10.2. Handle Sistemini Kullanan Fonksiyonlar

52

Bu fonksiyonlar, handle deerini parametre olarak alr, handle alanna erierek faydal bir takm ilemler yaparlar.

10.3. Handle Sistemini Yok Eden Fonksiyonlar Bu tr fonksiyonlar genellikle destroyxxx ya da closexxx eklinde isimlendirilirler. Handle deerini parametre olarak alr, handle sistemini yok ederler. rnein, C nin standart dosya fonksiyonlar bir handle sistemi oluturmaktadr. fopen(), handle sistemini oluturan fonksiyondur. fgets(), fprintf(), fread(), fwrite() handle sistemini kullanan fonksiyonlardr. fclose() handle sistemini yok eden fonksiyondur.
Anahtar notlar: C++da snflar bir eit, handle sistemi olarak kullanlabilir. Snfn balang fonksiyonu, handle sistemini oluturan fonksiyon, biti fonksiyonu(destructor) handle sistemini yok eden fonksiyon, ve dier ye public fonksiyonlar da handle sistemini kullanan fonksiyonlar olarak dnlebilir.

Elimizdeki handle ile eritiimiz veri yapsna

handle alan denilmektedir. ou kez

programc handle alannn ieriini bilmez. Bu nedenle baz handle sistemlerinde handle belirten deer , void * biimindedir. Genellikle handle sistemlerinde handle alan bir yap biiminde bildirilir. Handle alann yaratan fonksiyon, handle alann dinamik olarak tahsis eder ve yok eden fonksiyon da alan geri brakr.

11. CACHE SSTEMLER


Pek ok bilgisayar sistemlerinde eitli biimlerde yava bellek ve hzl bellek sistemleri bulunmaktadr. Yava bellekler bol ve ucuz, hzl bellekler az ve pahaldr. Yava bellein belli bir blmnn hzl bellekte tutulmas ve yava bellee eriimin azaltlmasn hedefleyen sistemlere cache sistemleri denir. Cache sistemlerinde bir bilgiye eriilmek istendii zaman nce hzl bellee baklr. Eer yava bellekte erimek istediimiz bilgi o anda hzl bellekte varsa bilgiyi hzl bir biimde elde ederiz. Bu duruma ngilizce cache hit

53

denilmektedir. Eer talep ettiimiz bilgi hzl bellekte yoksa artk mecburen yava bellee erimek zorunda kalrz. Bu duruma da ngilizce cache miss denilmektedir. Bir cache sisteminin baarsn etkileyen faktrler unlardr: 1. Yava bellein en ok talep edilen blgelerinin hzl bellekte tutulmas uygundur. Yava bellein nerelerinin hzl bellekte tutulacana cache stratejisi denir. Uygun bir strateji cache hit orann ciddi oranda arttrr. 2. Cache olarak kullandmz hzl bellek alan performans etkiler. 3. Cache sisteminin read-only ya da read/write olmas performans zerinde etkilidir. 4. Talep edilen bilginin hzl bellekte aranmasna ynelik algoritmik yap da performans da etkilidir.

Cache sistemleri read-only ve read/write olmak zere 2 blme ayrlmaktadr. Read-only cache sisteminde cache yalnzca okuma amal kullanlr. Yazma ilemi dorudan yava bellee yaplr, cache e yaplmaz. Dolaysyla her yazma ilemi bir cache miss oluturur. Bu sistem yava bellein btnln koruduu iin daha gvenlidir fakat daha yavatr. Read/Write sisteminde yazma ilemi de cache e yaplr. Read/Write cache sisteminde yava bellein baka bir blm cache e ekilmek istendiinde, cache teki bilgi zerine yazma yaplmsa nce onu yava bellee geri yazmak gerekir. Bu ileme tazeleme (flush) ilemi diyoruz. Genellikle tasarmc cache iin bir kirlenme bayra (dirty flag) tutar ve cache e hi yazma yaplmadysa bouna tazeleme yapmaz. Hzl bellekte yava bellein ardk tek bir blounu mu yoksa yava bellein kk birden fazla bloklarn m tutmalyz? te yava bellein cache te tutulan her farkl blouna cache blou (cache line) denilmektedir. Baz cache sistemlerinde tek bir cache blou (single cache line) kullanlmaktadr. Fakat uygulama da genellikle oklu cache bloklar tercih edilir. Tek cache bloklu tasarm da cache miss olutuunda yava bellein ilgili blm hzl bellee (to cache) ekilmelidir. Burada ciddi bir cache stratejisinden bahsedemeyiz. Birden fazla cache blounun sz konusu olduu durumda istatiksel temeli olan cache stratejisi izlemek gerekir. rnein yava bellek 1MB ve cache te 50kB olsun. Tek bir cache blou kullanyor olsak biz yava bellein ardk bir 50kB lk blmn cache te tutarz. Fakat oklu cache blok kullanyorsak biz rnein yava bellein 5 farkl 10kB lk blounu cache te tutabiliriz.

54

oklu cache blok sisteminde genellikle yava bellek mantksal olarak eit bloklara ayrlr. Bloklara numara verilir. rnein 10kB lk cache blou sz konusu olsun. Bu durumda 1MB lk yava bellek 100 bloa ayrlr. lk bloun numaras 0, son bloun numaras 99 dur. 50kB lk bir cache te 5 farkl blok tutulabilir. phesiz tasarmc o anda cache te hangi bloklarn bulunduunu bir biimde tutmaldr. rnein 182417 bellek blgesine erimek isteyelim. Bu adres yava bellein 18. bloundadr. O halde sistem 18. bloun cache te olup olmadna bakmaldr. Eer 18. blok cache te ise onun 2417. ofseti aranan yerdir. imdi 182417. birimin cache te olmadn dnelim. Bu birimin yava bellekten cache e alnmas gerekir. Peki, hangi veri blou cache ten atlacaktr? te eitli cache ten blok karma yntemleri vardr. Yntemlerden biri en az kullanlan bloun karlmas (least frequently used) yntemidir. Bu yntemde her cache hit olutuka cache blou iine alnan saya bir artrlr. Cache ten kartma sz konusu olduunda sayac en dk olan blok kartlr. Sk kullanlan dier bir yntem de son zamanlarda en ez kullanlan (least recently used) kartma yntemidir. Bu yntem de tipik olarak cache bloklar bir dizi ya da bal listede tutulur. Cache hit olutuunda ilgili cache bal liste yada dizinin en nne yerletirilir. Bylece bal liste ya da dizinin nnde son zamanlarda kullanlanlar (recently) arkalarnda son zamanlarda kullanlmayanlar birikir. Cache ten bir blok kartlaca zaman en arkada ki kartlr. Bu sistemde bloklara eriim saysna dikkat edilmektedir. Son zamanlarda eriilen bir blok deerlidir. Pek ok sistem programlama uygulamalarna bu tip cache sistemi uygun gzkmektedir. Yukarda ki 2 yntem en sk kullanlan yntemlerdir. Baz sistemler hibrit yntem kullanr. rnein yukardaki 2 yntemin uygun bir karm baz durumlarda iyi sonu vermektedir. Hatta en ok kullanlann cache ten karlmas (most frequently used) yntemi bile baz sistemler iin uygun olabilmektedir. Grld gibi cache ten kartma algoritmas ilgili sisteme baklarak karar verilmesi gereken bir sistemdir.

11.1. Sistem Programlama Uygulamalarnda Karlalan Tipik Cache Sistemleri

En ok kullanlan cache sistemlerinden biri tamamen donanmsal biimde gerekletirilmi olan CPU-DRAM ilikisi ile ilgilidir.

55

SRAM ler bir biti lojik kaplarla yaplan yani ok devre eleman gerektiren, hzl belleklerdir. DRAM lar bir biti tipik olarak bir kapasitif eleman ve bir transistrle gerekletirilen yani az devre eleman gerektiren yava belleklerdir. Bilgisayar sistemlerinde ana bellek olarak genellikle DRAM lar kullanlmaktadr. Bugn iin DRAM lar 10ns civarna kadar hzlanmlardr. SRAM lar 1ns nin olduka altndadr. Yani SRAM lar DRAM lardan en az 10 kat hzldrlar. Eskiden CPU lar RAM lerden daha yavat. Yani CPU RAM i beklemiyordu. rnein 80 li yllarn ortalarnda 8088 ilemcisi 10MHz te (100ns) alyordu. O zamann DRAM lar 100 ns nin altndayd. 80 li yllarn sonlarna doru CPU lar hzlannca DRAM lar yeterince hzlanamad. 80286 ilemcisi 16MHz (60 ns) te alyordu. O zamann DRAM lar 60 ns civarndayd ve bir baa ba noktasna gelinmiti. Bundan sonra artk gl CPU lar DRAM lar bekler duruma gelmitir. te 80286 board lar ile birlikte DRAM lar SRAM ler ile cache lenmitir. Bylece CPU ilk nce SRAM e bakar bilgi SRAM de bulunamazsa DRAM a bavurur. Fakat seneler ilerledike CPU lar ok fazla hzlanmlardr. CPU nun darda ki SRAM lere erimesi gze batmaya balamtr. Bu gz nne alnarak gl CPU lar ierisine SRAM lerden oluan daha hzl bir cache daha yerletirilmitir. Bylece CPU DRAM a 2 kademeli bir cache te eriir duruma geldi. CPU nun iindeki cache e isel cache (internal cache) ya da birinci dzey cache (L1 cache) denilmektedir. Dardaki cache e dsal cache (external cache) ikinci dzey cache (L2 cache) denilmektedir. Bylece CPU ilk nce L1 cache e bakar, bilgiyi orda bulamazsa L2 cache e baklr, bilgi orada da bulunamaz ise DRAM eriimi gerekletirilir. Sk karlalan dier bir cache sistemi de disk cache veya buffer cache tir. letim sistemi disk eriimini azaltmak iin son eriilen disk sektrlerini bir cache sistemi ierisinde tutar. Bu cache sistemi read/write bir sistemdir. Bylece biz bir dosyay atmzda srekli diske bavurulmaz. Diskte ki ilgili blm RAM e ekilir ve az bir disk eriimi ile aslnda RAM arlkl allr. Windows, UNIX/LINUX gibi modern sistemler genellikle gecikmeli yazma yntemini kullanmaktadr. Bu yntemde diske yazma yapldnda bu nce cache e yazlr. Sonra iletim sisteminin uygun olduu bir zamanda (cache blou kartlrken deil) tazeleme ilemi yaplr. yi bir disk cache sistemi dosya ilemlerinin %70 inin aslnda RAM den yaplmasn salamaktadr. Genellikle modern sistemler eldeki bo RAM in hepsini disk cache iin kullanma eilimindedir. RAM gereksinimi olutuka dinamik bir biimde cache ten kartma yaplr. Bilgisayarmz da fazla RAM bulunmasnn en nemli faydas disk cache performansnn artrlmasdr.

56

Cache sistemleri bilgi aktarmlarnda da sk kullanlmaktadr. rnein bir web sayfasna erimek istediimiz de servis salayclar tarafndan eitli cache mekanizmalar kullanlmaktadr. erik deiiklii olmayan sayfalar dorudan cache ten getirilebilmektedir.

11.2. C nin Standart Dosya Fonksiyonlarnn Kulland Cache Mekanizmas

C nin standart dosya fonksiyonlarna bufferold buffered fonksiyonlar denilmektedir. nk bu fonksiyonlar kendi ierlerinde bir cache mekanizmas olutururlar.
Anahtar Notlar: Bazen cache terimi ile buffer terimi ayn anlamda kullanlmaktadr. rnein standart dosya fonksiyonlarnda buffer szc cache anlamnda kullanlmtr. Bu iki terim birbirine benzese de arlk noktalar farkldr. Cache kavram yava bellee eriimi azaltmak iin, sistem fonksiyonlarna arlar azaltarak hz kazancn hedefleyen bir sistem iin kullanlr. Hlbuki buffer terimi bilgileri geici olarak bekletme temasn vurgulamaktadr. Buffer teriminde hz kazanc geri plandadr.

leri de ele alnaca gibi tm dosya ilemleri iletim sisteminin dosya sistemi tarafndan gerekletirilir. letim sistemlerini yazanlar dosya amay, kapamay, dosyadan n bayt okumay, dosyaya n bayt yazmay salayan sistem fonksiyonlarn bulundurmaktadr. Bu fonksiyonlar programclar tarafndan da dorudan arlabilir. Standart C fonksiyonlar gerek ii iletim sisteminin sistem fonksiyonlarn ararak yapmaktadr. rnein biz fread fonksiyonu ile dosyadan okuma yapmak istesek fread fonksiyonu bir biimde Windows sistemlerinde ReadFile, UNIX/LINUX sistemlerinde read sistem fonksiyonunu aracaktr. letim sisteminin sistem fonksiyonlar da phesiz disk cache sistemini arka planda kullanmaktadr. Standart C fonksiyonlar iletim sisteminden bamsz olarak ayrca bir cache mekanizmas da kullanmaktadr. rnein bu mekanizma sayesinde biz bir standart C fonksiyonu ile okuma yapmak istesek aslnda fonksiyon daha fazla miktarda bilgiyi iletim sisteminin fonksiyonu ile okuyarak cache i doldurmaktadr. Biz daha sonra okuma yapmak istediimizde bu istek ncelikle bu cache ten salanmaktadr. Peki, byle bir cache mekanizmasna gerek var mdr? Sistem fonksiyonlarnn arlmas greli bir zaman kaybna yol amaktadr. rnein, fgetc fonksiyonu her defasnda Windows sistemlerinde ReadFile fonksiyonlarn arsa, ciddi bir zaman kayb olumaktadr. te standart fonksiyonlar sistem fonksiyonlarn daha az arabilmek iin bir cache sistemi oluturmaktadr.

57

Anahtar Notlar: Standart C fonksiyonlar iin cache szc yerine tampon (buffer) szc kullanlmaktadr. Bu notlarda da bundan sonra bu balamda, standart C fonksiyonlar sz konusu olduunda, tampon szc kullanlacaktr.

Sistem fonksiyonlar ekirdek ierisindeki disk-cache sistemini kullanmaktadr. Buradaki ama, disk eriimini azaltmaktr. Oysa standart C fonksiyonlarn tamponlama yapmasnn amac, sistem fonksiyonlarnn arlmasn azaltmaktr.

Standart C Dosya Fonks.

Tampona Baklr

Sis. Fonk arlr.

Disk-cache Baklr.

D S K

User Mode (Kullanc mod)

Kernel Mode (ekirdek mod)

Anahtar Notlar: Zaman lmek iim clock isimli standart C fonksiyonu kullanlabilir. Prototipi yledir; clock_t clock(void); Fonksiyon, program almaya baladndan bu yana geen tick deeriyle geri dner. Bir tick deerinin ka saniye olduu, CLOCKS_PER_SEC sembolik sabitiyle belirlenmektedir. rnein Microsoft derleyicilerinde CLOCKS_PER_SEC 1000 deerindedir. Clock fonksiyonu bize 3000 gibi bir deer vermi olsun. Proses baladndan bu yana 3000/1000 = 3 saniye gemitir. O halde iki nokta arasndaki zaman fark stn kr bir biimde yle hesaplanabilir. clock_t t1, t2; double sec; t1 = clock(); // Proces ... t2 = clock(); sec = (double) (t2 - t1) / CLOCKS_PER_SEC; printf("%f\n", sec); Clock fonksiyonu dk duyarllktadr. stelik standartlara gre bu fonksiyonun ilgili sistemde alabilir durumda olmasnn da garantisi yoktur. Eer fonksiyon baarsz olursa -1 deerine dner. Microsoft derleyicilerinde, CLOCKS_PER_SEC 1 ms ye karlk gelmektedir. clock_t tr pek ok sistemde unsigned long olarak typedef edilmitir. Fakat standartlarda, derleyiciyi yazanlara braklmtr. Tamponlama yaplmadan, her seferinde sistem fonksiyonunun arlmasnn maliyetini gsteren program. #include <stdio.h> #include <stdlib.h>

58

#include <string.h> #include <time.h> #include <windows.h> #define SYS_METHOD #ifdef STDC_METHOD int main(void) { FILE *f; int ch; clock_t t1, t2; double sec; if ((f = fopen("C:\\Program Files\\Microsoft Office\\OFFICE11\\Powerpnt.exe", "rb")) == NULL) { printf("Cannot open file!..\n"); exit(EXIT_FAILURE); } t1 = clock(); while ((ch = fgetc(f)) != EOF) ; t2 = clock(); sec = (double) (t2 - t1) / CLOCKS_PER_SEC; printf("%f\n", sec); fclose(f);

return 0; } #endif

#ifdef SYS_METHOD int main(void) { HANDLE hFile; char ch; DWORD dwRead; clock_t t1, t2; double sec; if ((hFile = CreateFile("C:\\Program Files\\Microsoft Office\\OFFICE11\\Powerpnt.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { printf("Cannot open file!..\n"); exit(EXIT_FAILURE); }

59

t1 = clock(); do { if (!ReadFile(hFile, &ch, 1, &dwRead, NULL)) { printf("IO error\n"); exit(EXIT_FAILURE); } } while (dwRead != 0); t2 = clock(); sec = (double) (t2 - t1) / CLOCKS_PER_SEC; printf("%f\n", sec); CloseHandle(hFile);

return 0; } #endif

12. PROSES KAVRAMI


Program terimi daha ok altrlabilen bir dosyann diskteki durumunu anlatmak iin kullanlmaktadr. Halbuki bir program altrldnda, artk ona proses denilmektedir. Proses terimi ile eanlaml olarak task da kullanlmaktadr. letim sistemlerinin proses konusuyla uraan alt sistemine proses yneticisi (process manager) denilmektedir. Genel olarak bu konu proses ynetimi (process management) olarak isimlendirilir.

60

Bir proses oluturulduunda iletim sistemi, prosese ilikin btn bilgileri bir veri yapsyla ifade eder. Yani iletim sistemi, proses oluturulduunda ekirdek blgesi ierisinde dinamik bir alan tahsis eder. Proses bilgilerini o alana yerletirir. Prosese ilikin bilgilerin bulunduu alana proses tablosu denilmektedir. Proses tablosu ierisinde tipik olarak u bilgiler bulunmaktadr. - letim sisteminin proses iin tahsis ettii bellek alannn yeri - Prosese ilikin, gvenlik bilgileri - Prosesin alma dizini ve evre deikenleri - Prosese ilikin harcanan eitli zamanlar - Prosesin kulland kaynaklar - Dier nemli bilgiler phesiz iletim sistemi, almakta olan tm proseslere ilikin proses tablolarn belli bir dzen ierisinde organize etmektedir. rnein tipik olarak modern sistemlerde, tm proses tablolar bir bal liste ierisinde birbirlerine balanmtr. letim sistemi isterse, almakta olan tm proseslere eriebilir. Proses sonlandnda, prosesin tuttuu tm kaynaklar iade edilir. Proses tablosu da nihayet yok edilmektedir. letim sistemleri ayn anda birden fazla program altrp altrmamasna gre, tek veya ok prosesli olarak ikiye ayrlmaktadr. Tek prosesli (single processing, single tasking) sistemlerde, ayn anda tek bir program altrlabilir. rnein dos iletim sistemi byledir.

Hlbuki ok prosesli (multi processing, multi tasking) sistemlerde ayn anda birden fazla program alyor durumda olabilir. ok prosesli sistemlerde, prosesler zaman paylaml olarak altrlmaktadr. Yani, proses bir miktar altrlr, sonra almasna ara verilip dier proses bir sre altrlr. Sra eski prosese geldiinde kalan yerden almaya devam eder. Bir prosesin paral alma sresine kuanta sresi ya da kuantum denir. rnein Windows sistemlerin de eitli versiyonlarda deise de tipik 20ms lik bir kuanta sresi kullanlmaktadr. Kuanta sresi ok yksek tutulursa, prosesin kullanc etkileimi ve evreyle etkileimi azalr. Kuanta sresi ok dk tutulursa, vaktin nemli bir blm prosesler aras geite harcanr. Yani birim zamanda yaplan i miktar azalr. Birim zamanda yaplan i miktar through-put terimi ile ifade edilmektedir. Proses yneticisinin prosesleri altrp ara veren bu alt sistemine, proses

61

izelgeleyicisi (process scheduler) denilmektedir. Proses izelgelemesi eitli prensiplerle yaplabilmektedir. En ok kullanlan yntem, dngsel izelgeleme (round robin scheduling) dir.

P1

P2 letim Sistemi P5 P4 P3

Bu yntemde her prosese adil olarak eit zaman ayrlmaktadr. izelgeleme iin baka algoritmalar da kullanlabilmektedir. rnein pek ok iletim sisteminde proseslere ncelik derecesi atanabilmektedir. Bu ncelik derecesine gre proses birim zamanda dierlerine gre daha fazla CPU zaman kullanabilir. Fakat bu ncelik derecelendirmesinin de farkl sistemlerde ayrntlar vardr. Baz sistemlerde, prosese zg kuanta sresinin arttrlmas veya azaltlmas ile yaplmaktadr. rnein dier proseslerin kuanta sresi 20ms iken, zel bir proses 60ms lik kuanta sresini kullanabilmektedir. Baz sistemlerde ise, kuanta sresi deimemekle birlikte, bir turda baz proseslere daha fazla sra gelmektedir.
Anahtar Notlar: Bilgisayar sistemlerinde genel ve zel konular vardr. Genel anlatm, mevcut olan pek ok eyin ortak zellikleri zerine younlar. Fakat gerekteki durumlar eitlilik gstermektedir. te bu durumda belli bir sistem zerinde younlalabilir. zel bilgiler edinilmeden nce temel prensipler renilmesi uygundur. rnein, belirli bir Windows sisteminin nasl izelgeleme uygulad zel bir bilgidir. Bu durum Windows un versiyonlar arasnda dahi deiebilmektedir. phesiz izelgeleme konusu btn mevcut sistemleri kapsayacak ekilde genellenebilir.

ok ilemcili bilgisayarlarda iletim sistemi, her iki ilemciye de proses atayarak ayn anda iki ayn prosesin altrlmasn salayabilmektedir. Pek ok sistemde ortak bir izelgeleme kuyruu vardr. CPU lar da bamsz biimde almaktadr. Bir CPU da kuanta sresi bittiinde iletim sistemi kuyruktan ona sradaki prosesi atar. Yine pek ok bilgisayar sisteminde bir prosesin sonraki turda ayn ilemciye atanmas avantaj salayan bir durumdur. Bu nedenle iletim sistemi 62

mmkn olduunca toplam performans ykseltmek iin prosesi ayn ilemciye atamak istemektedir (nk bir prosesi bir ilemci altrrken o prosese ilikin bellek alanndaki kimi bilgiler CPU nun cache ine aktarlmaktadr. Cache deki bu bilgilerden yararlanmak avantaj salar.).
Anahtar Notlar: Genel olarak cache sistemleri gz nne alndnda, CPU nun rasgele bir bellek blgesine erimesi yerine, son eriilen yerlere yakn blgelere erimesi daha etkin olmaktadr. Bu durum locality of reference terimiyle ifade edilmektedir.

ok prosesli sistemlerde bir programn iki noktas arasnda geen zaman o anda sistemde ka prosesin alt ile dorudan ilgilidir. nk proses says arttka, proses bana den alma miktar azalr. Zaman ierisinde an ve an izlenmesi gereken baka sistemlerden bamsz bir almas olan sistemlere, gerek zamanl sistemler denir. Bu tr sistemler iin program yazarken, olay karma durumu oluabilir. rnein bir aygttan hzl bir biimde veri geliyor olsun, bizim srekli olarak bu aygta bakmamz gerekir. Fakat ok prosesli iletim sistemlerinde, programmzn almasnda ara verilebilmektedir. te prosesimiz almyor durumda iken bu olaylar karabilir. Windows, Linux gibi iletim sistemleri gerek zamanl olaylar izlemede iyi bir ortam sunmamaktadr. nk bu iletim sistemleri tipik olarak masast uygulamalarda performans ykseltmek iin tasarlanmtr. Hlbuki gerek zamanl olaylar, tipik deil zel durumlar oluturmaktadr. Hlbuki gerek zamanl olaylar izleyebilmek iin zel iletim sistemleri de vardr. Qnix ve Rtos gibi iletim sistemlerine gerek zamanl iletim sistemleri denilmektedir.

12.1. Proseslerin Bloke Olmas

Dosyadan bilgi okunmas, soketten bilgi beklenmesi, klavyeden okuma yapma gibi pek ok olay uzun sreli beklemelere yol amaktadr. te bir proses, bir fonksiyon ararak byle bir olay balattnda, iletim sistemi prosesi geici olarak izelge dna karr. lgili olayn gerekleip gereklemediini arka planda kesme tekniklerini de kullanarak izlemektedir. Olay gerekletiinde iletim sistemi prosesi yeniden izelgeye sokar ve fonksiyon geri dner. Burada fonksiyonu aran iin ekstra bir bekleme sz konusu deildir. Fakat iletim sistemi, proses bouna CPU zaman harcamasn diye onu izelge dna kartmaktadr. rnein iletim

63

sistemlerinin ounda sleep gibi bir isimde bekleme yapan bir fonksiyon vardr. rnein sleep(1000). Windows un bu sistem fonksiyonu 1 sn beklemeye yol aacaktr. te iletim sistemi bu prosesi geici olarak izelge dna kartr ve 1 sn sonra geri yerletirir. Dsal bir olay bekleyen bir prosesin geici sre, olay gerekleene kadar, izelge dna kartlmasna prosesin bloke edilmesi denir. Pek ok teorik kitapta bir prosesin yaam dngs ematik olarak gsterilir. Kullanlan tipik ekillerden biri yledir.

Wait alma balad

Star t

Run alma balad Quit

Ready

Burada Run prosesin CPU da almakta olduunu belirtir. Wait geici sre izelge dna klma durumunu anlatr. Ready, prosesin izelgede olduunu ama almak iin beklediini gstermektedir.

12.2.

Preemptive ve Non-Preemptive ok Prosesli Sistemler

ok prosesli sistemler kendi aralarnda preemptive ve non-priemptive olmak zer ikiye ayrlr. Preemptive sistemlerde kuanta sresi dolduunda bir donanm kesmesi yoluyla herhangi bir makine komutunda almaya ara verilmektedir. Non-preemptive sistemlerde almakta olan sistemin kendi isteiyle almaya ara verilir. Unix/Linux ve Win32 sistemleri preemptive sistemlerdir. Windows 3.1i, yani Win16 sistemleri non-priemptive sistemlerdir.

64

12.3. Modern letim Sistemlerindeki Koruma Mekanizmas

ok prosesli sistemlerde ayn anda birden fazla program alyor durumda olduuna gre bu programlar ayn zamanda RAM de bulunmaktadrlar. Peki, bir program gstericileri kullanarak baka bir programn bellek alanna eriip oray bozamaz m? rnein bir bankann hesap girii yapan program alrken, baka bir program bellekteki hesap bilgilerini deitirirse ne olur? te bu tr durumlarn bir biimde engellenmesi gerekir. Bir programn baka bellek alanlarna erimesini, sistemi kertecek makine komutlarn kullanmasn engelleyen

mekanizmaya koruma mekanizmas denilmektedir. Koruma mekanizmasnn oluturulmas birinci elden mikroilemcinin yardmyla salanmaktadr. letim sistemi ilemcinin salad olanaklardan faydalanr. Intel ilemcileri 80286 ve sonraki modellerinde koruma mekanizmasn salamaktadr. Intel 80x86 ilemcilerinin tane alma modu vardr: 1. Gerek Mod (Real Mode) 2. Korumal Mod (Protected Mode) 3. V86 Modu lemci reset edildiinde gerek modda almaya balar. Gerek mod koruma mekanizmasnn olmad DOS modudur. Korumal mod, mikroilemcinin tm kapasitesinin kullanld moddur. V86 modu hem korumal mod programlarnn hem de gerek mod

programlarnn altrld ara bir moddur. Intel ilemcileri RAM i sayfa denilen bloklara ayrmaktadr. Her sayfa 4K uzunluktadr ve her sayfaya bir numara verilmitir. Intel ilemcilerinde almakta olan kodun bir ncelik derecesi vardr. Toplam 4 ncelik derecesi vardr. Bunlar 0, 1, 2, 3 ile belirtilir. En yksek ncelik sfrnc nceliktir. En dk ncelik 3 numaral nceliktir. Windows, UNIX/LINUX yalnzca iki ncelik seviyesini kullanmaktadrlar (0, 3). Sradan programlara user mode programlar denir ve bunlar 3 ncelik derecesine sahiptir. letim sisteminin kendi kodlar ve aygt srcler 0 ncelik derecesine sahiptir ve bunlara kernel mode programlar denir. Intel sisteminde ayn zamanda bellekteki her 4k lk sayfaya 03 aras bir ncelik derecesi atanabilmektedir. Bir proses kendisi ile ayn seviyeli veya dk ncelikli bir sayfaya eriebilir,

65

daha yksek ncelikli bir sayfaya eriemez. Eer erimeye alrsa mikroilemci bunu tespit eder ve durumu iletim sistemine bildirir (page fault). letim sistemi de prosesi cezalandrarak sonlandrr. letim sistemi kendi kodlarn 0 ncelikli sayfalara yerletirir. Sradan proseslerin bellek alanlarn 3 ncelikli yapar. Bylece sradan programlar iletim sisteminin bulunduu bellek alanlarna eriip oralar bozamazlar. Fakat iletim sistemi her yere eriebilir. Bir user mode proses iletim sisteminin sistem fonksiyonunu ard zaman ne olur? Sistem fonksiyonu iletim sisteminin bir paras olduuna gre iletim sisteminin eitli veri yaplarn gncelleyecektir. Peki, bu durum koruma hatasna yol amaz m? te Intel ilemcileri kap (gate) denilen bir yntemle geici ncelik ykseltmesi salayabilmektedir. yle ki; kaplarda sistem fonksiyonlarnn balang adresleri bulunur. Kapya dallanma yapldnda otomatik olarak prosesin ncelii sfra ykseltilir. Bylece sistem fonksiyonu alrken proses kernel mode a gemi olur. Artk iletim sisteminin kodu almaktadr ve bellek korumas ortadan kalkmtr. Sistem fonksiyonu arldnda oluan bu geie prosesin kernel moda gemesi denilmektedir. Kod geri dnte otomatik olarak ncelik derecesi 3 e geri ekilir. Kernel moda gei greceli olarak yava bir ilemdir. nk akn gerek ii yapan koda gemesine kadar pek ok makine kodu altrlmaktadr. Baz makine komutlar dorudan sistemin kmesine yol aabilmektedir. Bu makine komutlar ancak 0 ncelikli prosesler tarafndan kullanlabilmektedir. rnein IN, OUT makine komutlar byle komutlardr. rnein seri port ve paralel port gibi veya bilgisayara taktmz kartlar gibi donanm birimleri ile haberlemek iin IN ve OUT komutlar gerekmektedir. Peki, biz bu tr programlar nasl yazacaz? te bunun iin 0 ncelikli kodlama yapmamz gerekir. Yani kodumuzu 0 ncelikli bir biimde altrmalyz. Fakat herkes bunu yapsa sistemi kertebilir. te byle zel programlara aygt src (device driver) programlar denilmektedir. O halde her eyi yapabilecek bir programn aygt src olarak yazlmas gerekir. Aygt srcler ncelikli ve yetkili kullanclar tarafndan altrlabilen programlardr. Biz bir aygt src yazdmz ve makineyi kertebileceimizi dnelim. Bu aygt srcy sistem yneticisinin yklemesi gerekir. Sistem yneticileri de emin olmadklar programlar yklemezler.
Anahtar Notlar: Sistem Fonksiyonlar letim sistemleri normal uygulama programlar gibi fonksiyonel bir yapyla yazlrlar. Sistem ierisindeki baz fonksiyonlar hem sistemin kendi almas srasnda sistem tarafndan hem de programc tarafndan arlabilmektedir. letim sisteminin byle fonksiyonlarna sistem fonksiyonlar ya da API (Application

66

Programming Interface) fonksiyonlar denilmektedir. Sistem fonksiyonlarnn isimleri ve parametrik yaplar sistemden sisteme deiebilmektedir.

12.4. Standart Dosya Fonksiyonlarnn Tamponlama lemlerinin Ayrntlar

fopen ile bir dosyay atmzda fopen alan her dosya iin bir tampon oluturur. Tampon <stdio.h> da bildirilen BUFSIZ sembolik sabitinin belirttii uzunluktadr. phesiz BUFSIZ deerini deitirirsek tampon uzunluu deimez. BUFSIZ yalnzca bize bu deeri vermek iin dnlmtr. BUFSIZ deeri pek ok derleyicide bir sektr uzunluu olan 512 deerindedir. Standartlarda tamponlama mekanizmasnn ayrntlarndan bahsedilmemitir. Yalnzca ana hatlaryla bir tamponun kullanlmas gerektiinden bahsedilmitir. Genellikle single cache line kullanlmaktadr. Tampon read/write amac ile kullanlr. Tamponun bellekteki balang adresi dosyann hangi blmnn tamponda olduu gibi bilgiler file yapsnn iinde tutulmaktadr. Bu durumda biz bir dosyay bayt bayt ele alacaksak uzun bir miktar okuyup kendi tamponumuzu oluturmamza gerek yoktur. Bu ii zaten standart dosya fonksiyonlar yapmaktadr. Tabi programc fonksiyon arlarndan zaman kaybetmek istemeyebilir. te bu nedenle fgetc fonksiyonunun getc isimli bir makrosu da bulundurulmutur. getc bir makrodur ve dorudan tampondan sradaki bayt karakterini almaktadr. Standartlara gre getc fonksiyonunun bir makro olmas zorunlu deildir. Makro olabilecei belirtilmitir. Yani getc fonksiyonu fgetc fonksiyonundan daha hzl alma eilimindedir. Standartlara gre her dosya iin tamponlama stratejisi 3 biimde olabilir. 1. Tam Tamponlama (Full Buffering): Bu modda tampon tam kapasite ile kullanlr. Yani bilgi tamponda varsa oradan verilir yoksa bir tampon okuma yaplr bilgi oradan verilir. Tampona yazma yaplmsa tampon boaltlmadan tampondaki bilgiler geri yazlr. 2. Satr Tamponlamas (Line Buffering): Bu modda tamponda bir satrlk bilgi tutulur. Yani tamponda hi bilgi olmadn dnelim ve fgetc fonksiyonu ile bir karakter okumak isteyelim. Gerek dosyadan bir tamponluk bilgi deil bir satrlk bilgi okunarak tampona ekilir. Bu modda yazma yapld zaman yine tampona yazlr. Tazeleme ilemi tam tamponlamada tampon dolunca ya da yeni bir bilgi tampona ekilecei zaman yapld halde bu modda \n karakteri yazld zaman yaplmaktadr. Yani bu modda \n karakteri dosyaya yazld anda tazeleme yaplmaktadr.

67

3. Sfr Tamponlama (No Buffering): Bu modda tampon hi kullanlmaz. Her okuma ve yazma ileminde dorudan sistem fonksiyonlar arlarak ilem yaplr.

Bir dosya aldnda default tamponlama stratejisi nedir? Standartlarda stdin, stdout ve stderr dosyalar iin baz eyler sylenmitir. Fakat normal dosyalar iin bir ey sylenmemitir. Yani derleyiciyi yazanlar default durumu istedii gibi alrlar. Hemen hemen her derleyicide default durum tam tamponlamadr. Bir dosyann tamponlama stratejisi dosya aldktan sonra fakat dosya zerinde henz hibir ilem yaplmadan deitirilebilir. Tampon stratejisi setbuf, setvbuf fonksiyonlar ile

deitirilmektedir.
void setbuf(FILE *stream, char *buf);

Bu fonksiyon temel olarak dosyann kulland tampon blgeyi deitirmek iin dnlmtr. kinci parametre NULL geilirse 0 tamponlamal moda geilir. setvbuf prototipi yledir.
int setvbuf(FILE *stream, char *buffer, int node, size_t size);

setvbuf fonksiyonu setbuf fonksiyonunu kapsamaktadr ve daha sonra eklenmitir. Fonksiyonun birinci parametresi dosya bilgi gstericisi, ikinci parametresi deitirilecek tamponun adresini belirtir. Tampon deiimi yaplmak istenmiyorsa bu parametre NULL geilmelidir. nc parametre tamponlama stratejisini belirtir. unlardan biri olabilir: _IOFBF _IOLBF _IONBF Drdnc parametre tamponun yeni uzunluunu belirtir. kinci parametre NULL girilirse, drdnc parametre ile biz yine tampon bykln deitirebiliriz. Fakat bu durumda tampon fonksiyon tarafndan tahsis edilir. Tabi eer tamponun yerini biz deitirmek istiyorsak tampon uzunluunu drdnc parametre ile belirtilen deere uygun tahsis etmeliyiz. Eer tamponlama stretejisi sfr tamponlama yaplrsa bu durumda ikinci ve drdnc parametreler dikkate alnmaz. Fonksiyon baarl ise 0 deerine, baarsz ise -1 deerine geri dner.

68

Standartlara gre setvbuf fonksiyonu baarl olmak zorunda deildir. rnein ktphaneyi tasarlayanlar normal dosyalara ilikin satr tamponlamas faydasz olduu iin bu geie izin vermeyebilirler. (rnein gcc derleyicilerinin yeni versiyonlar byle davranmaktadr.)

12.5. Proseslerin Adres Alan

alabilen bir program kabaca blmden oluur: 1. Kod 2. Data 3. Stack Programdaki tm fonksiyonlarn makine fonksiyonlar kod blmnde, statik mrl nesneler (global deikenler, statik yerel deikenler, stringler) data blmnde, yerel ve parametre deikenleri stack blmnde bulunurlar. allan program blok olarak bellee yklenir. Data blmndeki nesneler program sonlanana kadar bellekte kalrlar. Programn ak bloa girdiinde yerel deikenler stack zerinde yaratlrlar ve bloktan ktnda bellekten silinirler. Fonksiyon iki kez arldnda, fonksiyonun yerel deikenleri stack in tamamen farkl bir yerinde oluturulabilir. Bu alanlarn dnda bir de dinamik tahsisatlarda kullanlan heap denilen baka bir alan daha vardr. Heap blgesinin nerede olduu, burada tahsisatlarn nasl yapld, bykl sistemden sisteme deiebilir. Pek ok sistem Heap>Data>Stack biiminde bir blm yapsna sahiptir. Bu durumda rnein byk dizilerin, matrislerin nce heap zerinde sonra data blgesi zerinde tahsis edilmesi denenmelidir. Byk dizilerin yerel olarak tahsis edilmeleri iyi bir teknik deildir. Heap blgesi sistemlerde prosese zgdr. Yani bir programda yaplan dinamik tahsisatn o anda almakta olan programa etkisi yoktur. Bir proses sonlandnda heap blgesi de prosesle birlikte tamamen boaltlr. Threadli sistemlerde her thread, ayn data ve heap blmn ortak kullanr. Ancak her threadin stack i birbirinden ayrlmtr.
Anahtar Notlar: Thread Kavram Proses kavramnn dnda bir de proses, iindeki farkl aklar anlatan thread kavram vardr. Thread bir prosesin sanki farkl bir prosesmi gibi izelgelenen bir akdr. Prosesler tek bir thread ile almaya balarlar. Buna prosesin ana threadi denir ve dier threadler sistem fonksiyonlar arlarak herhangi bir zaman oluturulabilirler. Thread oluturan fonksiyonlarda threadin balang noktas bir fonksiyon adresi olarak verilir. Thread bir fonksiyon deil bir ak belirtir. Farkl iki thread ayn fonksiyon zerinde ilerleyebilir. Tabi bu threadler yerel deikenlerin farkl bir kopyasn kullanrlar. Yani bir threadin yerel deikeni dier

69

bir threadin yerel deikeniyle karmaz. Tm threadler ayn global deikenleri grrler. Win32 sistemleri, Linux sistemleri, MacOS sistemleri birden fazla threadle almaya izin veren sistemlerdir. ok threadli sistemlerde exit() fonksiyonu tm threadleri sonlandrmaktadr.

13. STDIN, STDOUT ve STDERR DOSYALARI


Dos, Windows, UNIX/LINUX iletim sistemlerinde klavye ve ekran (her ikisine birden terminal denilmektedir) birer dosya gibi ele alnmaktadr. rnein ekran sanki bir dosyadr, biz bu dosyaya yazma yaptmzda ekrana yazm oluruz. Klavye de bir dosya gibidir, biz bu dosyadan okuma yaptmzda klavyeden okuma yapm oluruz. getchar, gets ve scanf gibi giri fonksiyonlar aslnda birer dosya fonksiyonudur ve stdin dosyasndan okuma yapmaktadr. printf, puts, putchar gibi fonksiyonlar da birer dosya fonksiyonudur. Default olarak stdout dosyasna yazma yapmaktadrlar. Standartlarda stdin ve stdout dosyalarnn hangi aygta bal olduu hakknda bir ey sylenmemitir. Fakat tipik olarak stdin klavye ve stdout da ekran temsil etmektedir. Fakat bu durum zorunlu deildir. Yani rnein printf() ile fprintf(stdout, ) ayn anlamdadr. stderr hata mesajlarnn yazlmas iin dnlm bir dosyay temsil eder. Standartlarda stderr dosyasnn da balangta hangi dosya ile ilikin olduu konusunda bir ey belirtilmemitir. Mevcut sistemlerde stderr de iin banda ekran temsil etmektedir. stdin, stdout ve stderr FILE * trnden stdio.h ierisinde bildirilmi deikenlerdir. rnein tipik olarak stdio.h ierisinde yle bir grnt ile karlalmaktadr.
extern #define #define #define FILE stdin stdout stderr stdfiles[3] (&stdfiles[0]) (&stdfiles[1]) (&stdfiles[2])

13.1. Ynlendirme lemi

70

stdin, stderr ve stdout dosyalar program altrrken ya da daha sonra program alrken baka bir aygta ya da dosyaya ynlendirilebilir. Bir program altrrken Dos, Windows ve UNIX/LINUX ta komut satrnda byktr iareti ile ynlendirme yaplabilir. rnein; a > b (stdout b dosyasna ynlendirilmi oldu) Burada a program altrlacak fakat stdout b dosyasna ynlendirilecektir. Yani stdout dosyasna yazlanlar artk ekrana deil b dosyasna yazlacaktr. Komut satrndan < iareti stdin dosyasn ynlendirmek iin kullanlr. rnein a<b Burada a program altnda artk stdin dosyasnda okuma yaplmak istenirse gerekte b dosyasndan okuma yaplacaktr. Byktr ve kktr iaretleri birlikte kullanlabilir. A>b<c Burada stdout b dosyasna stdin c dosyasna ynlendirilmitir. Dos, Windows ta program altrrken stderr yi ynlendirmenin bir yolu yoktur. Fakat UNIX/LINUX sistemlerinde 2> sembol ile stderr de ynlendirilebilir. Biz a programn a > b biiminde altralm. Bu durumda stdout b dosyasna ynlendirilir fakat stderr ekran olarak kalr. UNIX sistemlerinde ve modern sistemlerin ounda, pipe denilen bir ilem sz konusudur. rnein:
C:\> a | b

Burada ubuk sembolne pipe denir ve u ilem yaplr: Sistem a ve b programlarn altrr ama a nn stdout dosyasn b nin stdin dosyasna ynlendirir. Bylece a da ekrana yazlanlar, b de klavyeden girilmi gibi ilem grecektir. Aslnda program altrldktan sonra yazlm yolu ile de ynlendirme yaplabilir. Standart freopen fonksiyonu ynlendirme yapmakta kullanlabilmektedir.
FILE *freopen(const char *path, const char *node, FILE *stream);

Fonksiyonun birinci parametresi hedef dosyann yol ifadesidir. kinci parametre a modunu belirtir. nc parametre ynlendirilecek dosyay belirtir. Fonksiyon birinci parametresi ile belirtilen hedef dosyann bilgi gstericisi ile geri dner. Fonksiyon baarsz olabilir. Bu durumda NULL adresi ile geri dnmektedir.

71

FILE *f; int i; if ((f = freopen("test.txt", "w", stdout)) == NULL) { printf("cannot redirect file !...\n"); exit(EXIT_FAILURE); } for (i = 0; i < 10; i++) printf("%d\n", i);

Burada stdout dosyas test.txt dosyasna ynlendirilmitir. Artk printf fonksiyonu ekrana deil test.txt dosyasna yazacaktr. rneimizdeki f dosya bilgi gstericisi kullanlmamtr fakat alan test.txt dosyasna ilikindir.

13.2. Stderr dosyasnn kullanlmas

Programc eitli hata ve uyar mesajlarn stdout dosyasna deil stderr dosyasna yazdrmaldr. Her ne kadar default durumda normal mesajlar ile hata mesajlarnn her ikisi de ekrana kacak olsa da bunlarn gerektii yerde birbirinden ayrlmas salanabilir. Program ierisindeki hata mesajlarnn printf() fonksiyonu ile stdout dosyasna deil de fprintf() ile stderr dosyasna yazdrlmas daha iyi bir tekniktir. rnein:
if((f = fopen(ptr)) == NULL){ fprintf(stderr, "...."); exit(EXIT_FAILURE); }

Bylece tm hata mesajlar baka bir dosyaya ynlendirilebilir.


Anahtar Notlar: rnein pek ok windows ve linux komutu normal mesajlar stdout dosyasna, hata mesajlarn stderr dosyasna yazdrmaktadr. Bizde ynlendirme sayesinde bu hata mesajlarn baka bir dosyaya ynlendirerek onlarn ekrana kmasn engelleyebiliriz. rnein find / -name sample.c 2> /dev/null /dev/null dosyas zel bir dosyadr ve bu dosyaya yazlanlar otomatik olarak silinmektedir. Bu dosya windows ta bulunmamaktadr. Stdin, stdout ve stderr dosyalar program baladnda alm kabl edilir ve programc bunlar kapatmaya almamaldr.

72

13.3. Stdin, stdout ve stderr dosyalarnn tamponlama mekanizmalar

Stdin, stdout ve stderr dosyalar tpk dier dosyalar gibi tampon (cache) kullanmaktadr. Aslnda aygtlarn dosya gibi deerlendirilmesi temelde iletim sisteminin salad bir mekanizmadr. rnein getchar gibi stdin dosyasndan okuma yapan bir fonksiyon arldnda bu fonksiyon iletim sisteminin sistem fonksiyonunu ararak okumay yapmak ister. letim sisteminin fonksiyonu klavyeden girilen karakterleri standart C fonksiyonuna verir. Standart C fonksiyonlar da bunlar tamponlayarak kullanr. Standartlara gre stdin ve stdout dosyalar iin default tamponlama stratejisi iin banda eer bu dosyalar karlkl etkileimli bir aygta ynlendirilmise (klavye ve ekran byledir) tam tamponlamal olamaz. Satr tamponlamal veya sfr tamponlamal olabilir. Karlkl etkileimli bir aygta ynlendirilmemise tam tamponlamal olmak zorundadr.Daha sonra bu tamponlama stratejileri deitirilebilir. Standartlara gre stderr dosyas iin banda ister karlkl etkileimli bir aygta ynlendirilmi olsun isterse olmasn kesinlikle tam tamponlamal olamaz. Sfr tamponlamal yada satr tamponlamal olabilir. Standartlardaki bu anlatmlardan nemli sonular kartlabilir.

13.4. Stdout zerindeki tamponlamann etkisi

Eer stdout balangta sfr tamponlamal ise putchar, printf gibi fonksiyonlar onlar hi tampona yazmadan dorudan iletim sisteminin sistem fonksiyonunu kullanarak ekrana yazdracaktr. Fakat stdout balangta satr tamponlamal ise printf, putchar gibi fonksiyonlarn yazdrdklar eyler nce tamponda biriktirilecek \n karakteri grldnde tampondan alnarak hepsi ekrana yazdrlacaktr. Bu durum aadaki ilgin sonucu dourmaktadr.
printf("ali");

Burada ak ok ile gsterilen satra geldiinde ali yazsnn ekrana kmas garanti deildir. sfr tamponlama sz konusuysa kar fakat satr tamponlama sz konusu ise kmaz. Bunun yerine aadaki gibi yazlsn.
printf("ali\n");

73

Burada ak ok ile gsterilen blgeye geldiinde ali yazsnn ekrana kmas garanti altna alnmtr. Tabi eer stdout karlkl etkileimli bir aygta deil dosyaya ynlendirilmise her iki durumda da yaznn dosyaya yazlmam olmas gerekir.
Anahtar Notlar: Microsoft derleyicilerinde ve borland derleyicilerinde stdout default olarak sfr tamponlamaldr. Halbuki gcc derleyicilerinde default olarak satr tamponlamaldr.

Aadaki durumda yaz kesinlikle ekranda kar.


printf("ali"); fflush(stdout);

fflush fonksiyonu o anda tamponda bulunan bilgileri aygta aktararak tamponu boaltmaktadr. Standartlarda zorunlu tutulmam olsa da stdin den okuma yapan fonksiyonlarn nce stdout dosyasna flush edebilecei belirtilmitir. Gerekten de stdin den okuma yapan fonksiyonlar genellikle stdout dosyasn flush etmektedir. rnein;
printf("sayi giriniz :"); scanf("%d", &sayi);

Her ne kadar burada say giriniz yazsnn kmas garanti deilse de scanf fonksiyonu stdout dosyasn flush edecek biimde yazlm olabileceinden dolay yaz ekranda gzkecektir. Garanti bir durum iin yine fflush uygulanmaldr.

13.5. Stdin zerindeki tamponlamann etkisi

Her ne kadar stdin dosyas iin banda sfr tamponlamal yada satr tamponlamal olabilirse de pratikte hemen her zaman satr tamponlamal olarak karmza kmaktadr. nk iletim sistemleri klavyeden enter tuuna baslana kadar okuma yapmaktadrlar. Stdin dosyasndan okuma yapan fonksiyonlarn hepsi nce tampona bakar. Mevcut bilgi orada varsa hemen tampondan alr ve gerek bir klavye okumas yapmaz. Fakat tamponda bilgi

74

yoksa iletim sisteminin sistem fonksiyonunu ararak klavyeden bir satrlk bilgi okur ve onu tampona yerletirir, tampondan verir. rnein:
ch = getchar(); puthcar(ch); ch = getchar(); putchar(ch);

Girite kullandmz enter tuu \n anlamna gelmektedir ve \n karakteri de tampona yerletirilir. Yukardaki rnekte ilk getchar arldnda fonksiyon stdin tamponunda karakter olmadn grr ve bir satrlk bilgiyi klavyeden okuyarak tampona yerletirmek ister. rnein biz A Girii yapm olalm. Getchar tampona a\n karakterlerini yerletirecektir. lk getchar fonksiyonu bize a y verece sonraki hi bekleme yapmadan \n yi verecektir. Getchar, gets, scanf gibi fonksiyonlarn hepsi ayn stdin dosyasndan okuma yaptna gre ve stdin iin ortak bir tampon olduuna gre bu fonksiyonlar ayn tampondan almaktadr. rnein:
#include <stdio.h> int main(void) { int ch; char s[30]; ch = getchar(); printf("%c\n", ch); gets(s); puts(s); return 0; }

Burada klavyeden ali girilip enter a baslm olsun. lk getchar a y alacak, gets ise li yi alacaktr.

13.6. C nin Stdinden Okuma Yapan Fonksiyonlar

75

C programlama dilinde stdin dosyasndan okuma yapan getchar, gets, scanf gibi standart fonksiyonlar bulunmaktadr.

13.6.1. getchar Fonksiyonu Getchar fonksiyonu stdin dosyasndan bir karakter okur. Prototipi yledir:
int getchar(void);

Fonksiyon baarl ise okunan deere, dosya sonuna gelinmise veya IO hatas olumusa EOF deerine dner. Baar durumunda yksek anlaml baytlar sfr, dk anlaml bayt okunan deerle geri dner. Baarszlk durumunda tm baytlar ff olan -1 deerine geri dner.
Anahtar Notlar: stdin dosyas klavyeye ynlendirilirse EOF etkisi yaratmak iin zel bir tu kombinasyonu kullanlmaktadr. Bu tu kombinasyonu dos ve windows sistemlerinde ctrl+z ve UNIX/LINUX sistemlerinde ctrl+d tulardr. Windows ta ctrl+z nin satr banda verilmesi gerekir. rnein int ch; while ((ch = getchar()) != EOF) putchar(ch); return 0; Eer stdin dosyas bir dosyaya ynlendirilmi ise bu dngden dosyann sonuna gelindiinde klr. Eer klavyeye ynlendirilmi ise ctrl+z veya crtl+d tular ile klr. Bu tulara basldktan sonra stdin kapatlmaz burada sadece yapay bir etki sz konusudur. Anahtar Notlar: Pek ok sistemde stdin sfr tamponlamal moda geememektedir. Bunun nedeni iletim sisteminin enter tuuna gereksinim duymasndandr.

13.6.2. gets Fonksiyonu Fonksiyon prototipi yledir.


char *gets(char *str);

76

Eer fonksiyon en az bir karakteri yerletirirse parametresi ile belirtilen adresin aynsna geri dner. Tamponda yalnzca \n olsa, gets bu \n yi alp NULL karakter yerletirir ve parametresi belirtilen adresin aynsna geri dner. Eer gets hibir yerletime yapmadan EOF grrse yani o anda dosya sonuna gelinmise NULL adres ile geri dner. rnein:
#include <stdio.h> int main(void) { char s[1024]; while (gets(s) != NULL) printf("%s\n", s); return 0; }

Burada ctrl+z/d yada EOF grlene kadar dng yinelenir. gets fonksiyonunu getchar kullanarak yazalm.
#include <stdio.h> char *mygets(char *str) { char *ptr = str; int ch; while ((ch = getchar()) != '\n' && ch != EOF) *ptr++ = ch; *ptr = '\0'; if (str == ptr && ch == EOF) return NULL; return str; } char *kaan_gets(char *str) { size_t i; int ch; for (i = 0; (ch = getchar()) != '\n' && ch != EOF; ++i) str[i] = ch; if (i == 0 && ch == EOF) return NULL; str[i] = '\0';

77

return str; }

int main(void) { char s[1024]; while (mygets(s) != NULL) printf("%s\n", s); return 0; }

Maalesef gets fonksiyonu kt tasarlanm bir fonksiyondur. nk diziyi ne kadar byk aarsak aalm daha uzun bir giri yaplabilir. Yani program her zaman kertmek mmkn olabilmektedir. Giri ok byk olduunda tm karakterlerin alnmasndan ziyade programn kmemesi nemlidir. Bu nedenle bu tr fonksiyonlar artk bir gvenlik parametresi ile tasarlanmaktadr. Fonksiyonun ikinci parametresi dizinin uzunluu biiminde girilmelidir. Fonksiyon en fazla size-1 karakter okur ve NULL karakteride yerletirerek diziyi tarmaz. Dier davran gets gibidir. gets_s fonksiyonunu kendimiz yazalm. rnein:
char *safe_gets(char *str, size_t size) { size_t i; int ch; for (i = 0; i < size 1 && (ch = getchar()) != '\n' && ch != EOF; ++i) str[i] = ch; if (i == 0 && ch == EOF) return NULL; str[i] = '\0'; return str; }

Anahtar Notlar: GNU ld linker gets fonksiyonunda uyar vermektedir. Ayrca gets gibi klasik yanl tasarlanm baz standart fonksiyonlar iin microsoft derleyicileri artk uyar vermektedir. Yeni microsoft derleyicilerinde bu fonksiyonlarn gvenli biimleri de bulunmaktadr. Gvensiz fonksiyonun ismi xxx ise Microsoft un bunlar iin yazd gvenli versiyonlar xxx_s biiminde isimlendirilmitir. rnein:

78

#include <stdio.h> int main(void) { char s[1024]; while (gets_s(s, 1024) != NULL) printf("%s\n", s); return 0; } Maalesef Visual C 8.0 (Visual Studio 2005) bu fonksiyonlar iin yanl bir biimde deprecated terimi kullanlmtr. Halbuki deprecated terimi standartlara zg resmi bir terimdir ve ileride standartlardan kaldrlmas dnlen diz zelliklerini belirtir. gets gibi fonksiyonlar resmi bir biimde depricated deildirler. Bu uyar mesajlarn kaldrmak iin iki yol izlenebilir. Programn tepesine: #define _CRT_SECURE_NO_WARNINGS Yazlabilir. Programn yukarsnda define etmek yerine nceden tanmlanm sembolik sabit yntemi de kullanlabilir. Belirli bir uyar mesajn pasif hale getirir. #pragma warning nilemci komutu kullanlabilir. lgili waning in numaras 4996 dr. Bu durumda pragma komutu yle kullanlabilir. #pragma warning(disable:4996) #pragma standartlarda bahsedilmitir. Fakat yanna gelenler derleyiciyi yazanlara braklmtr.

Aslnda pek ok ktphanede stdin den okuma yapan dier fonksiyonlar getchar kullanmaktadr. Gets stdin dosyasndan ald karakterleri parametresi ile belirtilen adrese yerletirir. \n karakterini de okur fakat \n yerine \0 karakterini yerletirir. Grld gibi nce gets sonra getchar kullanlsa sorun olumaz fakat nce getchar sonra gets kullanlrsa gets tampondaki \n yi alarak sonlanr.

13.6.3. scanf Fonksiyonu Fonksiyon prototipi yledir:


int scanf(const char *format, ...);

scanf fonksiyonu her trden bilgiyi okuma iddiasnda olan genel bir fonksiyondur. scanf fonksiyonu bataki boluk karakterlerini atarak ilerler. Karakterleri yine tek tek stdin dosyasndan

79

okumaktadr. Giri formatna uygun olmayan bir karakter grdnde onu ungetc fonksiyonu ile tampona geri brakp ilevini sonlandrr. scanf fonksiyonu baarl bir biimde yerletirilmi olan para says ile geri dner. scanf fonksiyonu bataki boluklar atar fakat sondaki boluklar atmaz. rnein:
#include <stdio.h> int main(void) { int a, b, result; char str[10]; result = scanf("%d%d", &a, &b); printf("result = %d a = %d b = %d\n", result, a, b); gets(str); puts(str); return 0; }

scanf fonksiyonu eer hibir yerletirme yapamazsa EOF deeri ile geri dner. rnein aadaki dng ile boluk karakterleri ile ayrlm tm saylar okunabilir. rnein:
#include <stdio.h> int main(void) { int val; while (scanf("%d", &val) != EOF) printf("%d\n", val); return 0; }

Eer giri uygun olmazsa, rnein say yerine alfabetik karakterler girilirse sonsuz dng oluur. Kullancnn Ali yazp Enter a bastn dnelim. scanf A y alp beenmeyecek ve onu tampona geri brakacaktr. Bu durumda 0 ile geri dnecektir. Dngden kmak iinde bir neden kalmayacaktr. Peki, uygunsuz bir deer girildiinde de dngden kmak isteyelim. rnein:
#include <stdio.h>

80

int main(void) { int val, flag; while ((flag = scanf("%d", &val)) != EOF && flag) printf("%d\n", val); return 0; }

scanf de format karakteri olmayan bir karakter girite bulundurulmak zorundadr. rnein:
#include <stdio.h> int main(void) { int day, month, year; int result; result = scanf("%d/%d/%d", &day, &month, &year); printf("result = %d day = %d month = %d year = %d\n", result, day, month, year); return 0; }

Burada giriler arasnda bl karakterleri bulundurulmak zorundadr. Format ksmnda herhangi bir boluk karakteri boluk karakteri grmeyene kadar boluklar at anlamna gelir. ki format karakteri arasnda karakter yoksa sanki boluk karakteri varm gibi deerlendirilir. Yani %d%d ile %d %d ve %d\n%d ayn anlamdadr. Boluk karakterlerinin bir veya birden fazla olmasnn hibir nemi yoktur. rnein:
int main(void) { int day, month, year; int result; result = scanf("%d / %d / %d", &day, &month, &year); printf("result = %d day = %d month = %d year = %d\n", result, day, month, year); return 0; }

81

Aadaki ilemde muhtemelen \n yanllkla konulmutur. (\n yerine boluk (space) de olabilirdi.) scanf bu durumda stdin den srekli okuma yapar boluk karakterlerini atar, ilk boluk olmayan karakteri okur, onu tampona geri brakp ilemini sonlandrr. rnein:
scanf("%d\n", &val);

13.7. Stdin Tamponunun Boaltlmas

Stdin den yeni bir giriin istenmesi iin \n grlene kadar (\n dahil) okuma yaparak karakterleri tampondan atmak gerekir. Maalesef bunu yapan standart bir C fonksiyonu yoktur. Bazen bu ilem iin fflush(stdin) armasnn yapld grlmektedir. Fakat bu arma standartlara gre geerli deildir. nk standartlarda ak bir biimde stdin dosyasnn r modunda alm olduu bu modda alan dosyalara fflush fonksiyonunun uygulanamayaca belirtilmitir. Fakat yine de bu arma baz derleyicilerde ie yaramaktadr. Stdin tamponunu boaltmak iin aadaki ilem uygulanabilir.
while (getchar() != '\n') ;

Ancak burada kk bir problem vardr (geri bu problem ihmal edilebilir). Eer \n den nce EOF grlrse sonsuz dng oluur. O halde daha salam bir durum yle oluturulur.
while ((ch = getchar()) != '\n' && ch != EOF) ;

Tabi bu kodun ikide bir yazlmas yerine ilem fonksiyona yaptrlabilir. rnein:
#include <stdio.h> #include <stdlib.h> void clr_stdin(void) { int ch; while ((ch = getchar()) ; } != '\n' && ch != EOF)

rnein bir kiiden nce numara, sonra isim isteyelim. Numara scanf ile ismi gets ile alacamz dnelim.

82

#include <stdio.h> #include <stdlib.h> void clr_stdin(void) { int ch; while ((ch = getchar()) ; } int main(void) { int no; char name[50]; printf("no: "); scanf("%d", &no); printf("adi soyadi :"); gets(name); printf("no: %d name = %s\n", no, name); } != '\n' && ch != EOF)

Burada tampon boaltlmalyd. Aadaki gibi olmalyd.


#include <stdio.h> #include <stdlib.h> void clr_stdin(void) { int ch; while ((ch = getchar()) ; } int main(void) { int no; char name[50]; printf("no: "); scanf("%d", &no); printf("adi soyadi: "); clr_stdin(); gets(name); printf("no: %d name = %s\n", no, name); } != '\n' && ch != EOF)

83

13.8. gets Fonksiyonu Yerine fgets Fonksiyonunun Kullanlmas

fgets fonksiyonunda bir gvenlik parametresi olduu iin baz programclar gets fonksiyonu yerine fgets fonksiyonunu kullanmaktadr. Fakat maalesef fgets \n karakterini de yerletirmektedir. O halde \n karakterinden de kurtulmak gerekir. Bu ilem klasik olarak yle yaplmaktadr.
#include <stdio.h> int main(void) { char s[SIZE]; char *pStr; fgets(s, SIZE, stdin); if ((pStr = strchr(s, '\n')) != NULL) *pStr = '\0'; return 0; }

14. ALGORTMA ANALZ


Bir problemi zmne gtren admlar topluluu iin kullanlan terimdir. Algoritma szc genellikle kesin zmler iin kullanlr. Kesin zm garanti etmeyen algoritmik yntemler iin heuristic terimi tercih edilmektedir. Algoritmalar eitli bak alarna gre snflandrlabilirler. Konuya gre snflandrma yapldnda ilk akla gelenler unlar olabilir: - Saylar teorisine ilikin eitli algoritmalar (blme, arpma, asal bulma vs..) - Sraya dizme algoritmalar - Arama algoritmalar

84

- Veri yaplarna zg algoritmalar - Optimizasyon algoritmalar - Graf algoritmalar - Yazlma ynelik temel algoritmalar - Dierleri

D. Knuth un 3 ciltlik The Art of the Computing isimli kitab temel referans kitab olarak kabul edilmektedir. Kitabn ciltleri yledir: 1- Fundamental Algorithms 2- Semi Numerical Algorithms 3- Sorting and Searching Gnmzde her tr zel algoritma konusu iin ayr kitaplar bulunmaktadr. Baz algoritmalarn matematiksel ya da istatistiksel temeli vardr. Baz algoritmalar tamamen temel matematiksel problemlerin saysal yntemle zmne ilikindir. rnein; Belirsiz integralle hesap yapma, dorusal denklem sistemlerinin zm, Bir algoritma nasl aklanabilir? Szel anlatm belirli bir noktaya kadar etkilidir, fakat ince ayrntlar aklamakta yetersiz kalr. Algoritmann programn yazmak, daha aklayc olsa da bu durumda algoritma az ok dile bal hale gelmi olur. Ak emalar gibi yntemler dilden bamsz gsterim salamak iin kullanlr. Genellikle bu yntemlerin hepsine ayn anda bavurulabilir. Fakat algoritma tamamen dilden bamsz olarak aklanamaz. algoritma kitaplar genellikle bir programlama dilini temel alarak hazrlanr. Knuth, klasik kitabnda algoritmalarn gerekletirilmesini, MIX ismini verdii, sembolik makine dilinde yapmtr. Bu yntem detaylarn aklanmas iin faydal olsa da can skc olabilmektedir. Bir algoritma dierinden daha iyi midir? Nasl kyaslayabiliriz? Kyaslama iin en ok kullanlan iki lt, hz ve kaynak kullanmdr. Hz lt baskn bir ekilde tercih edilmektedir. Bu nedenle kyaslamada hibir eyden bahsedilmemise, hz bakmndan kyaslama yaplaca anlalmaktadr. Hz kyaslamas basit bir konu deildir. Koda bakar bakmaz algoritmann hzn anlayamayz. Algoritmalarn ou bir dizi gibi, bilgiler zerinde ilemler yapar. Bu durumda bu bilgilerin istatistiksel dalm, sonu zerinde etkili olabilir. Bu nedenle,

85

Kyaslama iin simlasyon yntemi her zaman geerli bir yntem olarak kullanlabilir. Bu yntemde iki algoritmann da program yazlarak ilem zaman belirlenir. Girdi kmesinin etkisini ortalamak iin, deney bir kez deil, ok fazla kez yinelenmelidir. Elde edilen ortalama deer kyaslama iin kullanlmaldr. Bu yntem, uygulamas ok zor bir yntemdir. Bu nedenle, kyaslama iin saysal yntemler tercih edilmektedir. Baz problemler (zellikle optimizasyon problemleri) girdi kmesi bydke ar derecede bilgisayar zaman gerektirmektedir. Maalesef bu algoritmalarn, byk girdi kmeleri iin makul bir zm bulunmamaktadr. te bu tr durumlarda en iyi zm yerine kaliteli bir zm ile yetinilebilir. rnein, gezgin satc problemi traveling salesman problem NP (non-polynomial) tarzda zor bir problemdir. Bu problemde bir merkezden yola kan kii, tm ehirlere urayarak yine merkeze geri dnmek istemektedir. Hangi rotay izlemesi gerekir? Baz algoritmalarn datk biimleri sz konusu olabilmektedir. rnein algoritma bamsz bir takm paralar paralel yrtp sonra sonular birletirebilir. Byk bir matrisin arpm bu biimde gerekletirilebilir. Ancak her trl datk zm hz arttrmayabilir. nk ilerin makinelere datlp toplanmas da zaman kayb iermektedir. Algoritmalarn bu biimde datk srmlerine datk algoritmalar (distributed algorithms) denilmektedir.

14.1. Algoritmann Karmakl

Algoritmalar kyaslayabilmek iin kullanlan yntemlerden dieri, algoritmann karmakl denilen yntemdir. Bu yntemde, algoritmay temsil eden bir ya da birden fazla ilem seilir, bu ilemin ka kez yapldna baklr. Muhtemelen bu say eitli girdilerin bir fonksiyonu olacaktr. rnein; Algoritma, O(k,l,m) gibi parametreli olabilir ve bu ilemin says da bu parametrelerin bir fonksiyonu olarak ifade edilebilir. rnein bir dizi ierisindeki en byk saynn bulunmas algoritmasna bakalm:
max = a[0];

86

for (i = 1; i < n; ++i) if (max < a[i]) max = a[i];

Burada if deyimini kritik ilem olarak seersek karmaklk O(n) = n1 olur. Fakat karmakln fonksiyonunu karmak o kadar kolay olmayabilir. rnein, dizi ierisinde kesinlikle olduu bilinen bir sayy sral bir biimde arayalm:
for (i = 0; i < n; ++i) if (val == a[i]) { /******/ return; }

Burada en iyi olaslkla bir kez, en kt olaslkla n kez kontrol yaplacaktr. Peki, ortalama nedir? te karmakl ortalama olarak ve en kt olaslkla bazen de en iyi olaslkla ayr ayr belirlemek faydal olabilir. Bu algoritmadaki en kt durum, O (n) = n Ortalama durum iin yle bir hesap yaplabilir: (1 + 2 + 3 + ... + n) / n = n(n 1) /(2n) = (n + 1) / 2 Algoritmann kesin karmaklnn bulunmas ou zaman istatistiksel hesaplamalar gerektirmektedir. Girdi kmesinin dalm konuyu hemen istatistik ve olaslk tarafna eker. Algoritma analizi, genellikle yukardaki yntemle ve matematiksel ilemlerle

gerekletirilmektedir ve matematiin bir konusudur. Pratik karmlar iin kategori yaklam kullanlr. Kategori yaklamnda algoritmalar, iyiden ktye doru eitli snflara ayrlr. Ayn snfta bulunan algoritmalar iin daha iyi analiz yaplmas gerekir. yiden ktye doru karmaklk snflar unlardr: - O(1) sabit karmaklk - O(n) = logn logaritmik karmaklk - O(n) = n dorusal karmaklk - O(n) = nlogn dorusal logaritmik karmaklk - O(n) = n2 karesel karmaklk - O(n) = n3 kpsel karmaklk

87

- O(n) = nk polinomsal karmaklk - O(n) = kn stel karmaklk - O(n) = n! faktriyel karmaklk - Ve dierleri

En iyi karmaklk snf sabit karmaklktr. Eer algoritmada bir dng yoksa algoritma tekil ilemlerle gerekletirilmise, sabit karmaklk sz konusudur. rnein genin alannn bulunmas byledir. Logaritmik karmaklkta bir dng vardr, fakat dng logaritmik bir biimde dnmektedir. rnein, sral diziler zerinde ikili arama ynteminde olduu gibi. Eer algoritma i ie dng iermiyorsa bir ya da birden fazla tekil dng ieriyorsa dorusal karmaklk sz konusudur. rnein, dizi toplamn bulmak byle bir karmaklk ierir. Son iki kategori, dorusal logaritmik karmaklktr. Bu algoritmalarda i ie iki dng olmakla beraber, dnglerden biri logaritmik dnmektedir. zyinelemeli baz algoritmalarda bu durumla karlalmaktadr. rnein tipik olarak quick sort algoritmasnda olduu gibi. Eer algoritmada i ie iki dng varsa (birden fazla olabilir ve ayrca birden fazla tekil dng de var olabilir), karmaklk kareseldir. ie 3 tane, 4 tane ve k tane dng sz konusu olabilir. Bu durumda tipik olarak kpsel ve ksal karmaklk durumlar oluur. Polinomun derecesi nemlidir. rnein, bir algoritma 5 tane i ie dng 3 tane de tekil dng ieriyor olsun. Dieri bir tane i ie 6 tane dng ieriyor olsun. kinci polinomun derecesi daha yksektir. stel ve faktriyel karmaklklar, polinomsal olmayan (non-polynomial) karmaklk denir. NP problemler, bilgisayarlarla zm adeta mmkn olmayan zmlerdir. rnein, gezgin satc problemi, tipik bu gruptandr. NP problemlerin nemli bir blmnde, zm verildiinde, bunun snanmas, polinomsal karmaklkta yaplabilir. (Bu nedenle, NP problemlerin aslnda polinomsal zmlerinin olduu, fakat henz bulunamad biimde bir umut da srmektedir.) Sonu olarak, iki algoritmay kyaslamak iin kabaca kategori yaklamn kullanabiliriz. Daha ayrntl kyaslama iin kesin karmaklk deerleri hesaplanabilir. rnein, kabarck (bubble) sralamas ve seerek (selection) sralama algoritmalarnn her ikisi de i ie iki dng

88

gerektirmektedir. Bu durumda bu iki algoritma da karesel karmaklktadr ve benzer performanstadr. Biz ikisi arasndaki fark daha ak ifade etmek iin kategori yaklamndan kp kesin karmakl hesaplamamz gerekir. Hlbuki quick sort algoritmas logaritmik dnen ve normal dnen i ie iki dng ierir. Karmaklk kategorisi nlogn dorusal logaritmiktir. Bu durumda quick sort algoritmas dier ikisinden daha iyi bir algoritmadr.

15. TEMEL VER YAPILARI

Aralarnda fiziksel ya da mantksal iliki bulunan birden fazla nesnenin oluturduu toplulua veri yaps (data structures) denir. Baz veri yaplar programlama dili tarafndan sentaks olarak dorudan desteklenmektedir. rnein diziler, yaplar ve birlikler byledir. Dier veri yaplar dildeki, mevcut olanaklar kullanlarak oluturulur. En fazla kullanlan temel veri yaplar unlardr: Kuyruklar Stack sistemleri Bal listeler Hash tablolar kili aalar

Bu veri yaplarnn dnda greli olarak daha az kullanlan baka veri yaplar da vardr. rnein ikili aalarn dnda deiik aa yaplar, graf veri yaps gibi Tipik bir veri yaps, bir handle sistemi kullanlarak kurulabilir. Tipik bir veri yapsnda, nesnelerin yerletirilecei alanlar ve ilem yapan fonksiyonlar bulunur. Nesnelerin saklanaca alan, handle sisteminin iinde organize edilebilir. lem yapan fonksiyonlar, handle deerini parametre olarak alr ve ilem yaparlar.

15.1. Kuyruk Veri Yaps

89

Kuyruk veri yaps, FFO prensibi ile almaktadr. Kuyrua eleman yerletirme ve kuyruktan eleman alma gibi iki ilem sz konusudur. Yerletirme kuyruun sonuna yaplr, kuyruun bandan eleman alnr. Kuyruun belli bir kapasitesi sz konusudur. Kuyruk boken eleman alnamaz, dolu iken eklenemez.

15.1.1. Kuyruk Veri Yapsnn Kullanm Alanlar

Kuyruk veri yaps, bilgilerin geici sre bekletildii durumlarn ounda kullanlmaktadr. rnein tipik olarak, bilgi bir kanaldan gelip, baka bir kanaldan alnmaktadr. Bu ilemler paralel yrtlmektedir. Bilgi geldiinde, bir kuyrua yerletirilir, sonra sras bozulmadan kuyruktan alnr. rnein klavyeden baslan tular kaybolmamakta, bir kuyrua yerletirilmektedir. Seri porttan alnan bilgiler iletim sistemi tarafndan bir kuyrua yerletirilebilir ve porttan okuma yapld srada byk olaslkla kuyruklanm bilgi alnmaktadr (veri yaps kuyruk, bekleme ii tamponlama denir). Ya da rnein, yazcya birden fazla print istei yollanm olsun. Bunlar bir kuyruk sisteminde saklanr. Yazc iini bitirdiinde kuyruktan yeni i isteyip yazar. C de kuyruk iin zel bir veri yaps yoktur. C++ da Queue isimli template snf, C# ve Javadaki Queue snf temel kuyruk ilemlerini yapmaktadr.

15.1.2. Kuyruk Veri Yapsnn Gerekletirilmesi

Kuyruk yaps 3 biimde gerekletirilebilir: 1. Dizi kaydrma yntemi ile 2. Dngsel yntem ile 3. Bal liste yntemi ile

15.1.2.1. Dizi Kaydrma Yntemi ile Kuyruk Yapsnn Gerekletirilmesi

90

Bu yntemde kuyruun sonu bir gsterici ile ya da indeks ile tutulur. Eleman sona yerletirilir, batan alnarak dizi kaydrlr.
Anahtar Notlar: Baz dizisel veri yaplarnn ban ve sonunu belirtmek iin ngilizce head ve tail szckleri tercih edilmektedir.

Kuyruk veri yapsna ilikin balk dosyas u ekilde olabilir:


#ifndef _QUEUE_H_ #define _QUEUE_H_ #include <stddef.h> /* Sybolic Constants */ #define TRUE 1 #define FALSE 0 /* Typedef Declerations */ typedef int BOOL; typedef int DATATYPE; typedef struct tagQUEUE { size_t size; size_t tail; DATATYPE *pQueue; } QUEUE, *HQUEUE; /* Function Prototypes */ HQUEUE createQueue(size_t size); void closeQueue(HQUEUE hQueue); BOOL putQueue(HQUEUE hQueue, DATATYPE val); BOOL getQueue(HQUEUE hQueue, DATATYPE *pItem); BOOL isEmptyQueue(HQUEUE hQueue); #endif

Kuyruk veri yapsna ait uygulama dosyas u ekilde yazlabilir:


#include #include #include #include <stdio.h> <stdlib.h> <string.h> "queue.h"

91

#define PUBLIC #define PRIVATE static /* Function Definitions */ PUBLIC HQUEUE createQueue(size_t size) { HQUEUE hQueue; if ((hQueue = (HQUEUE)malloc(sizeof(QUEUE))) == NULL) return NULL; if ((hQueue->pQueue = (DATATYPE *)malloc(sizeof(DATATYPE) * size)) == NULL) { free(hQueue); return NULL; } hQueue->size = size; hQueue->tail = 0; return hQueue; }

PUBLIC void closeQueue(HQUEUE hQueue) { free(hQueue->pQueue); free(hQueue); } PUBLIC BOOL putQueue(HQUEUE hQueue, DATATYPE val) { if (hQueue->tail == hQueue->size) return FALSE; hQueue->pQueue[hQueue->tail++] = val; return TRUE; } PUBLIC BOOL getQueue(HQUEUE hQueue, DATATYPE *pItem) { size_t k; if (hQueue->tail == 0) return FALSE; *pItem = *hQueue->pQueue; /* for (k = 0; k < hQueue->tail; k++) hQueue->pQueue[k] = hQueue->pQueue[k + 1];

*/ memmove(hQueue->pQueue, hQueue->pQueue + 1, sizeof(DATATYPE) * (hQueue->tail - 1)); --hQueue->tail;

92

return TRUE; } PUBLIC BOOL isEmptyQueue(HQUEUE hQueue) { return hQueue->tail == 0; }

yle test edilebilir:


#include <stdio.h> #include <stdlib.h> #include "Queue.h" int main(void) { HQUEUE hQueue; int i, val; if ((hQueue = CreateQueue(10)) == NULL) { fprintf(stderr, "Cannot create queue!...\n"); exit(EXIT_FAILURE); } for (i = 0; i < 10; ++i) PutQueue(hQueue, i); while (!IsEmptyQueue(hQueue)) { GetQueue(hQueue, &val); printf("%d\n", val); } CloseQueue(hQueue); return 0; }

15.1.2.2. Dngsel Yntem ile Kuyruk Yapsnn Gerekletirilmesi

Bu yntemde kuyruun ban ve sonunu gsteren head ve tale isimli iki gsterici yada index alnr. Ayrca kuyruktaki eleman says da tutulur. Alma ilemi head gstericisinin gsterdii yerden yaplr ve head gstericisi 1 ilerletilir. Yerletirme ilemi tale gstericisinin gsterdii yere yaplr ve tale gstericisi 1 ilerletilir. Gstericiler dizinin sonuna geldiinde yeniden baa geirilir.

93

Head ve tale ayn yeri gsteriyorsa kuyruk ya tam doludur ya da botur. Kuyruun dolu mu bo mu olduu kuyruk ierisinde bulunan eleman saysna gre belirlenir. Queue.h dosyas u ekilde yazlabilir:
#ifndef _QUEUE_H_ #define _QUEUE_H_ #include <stddef.h> /* Sybolic Constants */ #define TRUE 1 #define FALSE 0 /* Typedef Declerations */ typedef int BOOL; typedef int DATATYPE; typedef struct tagQUEUE { size_t size; size_t head; size_t counter; size_t tail; DATATYPE *pQueue; } QUEUE, *HQUEUE; /* Function Prototypes */ HQUEUE createQueue(size_t size); void closeQueue(HQUEUE hQueue); BOOL putQueue(HQUEUE hQueue, DATATYPE val); BOOL getQueue(HQUEUE hQueue, DATATYPE *pItem); BOOL isEmptyQueue(HQUEUE hQueue); #endif

Queue.c uygulama dosyas u ekilde yazlabilir:


#include #include #include #include <stdio.h> <stdlib.h> <string.h> "queue.h"

#define PUBLIC #define PRIVATE static /* Function Definitions */ PUBLIC HQUEUE createQueue(size_t size) { HQUEUE hQueue;

94

if ((hQueue = (HQUEUE)malloc(sizeof(QUEUE))) == NULL) return NULL; if((hQueue->pQueue = (DATATYPE *)malloc(sizeof(DATATYPE) * size)) == NULL) { free(hQueue); return NULL; } hQueue->size = size; hQueue->counter = hQueue->head = hQueue->tail = 0; return hQueue; } PUBLIC void closeQueue(HQUEUE hQueue) { free(hQueue->pQueue); free(hQueue); } PUBLIC BOOL putQueue(HQUEUE hQueue, DATATYPE val) { if (hQueue->counter == hQueue->size) return FALSE; /* hQueue->tail %= hQueue->size; */ if (hQueue->tail == hQueue->size) hQueue->tail = 0; hQueue->pQueue[hQueue->tail++] = val; ++hQueue->counter++; return TRUE; } PUBLIC BOOL getQueue(HQUEUE hQueue, DATATYPE *pItem) { if (hQueue->counter == 0) return FALSE; /* hQueue->head %= hQueue->size; */ if (hQueue->head == hQueue->size) hQueue->head = 0; *pItem = hQueue->pQueue[hQueue->head++]; hQueue->counter--; return NULL; } PUBLIC BOOL isEmptyQueue(HQUEUE hQueue) { return !hQueue->counter; }

95

15.1.2.3. Bal Liste Yntemi ile Kuyruk Yapsnn Gerekletirilmesi Bal liste tekniinide bir bal liste oluturulur. Bal listenin ilk eleman ve son eleman handle alannda tutulur. Eleman eklerken listenin sonuna eklenir, eleman alnrken listenin bandan eleman alnr.

15.2. Veri Yaplarnn Trden Bamsz Hale Getirilmesi

Veri yaplarnn farkl trler ile alabilmesi iin 2 yntem dnlebilir. Birincisi her tr iin fonksiyonlarn yeniden yazlma yntemi: Bu yntemde fonksiyon isimleri her tr iin deitirilmelidir. phesiz hzl bir yntemdir. Fakat kod tekrar bir dezavantaj oluturmaktadr. kinci yntemde, veri yapsna ilikin fonksiyonlar trden bamsz bir biimde oluturulur: Bu yntemde fonksiyonlar veri yapsnda tutulacak nesnenin trn bilmemektedir. Bu nedenle nesneler hep adres yolu ile aktarlmaldr ve void gstericilerden faydalanlr. phesiz veri yapsnda saklanan elemanlarn bayt uzunluu bilinmelidir. Bu tr trden bamsz uygulamalarda tre baml ilemler genel olarak fonksiyon gstericileri ile fonksiyonlar kullanan kiiye yaptrlr. rnein trden bamsz kuyruk sistemi iin handle alan yle olabilir:
typedef struct tagQUEUE { size_t size; size_t head; size_t count; size_t tail; size_t width void *pQueue; } QUEUE, *HQUEUE;

Fonksiyonlarn prototipleri yle olabilir:


HQUEUE CreateQueue(size_t size, size_t width); void CloseQueue(HQUEUE hQueue); BOOL PutQueue(HQUEUE hQueue, const void *pItem); BOOL GetQueue(HQUEUE hQueue, void *pItem); BOOL IsEmptyQueue(HQUEUE hQueue);

96

GenericQueue.c balk dosyas u ekilde yazlabilir:


#include #include #include #include <stdio.h> <stdlib.h> <string.h> "GenericQueue.h"

#define PUBLIC #define PRIVATE static /* Function Definitions */ PUBLIC HQUEUE CreateQueue(size_t size, size_t width) { HQUEUE hQueue; if ((hQueue = (HQUEUE)malloc(sizeof(QUEUE))) == NULL) return NULL; if ((hQueue->pQueue = malloc(width * size)) == NULL) { free(hQueue); return NULL; } hQueue->size = size; hQueue->width = width; hQueue->count = hQueue->head = hQueue->tail = 0; return hQueue; } PUBLIC void CloseQueue(HQUEUE hQueue) { free(hQueue->pQueue); free(hQueue); } PUBLIC BOOL PutQueue(HQUEUE hQueue, const void *pItem) { if (hQueue->count == hQueue->size) return FALSE; if (hQueue->tail == hQueue->size) hQueue->tail = 0; memcpy((char *)hQueue->pQueue + hQueue->tail * hQueue->width, pItem, hQueue->width); ++hQueue->tail; ++hQueue->count; return TRUE; } PUBLIC BOOL GetQueue(HQUEUE hQueue, void *pItem) {

97

if (hQueue->count == 0) return FALSE; if (hQueue->head == hQueue->size) hQueue->head = 0; /* hQueue->head = hQueue->head % hQueue->size; */ memcpy(pItem, (char *)hQueue->pQueue + hQueue->head * hQueue->width, hQueue->width); hQueue->head++; --hQueue->count; return TRUE; } PUBLIC BOOL IsEmptyQueue(HQUEUE hQueue) { return hQueue->count == 0; }

Test kodu u ekilde yazlabilir:


#include <stdio.h> #include <stdlib.h> #include "GenericQueue.h" int main(void) { HQUEUE hQueue1, hQueue2; if ((hQueue1 = CreateQueue(10, sizeof(int))) == NULL) { fprintf(stderr, "Cannot create queue!...\n"); exit(EXIT_FAILURE); } if ((hQueue2 = CreateQueue(10, sizeof(double))) == NULL) { fprintf(stderr, "Cannot create queue!...\n"); exit(EXIT_FAILURE); } { int i, val; for (i = 0; i < 10; ++i) PutQueue(hQueue1, &i); while (!IsEmptyQueue(hQueue1)) { GetQueue(hQueue1, &val); printf("%d\n", val); } }

98

{ double i; double val; for (i = 0.1; i < 10.1; ++i) PutQueue(hQueue2, &i); while (!IsEmptyQueue(hQueue2)) { GetQueue(hQueue2, &val); printf("%f\n", val); } } CloseQueue(hQueue1); CloseQueue(hQueue2); return 0; } Anahtar Notlar: C++ n template tabanl veri yaplar aslnda her tr iin ayr fonksiyon yazma sistemine uymaktadr. C# ve Java da herey object snfndan tretildii iin veri yaplarnn genelletirilmesi bu snf eliinde gerekletirilebilmektedir. Fakat ayrca generic konusunun bu dillere eklenmesiyle tpk C++ da olduu gibi template tabanl veri yaplar da eklenmitir.

15.3. Bal Listeler

Bir dizide tm elemanlar ardl olarak bulunmaktadr. Eer dizinin elemanlar ardl olmaz ise biz elemanlarn yerlerini tutmak zorunda kalrz. Elemanlarn yerlerini ayr bir gsterici dizisinde tutmak iyi bir zm deildir. O halde ardl olmayan bir dizi oluturacaksak akla gelen en etkin yntem dizinin her elemannn sonraki elemann adresini tutmasdr. Bylece ilk elemann adresi de bir yerde tutulursa ardl olmayan bir dizi elde edilmi olur. Bu tr veri yaplarna bal listeler (linked list) denilmektedir.

15.3.1. Bal Listelerin Kullanm Alanlar

1. Blnme (Fragmentation) nedeni ile ardk bellek skntsnn ekildii durumlarda dinamik bytlen diziler iin, bal liste daha etkin bir yntemdir. nk blnm yerlerde bal listenin elemanlar oluturulabilir. rnein elimizde 100kB lk blnm bir bellek olsun. Ardk en geni alann 10K civarnda olduunu 99

dnelim. Fakat toplam bo bellek 50K civarnda olsun. Biz ancak 10K uzunluunda bir dizi oluturabiliriz. Fakat bal listeler sayesinde daha byk uzunluklarda diziler oluturabiliriz. zellikle bir bellek blgesinin (tipik olarak heap) birden fazla dinamik bytlen, diziler tarafndan paylald durumlarda bal listeler daha etkin bir zm oluturur. 2. Araya eleman ekleme ve silme gibi ilemlerde normal dizilerde eleman kaydrmas ve sktrlmas yaplmak zorundadr. Hlbuki bal listelerde eleman ekleme ve silme sabit karmaklkta bir ilem olarak yaplabilir. Hlbuki bu dizilerde dorusal karmaklktadr. 3. Bal listeler baz durumlarda zorunlu olarak kullanlmaktadr. rnein kullanlan bellein yapsndan kaynaklanan bir ardklk sz konusu olmayabilir. Bu tr uygulamalarda mecburi olarak bal liste kullanrz. Uzunluunu bilmediimiz diziler iin genellikle malloc-realloc teknii blnme konusunda sorunlara yol aar. Bu tr durumlarda bal listeler ilk akla gelmesi gereken yntemdir.

15.3.2. Bal Listeler ile Dizilerin Karlatrlmas

1. Eleman eriimi dizilerde ok hzl yani sabit karmaklktadr. Hlbuki bal listelerde dorusal karmaklktadr. Yani bu konuda diziler daha avantajldr. 2. Ayn blgenin dinamik olarak bytlen birden fazla dizi tarafndan kullanlaca durumda blnme problemi nedeni ile bal listeler daha etkindir. 3. Araya ekleme ve silme ilemlerinin youn olduu durumlarda bal listeler tercih edilmelidir.

15.3.3. Tek Bal ve ift Bal Listeler

Tek bal listelerde her eleman bir sonraki eleman gsterir. Fakat ift bal listelerde (doubly linked lists) her eleman hem bir nceki hem de bir sonraki eleman gstermektedir. Bylece ift bal listelerde geriye doru gidi de mmkndr. Uygulamada youn olarak ift bal listeler

100

kullanlmaktadr. ift bal listenin en nemli avantaj bir elemann adresi bilindiinde onun silinebilmesidir. Hlbuki tek bal listede ancak nceki elemann adresini bilirsek sonraki eleman silebiliriz.

15.3.4. Bal Listelerin Gerekletirilmesi

Bal listelerdeki her bir elemana dm (node) denir ve bir dm tipik olarak bir yap ile temsil edilir. rnein tek bal liste iin dm yaps yle olabilir:
struct NODE { DATATYPE val; struct NODE *pNext; };

ift bal liste iinde yle olabilir:


struct NODE { DATATYPE val; struct NODE *pNext; struct NODE *pPrev; };

Bal listenin ilk eleman bir gsterici ile tutulur. Genellikle sona ekleme ilemleri iin de son elemann tutulmasnda fayda vardr. Ayrca son elemann pNext gstericisi NULL yaplmas etkin bir yntemdir.

pNext

10

18

23

42 NU LL

Anahtar Notlar: C de henz bir yap bildirimi yaplmadan yap trnden nesneler tanmlanamaz fakat gstericiler tanmlanabilir. Bu tr bildirimlere eksik bildirimler (incomplete declarations) denilmektedir. rnein: typedef struct tagNODE *PNODE;

101

struct tagNODE { DATATYPE val; PNODE pNext; }NODE; lemi geerlidir. Bildirim tamamlana kadar bu gsterici ile elemana eriim yaplamaz. Bylece birbirlerini gsteren elemanlara sahip yaplar oluturulabilir. rnein: struct A { struct B *pB; }; struct B { struct A *pB; }; Tabi henz bildirimi yaplmam yap trnden typedef de yaplabilir. rnein: typedef struct tagNODE *PNODE;

15.3.5. Tek Bal Listelerin Handle Teknii ile Gerekletirilmesi

Bal liste list.h ve list.c biiminde iki dosya halinde organize edilebilir. Handle alan aadaki gibi olabilir.
typedef struct tagNODE { DATATYPE val; struct tagNODE *pNext; } NODE; typedef struct tagLIST { NODE *pHead; NODE *pTail; size_t count; } LIST, *HLIST;

rnein CreateList fonksiyonu aadaki gibi yazlr:


HLIST CreateList(void) { HLIST hList; if ((hList = (HLIST) malloc(sizeof(LIST))) == NULL) return NULL; hList->pHead = hList->pTail = NULL; hList->count = 0; return hList;

102

Bal listenin bana eleman eklemeden nce aadaki gibi bir kontrol yaparz:
if (hList->pTail == NULL) hList->pTail = pNewNode;

Burada pNewNode yeni tahsis edilmi elemandr. Eleman ekleyen fonksiyonun yeni eklenen dmn adresine geri dnmesi faydal sonulara yol aar. Bu durumda baa eleman ekleme ilemi yle yaplabilir.
NODE *AddItemHead(HLIST hList, DATATYPE val) { NODE *pNewNode; if ((pNewNode = (NODE *)malloc(sizeof(NODE))) == NULL) return NULL; pNewNode->val = val; pNewNode->pNext = hList->pHead; hList->pHead = pNewNode; if (hList->pTail == NULL) hList->pTail = pNewNode; ++hList->count; return pNewNode; }

15.3.6. Bal Listenin Dolalmas

Dolam ilemi tek bir dng ile yaplabilir:


for (pNode = hList->pHead; pNode != NULL; pNode = pNode->pNext)

Dolam fonksiyonunun her bulduu dmdeki eleman adresi ile bir fonksiyonu armas iyi bir tasarmdr. arlan geri dn deeri dolam sonlandrmak iin kullanlabilir.
BOOL WalkList(HLIST hList, BOOL (*Proc)(DATATYPE *)) { NODE *pNode;

103

for (pNode = hList->pHead; pNode != NULL; pNode = pNode->pNext) if (!Proc(&pNode->val)) return FALSE; return TRUE; }

Anahtar Notlar: C de parametre deikeni sz konusu olduunda gstericiler sanki diziymi gibi dizi deklaratr ile belirtilebilir. rnein: void func(int p[25]); void func(int *p); Keli parantez ierisine sabit ifadesi de yerletirilebilir. Yerletirilen saynnda hibir nemi yoktur. Yukardaki ikisi edeerdir. Fonksiyon gstericileri iinde alternatif gsterim vardr. rnein aadaki ikisi edeerdir: void Func(void Proc(int ,int)); void Func(void *Proc(int, int)); Prototiplerde isim yazmak zorunlu olmadna gre aadaki prototip bildirimleri de geerlidir. void Foo(void (int, int)); void Bar(int []);

15.3.7. Bal Listenin Sonuna Eleman Eklenmesi

Bu ilem iin aadaki gibi bir kod paras yeterlidir:


NODE *AddItemTail(HLIST hList, DATATYPE val) { NODE *pNewNode; if ((pNewNode = (NODE *) malloc(sizeof(NODE))) == NULL) return NULL; pNewNode->val = val; pNewNode->pNext = NULL; if (hList->pTail != NULL) hList->pTail->pNext = pNewNode; else hList->pHead = pNewNode; hList->pTail = pNewNode; ++hList->count;

104

return pNewNode; }

15.3.8. Bal Listeye Eleman Insert Edilmesi

Araya eleman ekleme ilemi eer ekleme yaplacak yere ilikin dm adresi biliniyorsa sabit zamanl bir ilemdir. Eer bir indekse gre insert ilemi yaplacaksa dorusal zamanldr. Belirli bir indekse gre insert yapan fonksiyon yle olabilir:
NODE *InsertItemIndex(HLIST hList, size_t index, DATATYPE val) { NODE *pNewNode; size_t i; NODE *pNode; if (index > hList->count) return NULL; if ((pNewNode = (NODE *) malloc(sizeof(NODE))) == NULL) return NULL; pNewNode->val = val; if (index == return if (index == return 0) AddItemHead(hList, val); hList->count) AddItemTail(hList, val);

pNode = hList->pHead; for (i = 0; i < index - 1; ++i) pNode = pNode->pNext; pNewNode->pNext = pNode->pNext; pNode->pNext = pNewNode; ++hList->count; return pNewNode; }

Tek bal listelerde biz bir dmn adresini biliyorsak ancak onun nne insert ilemi yapabiliriz.

NODE *InsertItemNode(HLIST hList, NODE *pNode, DATATYPE val)

105

{ NODE *pNewNode; if ((pNewNode = (NODE *) malloc(sizeof(NODE))) == NULL) return NULL; pNewNode->val = val; pNewNode->pNext = pNode->pNext; pNode->pNext = pNewNode; if (hList->pTail == pNode) hList->pTail = pNewNode; ++hList->count; }

15.3.9. Listeden Eleman Silinmesi

Eleman silme ilemi yine indekse gre yada dm adresine gre yaplabilir. Malesef tek bal listelerde dm adresi bilinen bir eleman silemeyiz. Ancak onun nndeki eleman silebiliriz. indekse gre silme yapan bir fonksiyon yle yazlabilir:
BOOL DeleteItemIndex(HLIST hList, size_t index) { NODE *pNode, *pDelNode; size_t i; if (index >= hList->count) return FALSE; --hList->count; if (index == 0) { pDelNode = hList->pHead; hList->pHead = pDelNode->pNext; free(pDelNode); if (hList->pHead == NULL) hList->pTail = NULL; return TRUE; } pNode = hList->pHead; for (i = 0; i < index - 1; ++i) pNode = pNode->pNext; pDelNode = pNode->pNext; pNode->pNext = pDelNode->pNext; if (pDelNode == hList->pTail)

106

hList->pTail = pNode; free(pDelNode); return TRUE; }

Dm adresine gre silme ilemi de yle yaplabilir:


BOOL DeleteItemNode(HLIST hList, NODE *pNode) { NODE *pDelNode; pDelNode = pNode->pNext; if (pDelNode == NULL) return FALSE; pNode->pNext = pDelNode->pNext; free(pDelNode); --hList->count; return TRUE; }

Bal listede tm dmleri silen bir fonksiyona gerek duyulur. Tm dmleri silmek iin hep sonraki dm saklamak gerekir. Fonksiyon yle yazlabilir:
void ClearList(HLIST hList) { NODE *pNode, *pTempNode; pNode = hList->pHead; while (pNode != NULL) { pTempNode = pNode->pNext; free(pNode); pNode = pTempNode; } hList->pHead = hList->pTail = NULL; hList->count = 0; }

Nihayet listedeki eleman saysn veren bir fonksiyon da yazlmaldr.


size_t GetListCount(HLIST hList)

107

{ return hList->count; }

15.3.10. Bal Listelerin Genelletirilmesi

Yukardaki rneklerde biz birden fazla bal liste oluturabiliriz fakat hepsi DATATYPE trnden olmak zorundadr. Halbuki ayn anda farkl trlerden bal listeler oluturmak isteyebiliriz. Bunun iin yine void gstericiler kullanlarak genelletirme yaplabilir ya da makro teknii kullanlabilir. Makro teknii LINUX, BSD, CSD gibi sistemlerde de birbirine benzer biimlerde kullanlmaktadr. Bu tr rneklerde dm olarak kullanlan yapnn baz elemanlar bilinmektedir. Fakat baz elemanlar bilinmemekte yalnzca onlarn uzunluu bilinmektedir. Bilinen elemanlar yapnn bana toplayp bilinmeyen elemanlarn yeri belirlenebilir. C90 da sfr uzunluklu bir dizi olamaz. Fakat C99 da bu tr durumlara olanak salamak iin yapnn son eleman uzunluu belirtilmeyen (yani 0 uzunluklu) bir pNext dizi olabilir. Bu durumda NODE yaps yle olabilir.

pNext

pNext->data

typedef struct tagNODE { struct tagNODE *pNext; unsigned char data[1]; }NODE;

imdi bal listede tutacamz verinin uzunluunun width kadar olduunu dnelim ve bu verinin adresi pData ile temsil edilsin. Yeni bir dm tahsis edip bu veriyi o dme yle yerletirebiliriz:
NODE *pNode; pNode = (NODE *)malloc(sizeof(NODE *) + width); memcpy(pNode->data, pNode, width);

Trden bamsz bal listenin handle alan yle olabilir: 108

typedef struct tagNODE { struct tagNODE *pNext; unsigned char data[1]; } NODE; typedef struct tagLIST { NODE *pHead; NODE *pTail; size_t width; size_t count; } LIST, *HLIST;

Bal listeyi yaratan fonksiyon yle yazlabilir:


HLIST CreateList(size_t width) { HLIST hList; if ((hList = (HLIST) malloc(sizeof(LIST))) == NULL) return NULL; hList->pHead = hList->pTail = NULL; hList->width = width; hList->count = 0; return hList; }

Bal listeye eleman ekleyen fonksiyon yle yazlabilir:


NODE *AddItemHead(HLIST hList, const void *pData) { NODE *pNewNode; if ((pNewNode = (NODE *) malloc(sizeof(NODE *) + hList->width)) == NULL) return NULL; memcpy(pNewNode->data, pData, hList->width); pNewNode->pNext = hList->pHead; hList->pHead = pNewNode; if (hList->pTail == NULL) hList->pTail = pNewNode; ++hList->count; return pNewNode; }

Diziyi dolaan fonksiyon yle yazlabilir:


BOOL WalkList(HLIST hList, BOOL (*Proc)(void *)) { NODE *pNode; for (pNode = hList->pHead; pNode != NULL; pNode = pNode->pNext) if (!Proc(pNode->data)) return FALSE;

109

return TRUE; }

15.3.11. Genel Bal Liste Oluturulmasnda Dier Bir Yntem

Genel bal liste iin dier bir yntem de bir dm yaps oluturup balanacak elemanlar soyutlayarak bu dmleri birbirine balamaktr. LINUX ve BSD iletim sistemlerinde bulunan bal listeler bu biimde oluturulmutur. Bu yntem de handle sistemi kullanlmaz. Fakat ilk dm tutan nesne bir handle alan gibi kullanlr. Tek bal liste iin ncelikle aadaki gibi bir yap oluturulabilir:
typedef struct tagDLIST_HEADER { struct tagLIST_NODE *pHead, *pTail; } DLIST_HEADER;

TagDLISTNODE yaps yledir:


typdef struct tagDLIST_NODE { struct tagDLIST_NODE *pNext, *pPrev; } DLIST_NODE;

Aadaki iki makro tanmlamay kolaylatrabilir.


#define INIT_DLIST() #define DEFINE_DLIST(name) {NULL, NULL} DLIST_HEADER name = INIT_DLIST()

Listenin bana yle eleman ekleyebiliriz:


void AddNodeHeadDL (DLIST_HEADER *pHeader, DLIST_NODE *pNewNode) { if (pHeader->pHead != NULL) { pHeader->pHead->pPrev = pNewNode; pNewNode->pNext = pHeader->pHead; } else { pNewNode->pNext = NULL; pHeader->pTail = pNewNode; } pNewNode->pPrev = NULL; pHeader->pHead = pNewNode; }

110

Sona ekleme ilemi yle yaplabilir:


void AddNodeTailDL(DLIST_HEADER *pHeader, DLIST_NODE *pNewNode) { if (pHeader->pTail != NULL) { pHeader->pTail->pNext = pNewNode; pNewNode->pPrev = pHeader->pTail; } else { /* list contains no item */ pNewNode->pPrev = NULL; pHeader->pHead = pNewNode; } pNewNode->pNext = NULL; pHeader->pTail = pNewNode; }

Listede tutulan veri yapsnn bana erimek iin aadaki gibi bir makro yazlabilir:

#define EXTRACT_OBJECT(ptr, type, member) \ ((type *) ((unsigned char *) (ptr) - (unsigned long) (&((type *) 0)>member)))

Listeyi dolamak iin ise aadaki gibi bir makro kullanlabilir:


#define WALK_LIST(head, pos) \ for (pos = (head)->pHead; (pos) != NULL; (pos) = (pos)->pNext)

pHead pTail

pPrev pNext

pPrev pNext NULL

Yukardaki fonksiyonlar ve makrolar grne gre yalnzca DLIST_NODE nesnelerini birbirine balamaktadr. Aslnda listede tutulan gerek nesnelerin birer DLIST_NODE eleman olmaldr. Bu durumda bu fonksiyonlar ve makrolar gerek nesnelerin dmlerini birbirine balar

111

rnein PERSON yaplarndan bir bal liste oluturalm. imdi bal liste iin bir header tanmlayalm.
typedef struct tagPERSON { char name[32]; int no; DLIST_NODE node; } PERSON;

Burada per PERSON trnden bir nesnenin adresidir. Dolam ilemi yle yaplabilir.
WALK_LIST(&people, pNode) { per = EXTRACT_OBJECT(pNode, PERSON, node); printf("%s %d\n", per->name, per->no); }

15.4. Stack Sistemleri

Stack sistemleri LIFO prensibi ile alan kuyruk sistemidir. Gerek doada gerekse tipik bilgisayar programlarnda stack sistemleri ile karlalmaktadr. Stack e geleneksel olarak eleman ekleme ilemine push ilemi, stack ten eleman alma ilemine pop ilemi denilmektedir.

15.4.1. Stack Sistemlerinin Kullanm Alanlar

Baz sistemler stack almasna benzerler. Bu sistemler ile doada da sk karlalr. rnein tabaklarn st ste konulup alnmas, asansre son giren kiinin ilk olarak kmas stack sistemine uygundur. Baz iskambil oyunlarnda oyuncunun en stteki kad alabilmesi byle bir sistem ile salanabilir. Parsing ilemlerinde stack sistemleri youn olarak kullanlr. rnein Reverse Polish Notation olarak bilinen postfix hesaplama ynteminde stack kullanlmaktadr. Bu

112

yntemde infix operatrler bir algoritma ile postfix biime dntrlr sonra stack kullanlarak ilemler yaplr. rnein: 3+5*4 Infix biim 1+2*3+4 354*+ postfix biim 123*+4+

ekline dntrlr. Normal yukardan aaya pars ileminde de stack sistemi kullanlmaktadr. 3 + 2 * (5 + 9) Burada tipik yntem nce daha yksek ncelikli operatre bakma ve nceki operandlar stack te tutmaktr. Programc 3 grd zaman onu stack e atar. Sonra + ve 2 yi grnce hemen ilemi yapmaz. Daha yksek ncelikli bir operatr grd iin onu da stack e atarak devam eder. Sonra stack ten eke eke ilemleri yapar. 13 * 2 + 3 26 + 3 29

Editrlerdeki undo mekanizmas tipik bir stack sistemidir. Her ctrl+z tuuna basldnda en son yaplan ilem geri alnmaktadr.

15.4.2. Stack Sisteminin Gerekletirilmesi Stack sistemi klasik olarak yle gerekletirilir. Stack iin bir dizi alnr. smine stack pointer denilen bir gsterici bu dizinin sonuna ekilir.

113

SP 30 SP 20 10

Push ilemi srasnda sp bir azaltlarak bilgi sp nin gsterdii yere yazlr. Pop ilemi srasnda sp nin gsterdii yerdeki bilgi alnr ve sp bir artrlr. ok fazla push yaplrsa stack yukardan taar (stack over flow), ok fazla pop yaplrsa stack aadan taar (stack under flow). Stack sistemi iin handle alan yle olabilir:
typedef int DATATYPE; typedef struct tagSTACK { DATATYPE *pStack; DATATYPE *SP; size_t size; } STACK, *HSTACK;

Handle alann oluturan fonksiyon yle yazlabilir:


HSTACK CreateStack(size_t size) { HSTACK hStack; if ((hStack = (HSTACK) malloc(sizeof(STACK))) == NULL) return NULL; if ((hStack->pStack = (DATATYPE *) malloc(sizeof(DATATYPE) * size)) == NULL) { free(hStack); return NULL; } hStack->SP = hStack->pStack + size; hStack->size = size; return hStack;

114

Push ilemi yle yaplabilir:


BOOL Push(HSTACK hStack, DATATYPE val) { if (hStack->SP == hStack->pStack) return FALSE; *--hStack->SP = val; return TRUE; }

Pop ilemi iin bir kontrol yapmayabiliriz:


DATATYPE Pop(HSTACK hStack) { return *hStack->SP++; }

Handle alann kapatan fonksiyon da yle yazlabilir:


void CloseStack(HSTACK hStack) { free(hStack->pStack); free(hStack); }

Stack in bo yada dolu olduunu anlamak iin yle bir fonksiyon yazabiliriz:

BOOL isEmpty(HSTACK hStack) { return hStack->SP == hStack->pStack + hStack->size; }

yle bir rnek yaplabilir:

int main(void) { HSTACK hStack; char *name = "kaan aslan"; if ((hStack = CreateStack(50)) == NULL) { fprintf(stderr, "Cannot create stack!..\n"); exit(EXIT_FAILURE); }

115

while (*name != '\0') Push(hStack, *name++); while (!IsEmpty(hStack)) putchar(Pop(hStack)); putchar('\n'); CloseStack(hStack); return 0; }

15.5. Hash Tablolar

Hash tablolar arama amal kullanlan veri yaplardr. Bir takm deerler bir anahtarla tabloya yerletirilir. Sonra anahtar deer verilerek bilgi geri alnr. Eer tablodaki eleman says nceden kestirilebiliyorsa ve tablo yeterli uzunlukta oluturulursa hashing yntemi arama iin en etkin yntemlerden biridir. kili aa gibi yntemlere gre stndr. Hash tablosu ynteminin altnda yatan fikir anahtar deerden bir dizi indeksi elde edip dizinin o indeksteki elemanndan bilgiyi ekmektir. rnein kiilerin bilgileri numaraya gre yerletirilip aranacak olsun. Bir yap dizisi oluturulsa kiinin numaras o diziye indeks yaplp kiinin bilgileri dizinin o elemanna yerletirilse bundan hzl bir yntem olamaz. rnein numaras 1349 olan kiinin bilgileri dizinin 1349. elemanna yerletirilir ve geri alnrken de numara 1349 olarak girildiinde dizinin o elemanndan alnr. Fakat yukardaki yntemin eitli problemleri vardr: Numara ok geni bir aralkta ve az sayda kii olabilir. Bu durum bou bouna ok byk bir dizinin almasna neden olur. Numara ok geni bir aralktadr fakat bu kadar dizi oluturmaya bellek yetmemektedir. Yukardaki yntem anlaml olarak dzeltilirse faydal bir sisteme dntrlebilir. Bu yntemde yerletirme ilemi iin oluan diziye hash tablosu denir. Anahtar deerden dizi indeksi elde etmeye yarayan fonksiyona hash fonksiyonu denilir. rnein hash tablosu 1000 elemanl olsun. Anahtar deer 10 dijitlik saylar olsun. te hash fonksiyonu bu 10 dijitlik saydan sfr ile 999 arasnda bir indeks elde eden bir fonksiyondur. Anahtar deer kiinin ismi gibi bir yaz da olabilir. O halde hash fonksiyonu yazy indekse dntren bir fonksiyon olacaktr.

116

Biz anahtar deeri hash fonksiyonuna sokup tablonun ilgili elemanna yerletirsek bu kez bir akma (collision) problemi ortaya kacaktr. rnein numaray indekse dntren hash fonksiyonu 1000 e blmnden elde edilen kalan fonksiyonu olsun. Bu durumda rnein sonu 847 ile biten tm anahtar deerler ayn dizi indeksini elde ederler. te akma olutuunda izlenecek stratejiye gre hashing yntemi eitli alt yntemlere ayrlmaktadr. Bunlardan en fazla kullanlan ayr zincir oluturma (seperate chaining) yntemidir. Ayr zincir oluturma ynteminde hash tablosu bir bal zincir dizisi biimindedir. Yani rnein hash tablosu bal listelerin head gstericilerinden olumu bir dizi olabilir. Yerletirilecek deer hash fonksiyonuna sokulur, dizi indeksi elde edilir, bilgi o bal listenin bana hemen eklenir. rnein, 8176781 numaral kiinin bilgileri 781. bal listeye eklenir. Bu bal listede sadece bu kiinin bilgileri deil sonu 781 ile biten tm kiilerin bilgileri bulunur. rnein 17486674 numaral kiiyi arayacak olalm. Hash fonksiyonu ile 674 deeri elde edilecek ve artk 674 nolu bal listede dorusal arama yaplacaktr. Knuth a gre bal listedeki ortalama eleman says 10 u gemedikten sonra bu yntem ok iyi bir yntemdir. Bu durumda rnein 10000 elemann yerletirilecei tahmin edilen bir tablonun 1000 lik almas gerekir. Ortalama karlatrma says 5 olacaktr. Ayr zincir oluturma ynteminde eer sisteme ok fazla eleman eklenmek istenirse sistem dorusal arama yntemine benzemeye balar. Sisteme ok az eleman eklenirse sistem rastgele eriimli bir sistem gibi olur. Bu sistemde ortalama olarak sisteme ka eleman gelecei konusunda bir ngrde bulunulmaldr. Hash tablosu daha sonra bytlebilirse de bunun doal olarak bir maliyeti olacaktr.

15.5.1. Sral Yoklama Yntemi (Lineer Probiny)

Bu yntemde hash fonksiyonlar ile elde edilen indekse deer yerletirilmeye allr. Hash tablosu bir yap dizisi biimindedir. lgili indeks dolu ise ilk bo indekse yerletirme yaplr. rnein : Tablo 100 eleman uzunluunda olsun. Yerletirilecek kii 18898 numarasna sahip olsun. Hash fonksiyonu olarak blmden elde edilen kalan fonksiyonunun kullanldn dnelim. Tablonun 68 nolu eleman, dolu ise 69, dolu ise 70 elemanlarna baklr. lk bo elemann 79

117

olduunu dnelim. Deer 79 a yerletirilir. Sralamal yoklama ynteminin en nemli dezavantaj arama srasnda baarsz aramalarda (un-secsesful search) tablonun sonuna kadar gitme zorunluluudur. Geri bunu nlemek iin eitli yntemler kullanlmaktadr. Fakat bu yntemlerin de maliyeti vardr. Ayrca bu yntemde tablo uzunluundan daha fazla eleman tabloya yerletiremeyiz. Tabloya girecek eleman says kestirilebiyorsa ve fazla deilse byk bir tablo amak etkin bir aramaya olanak salamaktadr.

15.5.2. Hash Fonksiyonlar

Bir hash fonksiyonunun iyi olabilmesi iin deerleri tabloya iyi bir biimde yaydrmas gerekir. rnein blmnden elde edilen kalan fonksiyonu ok kt bir hash fonksiyonudur. Gelen deerler yanl bile olsa iyi bir hash fonksiyonunun onu tabloya iyi bir biimde datmas gerekir. rnein ift saynn ift sayya blmnden elde edilen kalan hep ifttir. Analizler tablo uzunluunun asal say olmas durumunda hash fonksiyonlarnn performansnn arttn gstermitir. Bu nedenle tablo uzunluklar hep asal say olarak alnmaktadr (rnein 100 deil 101, 1000 deil 1001 gibi). yi bir hash fonksiyonunun kolay hesaplanabilir olmas gerekir. Yazy sayya dntren, sayy sayya dntren pek ok kaliteli hash fonksiyonu nerilmektedir. 15.5.3. Hash Tablolarnn Kullanm Alanlar

Hash tablolar zellikle bellek zerinde hzl aramann istendii her durumda kullanlabilir. Fakat bu yntemde tabloya yerletirilecek eleman saysnn nceden ngrlebilmesi nemli bir faktrdr. rnein LINUX iletim sisteminde toplam 32767 ilem ayn anda alabilmektedir. Baz fonksiyonlar proses id denilen bir sayy alp proses tablosuna erimektedir. Proses id verildiinde proses tablosunun adresini elde etmek iin tipik olarak bir hash tablosu kullanlmaktadr. Ya da rnein LINUX taki buffer cache mekanizmasnda bir disk blounun cash te olup olmadn anlamak iin hash tablolar kullanlmaktadr. Cache te o anda 100 lerce disk blou bulunuyor olabilir. Bir blok okumas yaplmak istendiinde bloun cash te olup olmadna baklacaktr. te cache teki bloklarn tek tek incelenmesi yerine bir hash tablosu kullanlmaktadr.

118

15.5.4. Hash Tablolarnn Gerekletirilmesi

Hash tablolar ayr zincir oluturma yntemi ile kolay bir biimde gerekletirilebilir. Bal listelerin ift bal olmas dme gre silme ilemlerini kolaylatrmaktadr. Burada tek bal listeli sistem uygulanacaktr. Hash tablosu iin handle alan yle olabilir:
typedef struct tagNODE { DATATYPE val; struct tagNODE *pNext; } NODE; typedef struct tagHASHT { size_t tableSize; NODE **pHeads; size_t count; } HASHT, *HHASHT;

Bu tablo yle oluturulabilir:


HHASHT CreateHash(size_t tableSize) { HHASHT hHash; size_t i; if ((hHash = (HHASHT) malloc(sizeof(HASHT))) == NULL) return NULL; if ((hHash->pHeads = (NODE **) malloc(sizeof(NODE *) * tableSize)) == NULL) { free(hHash); return NULL; } for (i = 0; i < tableSize; ++i) hHash->pHeads[i] = NULL; hHash->tableSize = tableSize; hHash->count = 0; return hHash; }

En basit bir hash fonksiyonunu yle oluturalm.


size_t HashFunc(HHASHT hHash, const char *name) { size_t count = 0;

119

while (*name != '\0') { count += *name; ++name; } return count % hHash->tableSize; }

Hash tablosuna eleman ekleme ilemi yle yaplabilir:


BOOL AddHash(HHASHT hHash, const DATATYPE *pVal) { NODE *pNode; size_t index; if ((pNode = (NODE *) malloc(sizeof(NODE))) == NULL) return FALSE; pNode->val = *pVal; index = HashFunc(hHash, pVal->name); pNode->pNext = hHash->pHeads[index]; hHash->pHeads[index] = pNode; ++hHash->count; return TRUE; }

Arama yapan fonksiyon yle olabilir:


DATATYPE *FindHash(HHASHT hHash, const char *name) { NODE *pNode; size_t index; index = HashFunc(hHash, name); for (pNode = hHash->pHeads[index]; pNode != NULL; pNode = pNode->pNext) if (!strcmp(pNode->val.name, name)) return &pNode->val; return NULL; }

Hash tablosu yle kapatlabilir:

void CloseHash(HHASHT hHash) {

120

size_t i; NODE *pNode, *pTemp; for (i = 0; i < hHash->tableSize; ++i) { pNode = hHash->pHeads[i]; while (pNode != NULL) { pTemp = pNode->pNext; free(pNode); pNode = pTemp; } } free(hHash->pHeads); free(hHash); }

15.6. Arama lemlerinin Temelleri

Arama algoritmalar algoritmalar ve veri yaplar konusunun en nemli konularndan birisidir. Yerletirilen bir bilginin daha sonra geri alnmas pek ok uygulamada gerekmektedir. Arama ilemi iin bir anahtaar deer kullanlr. lem sonucunda o anahtara ilikin bilgiler elde edilir. Arama ilemi baarl (successful) ya da baarsz (unsuccessful) olabilir. Baz sistemlerde biz kesinlikle bilginin bulunduunu biliriz ve aramann baarsz olma olasl yoktur. Arama konusundaki karmaklk iin baarl aramalardaki arama karmakl, baarl aramalardaki en kt olaslktaki karmakln, baarszlk durumundaki karmakln dikkate alnmas gerekir. rnein sral yoklama ynteminde baarsz aramalarda tm hash tablosunu gzden geirmek gerekebilir. ok fazla baarsz aramann yapld durumda bu yntem pheli duruma dmektedir. Bir sistem iin uygun veri yaps ve algoritmann belirlenmesi iin o sistemin genel niteliklerinin analiz edilmesi gerekmektedir. En basit arama yntemi sral arama (sequential search) yntemidir. Bu yntemde elemanlar tek tek gzden geirilir. Ortalama arama baar karmakl, O(n) = n + 1, en kt olaslkta karmaklk O(n) = n, baarsz arama karmakl O(n) = n dir. Sral arama iin tipik algoritma yledir:
int a[SIZE]; for (i = 0; i < SIZE; ++i) if (a[i] == key) { /**********/

121

Knuth bu yntemin daha etkin olabileceini sylemitir:


int a[SIZE + 1]; a[SIZE] = key; for (i = 0;; ++i) if (a[i] == key) break; if (i == SIZE) { /***/ } else { /******/ }

En iyi arama yntemi ne olabilir. Sral arama en kt yntemdir. phesiz en iyi arama ytemi sabit karmaklkta bir yntem olabilir. Yani rastgele eriimli bir yntem. Eer hibir akma sz konusu deilse ve ok fazla elemanda yoksa dz bir hash tablosu ideal yntem olabilirdi. Fakat bu yntemde bile eer anahtar deer bir yaz ise yaznn indekse dntrlmesi gerekmektedir. Yani ek bir takm ilemler sz konusudur. Eer aranacak elemanlar ok az sayda ise en kt sanlan sral arama yntemi en iyi yntem olabilir. Eer deerler zaten sral bir biimde bulunuyorsa ikili arama (binary search) yntemi ok etkin bir yntemdir. Baarl en kt durum yada baarsz aramalardaki karmaklk durumu O(n) = log2n durumudur. rnein 1 milyon kayt iin yaklak olarak 20 karlatrma yaplr. Peki ya dizilim sral deilse? nce sraya dizip sonra ikili arama yapmak ok pahalya mal olur. Tabi eer sisteme yeni bir eleman eklenmeyecekse bir kere sort yapp hep ikili arama uygulayabiliriz. Deerler sral ise ikili aramadan daha iyi bir yntem olabilir mi? Eer deerlerin dalm zerinde bir bilgi sahibi isek aralk daraltma ilemini ona gre yapabiliriz. rnein saylar kkten bye dizilmi olabilir fakat herbiri bir ncekinden 3 kat daha byk olabilir. Bu durumda ikili aramada ki gibi ubuu ortaya ekmektense te ikilik bir noktaya ekmek daha etkili olabilir. Bu ynteme stel arama (exponential search) denilmektedir. hpesiz bu yntem iin dalm hakknda bilgi sahibi olmak gerekir. Eer bilinmiyorsa bu yntem yarar yerine zarar getirir. Algoritmik arama yntemlerinde daha bilgi yerletirilirken bir takm notlar alnmaktadr. Sonra o notlardan faydalanlarak hzl bir arama gerekletirilir. Aslnda hash tablosu yntemi de bu tr bir yntemdir. Hash deeri not edilen bilgidir. 122

Algoritmik arama yntemleri arlkl olarak aalar kullanlarak gerekletirilir. Disk ve bellek zerindeki arama algoritmalarnda kullanlan yntem asndan baz farkllklar vardr.

15.7. Aa Yaplar

Belirli bir dme tek bir yerden gelinebilen dm topluluuna aa denilir. rnein:

Eer bir dme birden fazla ekilde gelinebiliyorsa, bu tr dm topluluuna graf denilmektedir. rnein:

123

Eer grafn zerinde ynlendirme yoksa ift tarafl ynlendirmenin olduu dnlmelidir. Bir aata tek bir kk vardr. ki dm balayan yola ngilizce arc denilir. Ayrca bir aata tek bir kkn bulunmas ve o kke hibir gidiin olmamas gerekir. Bir aata her dmn bir ykseklii vardr. Buna dmn derecesi de denilmektedir. Dmn yksekli o dme gidilmek iin ka tane yoldan geildii bilgisidir. Bir aacn ykseklii en yksek dm ile belirlenir. Aata her bir dmn tek bir st dm (parent node) bulunmaktadr. Bir dmn hi alt dm yoksa yaprak (leaf) denir. Kk ve yapraklar dndaki dmlere de ara dm (internal nodes) denilir. Bir aata her bir dmn en fazla m tane alt dm olmas koulu varsa bu aaca m li aa (n ary tree) denir. zel olarak bir dmn en fazla iki alt dm varsa bu tr aalara ikili aa (binary tree) denilir. Eer bir aa arama amal kuruluyorsa bu tr aalara arama aalar (search trees) denir. En yaygn kullanlan arama aalar ikili arama aalardr (binary search trees). Bir ikili arama aacn kkleri sola bykleri sola yerletirerek olutuabiliriz. rnein:

17 25

32

12

Eer bir ikili aata tm yapraklarn ykseklii arasnda belirli bir fark varsa (tipik olarak 1) bu tr aalara dengelenmi ikili aa tr denilir.

124

Eer bir ikili aata yapraklar dndaki btn dmlerin tam olarak iki alt dm varsa bu tr ikili aalara tam ikili aalar (complete binary trees) denilmektedir.

Bir ikili arama aac dengeli ise tpk ikiye blme ynteminde olduu gibi en kt baarl arama karmakl yada baarsz arama karmakl O(n) = log2n dir. kili arama aaalar dengesiz olarak kullanlabilir. Fakat dengesiz bir ikili aacn en kt durumu bal liste haline dnmesidir. Aaca yeni dm eklendike dengenin bozulmasn engelleyen ve aac dengede tutan yntemler vardr. En nemli iki yntem krmz-siyah aac (red black tree) ve AVL aac (Adelson-Velski-Lendis tree) dr. Krmz-siyah aacnda denge faktr 1 den byk olabilmektedir. Fakat dengeye getirmek daha kolaydr. AVL aac ise daha dengelidir. Fakat dengeleme ilemi biraz daha karmaktr.

125

Bir ikili aa dmler birer yap olacak biimde yollarda birer gsterici olacak biimde bir yap ile temsil edilebilir. kili aacn bir dm aadaki gibi bir yap ile temsil edilebilir:
typedef struct tagBNODE { DATATYPE val; struct tagBNODE *pLeft; struct tagBNODE *pRight; } BNODE;

Kk dmde bir gstericide tutulursa ikili arama aac oluturulabilir.

15.7.1. Dengelenmemi kili Aacn Oluturulmas kili aacn handle alan aadaki gibi oluturabilir:

typedef struct tagBTNODE { DATATYPE val; struct tagBTNODE *pLeft; struct tagBTNODE *pRight; } BTNODE; typedef struct tagBTREE { BTNODE *pRoot; size_t count; } BTREE, *HBTREE;

Handle alann oluturan fonksiyon yle olabilir:

HBTREE CreateBTree(void) { HBTREE hBTree; if ((hBTree = (HBTREE)malloc(sizeof(BTREE))) == NULL) return NULL; hBTree->pRoot = NULL; hBTree->count = 0; return hBTree; }

126

kili aaca eleman eklemek iin nce eklenecek yerin bilinmesi gerekir. rnein: 15

30

90

17

40

70

110

120

Burada rnein 85 numaral bir dm eklemek isteyelim. Yer bulma ilemi olduka basittir. Kk dmden balanr, bykse saa kkse sola doru gidilir. NULL grnce durulur.

BTNODE *InsertItem(HBTREE hBTree, DATATYPE val) { BTNODE *pNewNode, *pNode, *pPrevNode; pNewNode = (BTNODE *) malloc(sizeof(BTNODE)); if (pNewNode == NULL) return NULL; pNewNode->pLeft = pNewNode->pRight = NULL; pNewNode->val = val; if (hBTree->pRoot == NULL) { hBTree->pRoot = pNewNode; return pNewNode; } pNode = hBTree->pRoot; while (pNode != NULL) { pPrevNode = pNode; pNode = val < pNode->val ? pNode->pLeft : pNode->pRight; } if (val < pPrevNode->val) pPrevNode->pLeft = pNewNode; else pPrevNode->pRight = pNewNode;

127

return pNewNode; }

kili arama aac zellikle arama iin kullanldna gre, aramada bir anahtar ve deerin olmas daha anlamldr. Bu nedenle aslnda dmn yle oluturulmas daha uygun olur.

typedef struct DATATYPE { KEYTYPE key; VALIDATETYPE val;

Fakat bu tasarmda VALUETYPE ayn zamanda anahtar deeri de ieriyorsa, bilgi iftlemesi sz konusu olur. Eer anahtarda DATATYPE ierisinde ise, bu durumda biz arama srasnda anahtar ksm doldurulmu bir DATATYPE verebiliriz. Yukarda ki InsertItem fonksiyonunda DATATYPE bir yap olamaz nk biz onu karlatrma operatrleri ile kullanmz. Fakat bu rnek algoritmik yapnn anlalmas iin verilmitir. Eleman arayan fonksiyon yle yazlabilir:

DATATYPE *FindItem(HBTREE hBTree, DATATYPE val) { BTNODE *pNode; pNode = hBTree->pRoot; while (pNode != NULL) { if (val == pNode->val) return &pNode->val; pNode = val < pNode->val ? pNode->pLeft : pNode->pRight; } return NULL; }

16. ZYNELEMEL ALGORTMALAR VE KEND KENDN AIRAN FONKSYONLAR

128

Sistem programlamada karlalan baz tipik algoritmalar zyinelemelidir. zyinelemeli algoritmalar tipik olarak kendi kendini aran fonksiyonlar ile gerekletirilir. Aslnda zyinelemeli algoritmalar suni bir stack kullanm ile zyinelemeli olmayan fonksiyonlarla da gerekletirilebilir. Sistem programlama da kullanlan tipik zyinelemeli algoritmalardan bazlar unlardr: Aa dolama algoritmalar Permtasyon oluturan algoritmalar Parsing algoritmalar Dizin dolama algoritmalar Dierleri

Bir algoritma zerinde zm iin ilerlediiniz zaman eer baladmz noktaya ok yakn bir durum ile karlayorsak bu algoritma zyinelemeli karaktere sahiptir. Tipik olarak kendi kendini aran fonksiyonlar ile gerekletirilir. Bir fonksiyonun kendini armas ile baka bir fonksiyonu armas arasnda ilevsel hibir farkllk yoktur. Parametre deikenleri ve yerel deikenler stackte oluturulduu iin her armada onlarn yeni bir kopyas oluturulmu olur. phesiz fonksiyonun hi geri dnmeden srekli kendini armas stack tamas oluturarak programn kmesine yol aar. Normal olarak fonksiyon kendi kendini ararak ilerlemeli fakat belirli bir noktadan sonra k srecine girmelidir.

16.1. zyinelemeli Fonksiyon rnekleri

1- Bir saynn faktriyelini alan bir fonksiyonun zyinelemeli olarak yazlmasna hi gerek yoktur. Tipik yazm yle olabilir:
long Factorial(int n) { long i = 1; while (n > 1) { i *= n;

129

n--; } return i; }

zyinelemeli fonksiyon aadaki gibi yazlabilir:


long Factorial(int n) { long f; if (n == 0) return 1; f = n * factorial(n - 1); return f; }

n=4 f = n*factorial(3)

n=3 f =n*factorial(2)

n=2 f=n*factorial(1)

n=1 f=n*factorial(0)

n=0 return 1

2- zyinelemeli fonksiyonlar bir eyi tersten yapmak iin sklkla kullanlmaktadr. Yani fonksiyon kendini ara ara sona kadar gider, sonra karken ilemini yapar. rnein bir yazy tersten yazan putsrev isimli fonksiyonun zyinelemeli yazlmasna gerek yoktur. Fakat yle yazlabilir:

void putsRev(const char *str) { if (*str == '\0') return; putsRev(str + 1); putchar(*str); }

130

3- Tek bal listeyi tersten dolamak iin nce kendini ara ara sona kadar gideriz. Sonra kta ilemlerimizi yaparz.

BOOL WalkListRev(NODE *pNode) { if (pNode == NULL) return; WalkListRev(pNode->pNext); printf("%d\n", pNode->val); }

4- Bir saynn bitlerini yle yazdrabiliriz:

void bitprint(unsigned n) { if (n == 0) return; bitprint(n >> 1); putchar((n & 1) + '0'); }

5- En byk elemann bulunarak ilk elemanla ya da son elemanla yer deitirilmesi biiminde sraya dizme yntemine seerek sralama (selection sort) denilmektedir. Seerek sralama ilemi zyinelemeli bir fonksiyon ile de gerekletirilebilir:

void SSort(int *p, int size) { int i, max, maxIndex; if (size == 1) return; max = p[0]; maxIndex = 0; for (i = 1; i < size; ++i) if (max < p[i]) { max = p[i]; maxIndex = i; } p[maxIndex] = p[size - 1]; p[size - 1] = max; SSort(p, size - 1);

131

6- Bilgisayar sistemi yalnzca karakterleri yazmaya izin vermektedir. Say yazdran fonksiyonlar aslnda karakter yazdran fonksiyonlar ile gerekletirilir. Yani aslnda printf gibi fonksiyonlar putchar kullanlarak yazdrlmtr. rnein 123 gibi bir sayy putchar kullanarak yazdrabilmemiz iin nce sayy basamaklarna ayrmamz gerekir. Klasik yntem blmek, blmnden elde edilen kalan bulmaktadr. Fakat bu durumda saylar tersten yazlmaktadr.
while (n) { putchar(n % 10 + '0'); n /= 10; };

lk akla gelecek yntem bu karakterleri henz bastrmayp, char trden bir dizinin ierisinde toplamak ve diziyi strrev ile ters-dz etmektir.
char s[20]; int i; while (n) { s[i++] = n % 10 + '0'; n /= 10; }; s[i] = '\0'; strrev(s);

Oysa bu ilem tipik olarak aadaki gibi kendi kendini aran bir fonksiyon ile gerekletirilebilir:

void printd(int n) { if (n < 0) { putchar('-'); n = -n; } if (n / 10) printd(n/10); putchar(n % 10 + '0'); }

Bu fonksiyonu herhangi bir tabana gre evirme yapacak ekilde genelletirebiliriz. 132

void printnum(unsigned n, int base) { if (n / base) printnum(n / base, base); putchar(n % base > 9 ? n % base - 10 + 'A' : n % base + '0'); }

7- En iyi sralama algoritmas olarak bilinen Quick-Sort algoritmas nlogn karmakla sabittir ve zyinelemeli bir karaktere sahiptir.

Algoritmann dayand fikir yle zetlenebilir. Bir pivot eleman seilir (pivot elemann iyi seilmesi olumludur fakat dizinin dalm bilinmiyorsa rasgele bir eleman pivot seebiliriz. rnein bu ilk eleman olabilir). Sonra dizi batan ve sondan hareketle sol taraftan pivottan kk deerler sa taraf pivottan byk deerler olacak biime getirilir. Sonra pivottan itibaren, pivotun iki taraf ile ayn ilemler z yinelemeli olarak yinelenir. Bir saydan kkleri solda bykleri sada toplayan basit bir fonksiyon yle yazlabilir:
int Partition(int *pi, size_t size, int val) { size_t left = 0, right = size - 1; int temp; while (left < right) { while (pi[left] < val && left < right) ++left; while (pi[right] >= val && right > left) --right; temp = pi[left]; pi[left] = pi[right]; pi[right] = temp; } return left;

133

Partition ilemi sonucunda bulunan indekste pivot deerin olmas gerekir. Bundan sonra ikiye blmeler yaplabilir. Partition fonksiyonu bir dizinin balang adresini alp left ve right ile belirtilen iki ubuk arasndaki elemanlar paralara ayracak biimde yazlrsa ve pivot yer deitirmesini yaptktan sonra pivot elemann bulunduu indekse geri dnerse bu durumda quick sort algoritmas aadaki gibi basit bir ekle dnr:
int Partition(int *a, size_t left, size_t right) { int pivot = a[left]; int i = left; int k = right + 1; int temp; for (;;) { do ++i; while (i < right && a[i] <= pivot); do --k; while (k > left && a[k] >= pivot); if (i >= k) break; temp = a[i]; a[i] = a[k]; a[k] = temp; } a[left] = a[k]; a[k] = pivot; return k; }

void QSort(int *a, size_t left, size_t right) { size_t pivotIndex; if (left < right) { pivotIndex = Partition(a, left, right); QSort(a, left, pivotIndex - 1); QSort(a, pivotIndex + 1, right); } }

134

Normal olarak partition ilemi ile blme beraber yaplabilir. Ayrca bir sarma fonksiyon ile parametreleri dzeltebiliriz. 8- kili arama aacn dolamak iin tipik olarak zyinelemeli fonksiyon kullanlabilir. rnein: 27

18

42

18 5

35

50

25

70

kili aa 3 biimde dolalabilir. Dolam ortadaki dmn sol ve sa dmlere gre hangi srada dolalacana gre isimlendirilmitir. 1. Inorder Dolam: Bu dolamda sol, st ve sa dolam uygulanr. kili aa byle dolalrsa sral olarak dolalm olur. 2. Preorder Dolam: Bu dolamda nce st dm sonra sol ve sa dmler dolalr. Bu dolam az kullanlmaktadr. 3. Postorder Dolam: Bu dolamda nce sol ve sa alt dmler, sonra st dm dolalr. Inorder dolaan fonksiyon yle yazlabilir:

void WalkTree(BTNODE *pNode) { if (pNode == NULL) return;

135

WalkTree(pNode->pLeft); printf("%d\n", pNode->val); WalkTree(pNode->pRight); }

Bu fonksiyon kk dmn adresi ile arlmaldr. kili aacn tm dmlerinin free hale getirilmesi iin aa postorder biimde dolalmaldr. nk nce alt dmlerin sonra st dmlerin free hale getirilmesi gerekmektedir. O halde ikili aac boaltmak iin yle bir fonksiyon yazlabilir:
void FreeTree(BTNODE *pNode) { if (pNode == NULL) return; FreeTree(pNode->pLeft); FreeTree(pNode->pRight); free(pNode); }

9- Dizin aacnn dolalmas tipik olarak zyinelemeli bir algoritmadr. Her iletim sisteminin bir dizin ierisindeki dosyalar elde etmek iin sunduu API fonksiyonlar vardr. Microsoft Windows derleyicileri bu API fonksiyonlarn sarmalayan _findfirst, _findnext ve _findclose fonksiyonlarn bulundurmaktadr. Bu ilemin ok benzeri UNIX sistemlerinde opendir, readdir ve closedir fonksiyonlar ile yaplmaktadr. Bu fonksiyonlar bir dizin ierisindeki dosyalar elde ederken onlarn normal bir dosya m yoksa bir dizin dosyas m olduunu da vermektedir. (Sistem programlamada dosya kavram normal dosyalar ve dizinleri de ierecek ekilde kullanlmaktadr. ) _findfirst fonksiyonunun prototipi yledir. intptr_t _findfirst(const char *file, struct _finddata_t *fileinfo); Fonksiyonun birinci parametresi bir yol ifadesidir. Bu yol ifadesi joker karakteri ierebilir. rnein: C:\\windows\\*.tmp Fonksiyonun ikinci parametresi dosya bilgilerinin yerletirilecei _finddata_t trnden bir yapnn adresini alr. Fonksiyon koulu salayan ilk dosyann bilgilerini elde eder ve bir handle deeri ile geri dner. Fonksiyon baarsz ise -1 deerine geri dnmektedir. Bu handle deeri

136

_findnext fonksiyonuna geirilerek koulu salayan dier dosyalar bulunur. Nihayet _findclose fonksiyonuyla handle alan kapatlr. _findnext fonksiyonunun prototipi yledir:
int _findnext(intptr_t _FindHandle, struct _finddata_t *_FindData);

Fonksiyon baarl ise 0 deerine baarsz ise -1 deerine geri dner. _findclose ise yledir:
int _findclose(intptr_t _FindHandle);

Fonksiyon baarl ise 0 baarsz ise -1 deerine dner. Tm bu fonksiyonlarn prototipi io.h ierisindedir. _finddata_t yaps ise yledir.
struct _finddata_t { unsigned attrib; __time32_t time_create; __time32_t time_access; __time32_t time_write; __fsize32_t size; char name[260]; }

Bir dizindeki dosyalarn listesini almak iin yle bir kod yazlabilir.
#include <stdio.h> #include <stdlib.h> #include <io.h> int main(void) { intptr_t handle; struct _finddata_t f; int result; handle = _findfirst("c:\\windows\\*.*", &f); result = handle == -1; while (!result) { printf("%s\n", f.name); result = _findnext(handle, &f); } _findclose(handle); return 0; }

137

Elde edilen dosyann bir dizin dosyas olup olmad _finddata_t yapsnn attrib eleman ile belirlenebilir. Yapnn attrib eleman bit bit kodlanmtr. Yani her bit bir zelliin olup olmadn belirtmektedir.

Arch dir

system hidden

readonly

Attrib eleman, btn bitleri 0 olan, ilgili biti 1 olan bir say ile and ekilirse ilgili bitin set edilip edilmedii, dolaysyla dosyann o zellie sahip olup olmad belirlenebilir. Bunun iin io.h ierisinde aadaki sembolik sabitler bulundurulmutur.
#define #define #define #define #define #define _A_NORMAL _A_RDONLY _A_HIDDEN _A_SYSTEM _A_SUBDIR _A_ARCH 0x00 ox01 0x02 0x04 0x10 0x20

Bu durumda bir dizindeki alt dizinlerin yanna dir biiminde iaret koymak istersek bunu yle yapabiliriz:

#include <stdio.h> #include <stdlib.h> #include <io.h> int main(void) { intptr_t handle; struct _finddata_t f; int result; handle = _findfirst("*.*", &f); result = handle == -1; while (!result) { printf("%-30s %s\n", f.name, (f.attrib & _A_SUBDIR) ? "<DIR>" : "" ); result = _findnext(handle, &f); } _findclose(handle); return 0; }

138

Snf almas: Bir dizinin dizindeki dosyalarn alnz, dosyalarn zelliklerini listenin yanna Read Only + Archive biiminde yazdrnz.
#include <stdio.h> #include <stdlib.h> #include <io.h> void PutAttr(unsigned int attr) { char *attrText[] = {"Read Only", "Hidden", "System", "", "Dir", "Archive"}; int i; for (i = 0; attr ; ++i) { if (attr & 1) { printf("%s", attrText[i]); if (attr >> 1) printf("+"); } attr >>= 1; } putchar('\n'); } int main(void) { intptr_t handle; struct _finddata_t f; int result; handle = _findfirst("*.*", &f); result = handle == -1; while (!result) { printf("%-30s", f.name); PutAttr(f.attrib); result = _findnext(handle, &f); } _findclose(handle); return 0; }

Her alt dizinde ilk iki dosya . ve .. isimli dizin dosyalardr. Bir dizinden balayarak alt dizinler ile birlikte tm aac dolamak iin zyinelemeli bir algoritma gerekir. Algoritma olduka basittir. Dizindeki dosyalar yazdrlarak ilerlenir. Bir dizin ile karlaldnda o dizine geilerek fonksiyonun kendini armas salanr.

139

#include <stdio.h> #include <stdlib.h> #include <io.h> #define MAX_PATH 260

void WalkDirTree(const char *dir) { intptr_t handle; struct _finddata_t f; int result; char path[MAX_PATH], subDir[MAX_PATH]; sprintf(path, "%s\\*.*", dir); handle = _findfirst(path, &f); result = handle == -1; while (!result) { if (!strcmp(f.name, ".") || !strcmp(f.name, "..")) { result = _findnext(handle, &f); continue; } if (f.attrib & _A_SUBDIR) { sprintf(subDir, "%s\\%s", dir, f.name); WalkDirTree(subDir); } printf("%s\n", f.name); result = _findnext(handle, &f); } _findclose(handle); } int main(void) { WalkDirTree("e:\\sysprog-cupa"); return 0; }

Fonksiyonu biraz daha kullanl hale getirebiliriz. Bunun iin bir sarma fonksiyon kullanabiliriz. Fonksiyonun bize tm yol ifadesini yada her ikisini birden vermesi de daha uygun olabilir.

#include <stdio.h> #include <stdlib.h> #include <io.h> #define MAX_PATH 260

140

#define FALSE #define TRUE typedef int BOOL;

0 1

void WalkDirTree(const char *dir, void (*Proc)(const char *path, const struct _finddata_t *file)) { intptr_t handle; struct _finddata_t f; int result; char path[MAX_PATH], newFile[MAX_PATH]; sprintf(path, "%s\\*.*", dir); handle = _findfirst(path, &f); result = handle == -1; while (!result) { if (!strcmp(f.name, ".") || !strcmp(f.name, "..")) { result = _findnext(handle, &f); continue; } sprintf(newFile, "%s\\%s", dir, f.name); Proc(newFile, &f); if (f.attrib & _A_SUBDIR) WalkDirTree(newFile, Proc); result = _findnext(handle, &f); } _findclose(handle); } void Disp(const char *path, const struct _finddata_t *f) { printf("%s\n", path); } int main(void) { WalkDirTree("e:\\sysprog-cupa", Disp); return 0; }

Bazen bir dosya bulunduunda artk daha fazla ilemin devam etmesi istenmez. Bu durum aadaki gibi salanabilir:
#include <stdio.h> #include <stdlib.h> #include <io.h>

141

#define #define #define typedef

MAX_PATH FALSE TRUE int BOOL;

260 0 1

BOOL WalkDirTree(const char *dir, BOOL (*Proc) (const char *path, const struct _finddata_t *file)) { intptr_t handle; struct _finddata_t f; int result; char path[MAX_PATH], newFile[MAX_PATH]; sprintf(path, "%s\\*.*", dir); handle = _findfirst(path, &f); result = handle == -1; while (!result) { if (!strcmp(f.name, ".") || !strcmp(f.name, "..")) { result = _findnext(handle, &f); continue; } sprintf(newFile, "%s\\%s", dir, f.name); if (!Proc(newFile, &f)) { _findclose(handle); return FALSE; } if (f.attrib & _A_SUBDIR) if (!WalkDirTree(newFile, Proc)) { _findclose(handle); return FALSE; } result = _findnext(handle, &f); } _findclose(handle); return TRUE; } BOOL Disp(const char *path, const struct _finddata_t *f) { printf("%s\n", path); return TRUE; } int main(void) { WalkDirTree("e:\\sysprog-cupa", Disp); return 0; }

142

Snf almas: Bir kk dizinden itibaren dizin aacn bir aa yaps biiminde bellekte oluturunuz. Bir dm bir dosyaya ya da bir dizine ilikin olabilir. Eer dm dizine ilikinse bu dmn alt dmleri bu dizinin iindeki dosyalar belirtmektedir. Yani bir dizin ierisindeki dosyalar bal liste biiminde dnebiliriz. Bal listenin eleman bir dizin ise buda baka bir bal listenin head gstericisini tutmaktadr. Aklama: Bu aa yapsnn bir dm yle oluturulabilir:
typedef struct struct struct } NODE; struct tagNODE { _finddata_t f; NODE *pNext; NODE *pHead;

Burada normal dosyalar iin pHead gstericisinin bulundurulmas gereksiz grlebilir. Geri uygulamada bu kaybn ciddi bir nemi yoktur. Fakat istenirse iki tr dm bulundurulabilir.
typedef struct tagFILE_NODE { struct _finddata_t f; struct tagFILE_NODE *pNext; } FILE_NODE; typedef struct tagDIR_NODE { struct _finddata_t f; FILE_NODE *pNext; FILE_NODE *pHead; } DIR_NODE;

Bylece liste elemanlar FILE_NODE biiminde tutulabilir. Duruma gre DIR_NODE * trne dntrlebilir. Ayn ilem C++ ta tretme yolu ile yaplabilir.
struct FileNode { struct _finddata_t m_f; FileNode *m_pNext; }; struct DirNode : public FileNode { FileNode *m_pHead; };

143

Bal liste iin standart ktphanede bulunan list snf kullanlacaksa, daha deiik bir dzenlemeye gidilebilir.

struct FileNode { struct _finddata_t m_f; }; struct DirNode : public FileNode { std::list<FileNode *> m_head; };

imdi aac ilk biimde kurduumuzu dnelim.


typedef struct struct struct } NODE; struct tagNODE { _finddata_t f; NODE *pNext; NODE *pHead;

Byle bir aac dolama ilemi yine zyinelemeli olarak yaplmak zorundadr.
void WalkListTree(NODE *pDir) { NODE *pNode = pDir; while (pNode != NULL) { /***/ if (f.attrib & _A_SUBDIR) WalkDirTree(pNode->pHead); pNode = pNode->pNext; } }

Baka bir rnek: sample.exe dosyasnn bulunmas


BOOL Disp(const char *path, const struct _finddata_t *f) { char *pStr; pStr = strrchr(path, '\\'); if (pStr) if (!stricmp(pStr + 1, "sample.exe")) { printf("%s\n", path); return FALSE; } return TRUE; }

144

C# program ile yukardaki yapmak istediimizi basite yapabiliriz:

using using using using using

System; System.Collections.Generic; System.Linq; System.Text; System.IO;

namespace SampleCSharp { class Program { static void Main(string[] args) { string[] files; files = Directory.GetFiles("e:\\sysprog-cupa", "*.*", SearchOption.AllDirectories); foreach (string s in files) Console.WriteLine(s); } } } Anahtar Notlar: Her iletim sisteminde yol ifadesinin maksimum karakter says nceden belirlenmi durumdadr. rnein LINUX sistemlerinde 256, Windows sistemlerinde 260 karakterdir. Bu durumda biz yukardaki WalkDirTree fonksiyonuna 260dan daha byk bir yol ifadesi geemeyiz. WalkDirTree fonksiyonu prosesin default alma dizinini deitirecek biimde yeniden yazlabilir. Bylece bu snr byk lde kaldrlm olur.

17. PROSESLER ARASINDA ALTLIK STLK LKS


UNIX/LINUX sistemlerinde kat bir biimde Windows sistemlerinde gevek bir biimde prosesler arasnda stlk altlk ilikisi vardr. Bir proses yani program baka bir prosesi yani program altrdnda altran proses st proses, altrlan proses alt proses olur. rnein biz komut satrndan bir program altrdmzda, (komut satr cmd.exe isimli bir programdr)

145

altrlan prosesin st prosesi cmd.exe olacaktr. Solomon tarafndan yazlm olan proses explorer isimli program Windowsta alan prosesler zerinde eitli faydal bilgileri vermektedir. Gerek unix sitemlerinde gerekse windows sistemlerinde olsun, st ve alt prosesler arasnda baz aktarmlar yaplmaktadr. Daha teknik bir anlatmla st prosesin proses tablosundaki baz bilgiler yaratlan prosese aktarlmaktadr. Bu tipik bilgiler unlar olabilir: Unix sistemlerinde user id, group id, efective user id, efective group id ve Windows sistemlerinde ki gvenlik bilgileri aktarlr. Prosesin default alma dizini evre deikenleri Dier nemli bilgiler

17.1. Proseslerin evre Deikenleri (Environment Variables)

Pek ok iletim sisteminde evre deikeni kavram vardr. evre deikenleri deiken = deer iftlerinden oluur ve genellikle alt prosese dorudan geirilirler. evre deikenleri UNIX/LNUX sistemlerinde shell zerinden
export deiken = deer

ilemi ile oluturulabilir. Windows komut satrnda


set deiken = deer

ilemi ile oluturulabilir. Bu biimde shell zerinden evre deikenleri oluturulduunda bu evre deikenleri shellin evre deikenleri olur. Dolaysyla shellden altrlacak programlara dorudan aktarlr. Unix sistemlerinde shell zerinde bir evre deikeni $ ile kullanlrsa evre deikenine kar gelen deer elde edilir. rnein:
export fiyat = 1300 echo $fiyat

1300 yazlmasna neden olur. Windowsun komut satrnda evre deikeni iki yzde arasna getirilirse ayn etki oluturulabilir. evre deikenlerini set etmek ve kullanmak iin iki C fonksiyonu kullanlr.

146

char *getenv(const char *name);

Prototipi stdlib.h balk dosyas iinde bulunur. Fonksiyon parametre olarak evre deikeninin ismini alr. Geri dn deeri olarak evre deikeninin deerini verir. Fonksiyon deikenin deerini statik bir alana yazp onun adresi ile dner. Eer ilgili evre deikeni yoksa fonksiyon NULL deerine geri dner.
#include <stdio.h> #include <stdlib.h> int main(void) { char *pStr; if ((pStr = getenv("fiyat")) == NULL) { fprintf(stderr, "Cannot get environment variable\n"); exit(EXIT_FAILURE); } puts(pStr); return 0; }

Prosesin evre deikenleri alt prosese geirilebildiine gre komut satr da bir proses olduuna gre biz komut satrnda bir evre deikeni oluturup komut satrndan bir program altrrsak altrlan programa o evre deikeni geer. Windowsta komut satrnda set komutu unix/linux sistemlerinde env komutu shell in tm evre deikeni listesini dkmektedir. evre deikenlerini programlama yolu ile oluturmak iin setenv fonksiyonu kullanlr. setenv fonksiyonunun bir benzeri putenv isimli fonksiyondur. setenv fonksiyonu POSIX sistemlerinde bu isimle bulunur. Microsoft sistemlerinde bu fonksiyon putenv biimindedir.
int _putenv(const char *envstring);

Fonksiyonun parametresi deiken = deer biimindedir. Fonksiyon baarl ise 0 deerine, baarsz ise -1 deerine geri dner. Eer ilgili evre deikeni varsa yeni deer zerine yazlr. rnein:

147

int main() { _putenv("fiyat = 1300"); return 0; }

phesiz alt prosesteki deiiklik st prosesteki deiiklii etkilememektedir. yani rnein biz komut satrnda n bir program altrsak bu program ile de bir evre deikenini set etsek komut satr bundan etkilenmez. Peki, komut satrna yani shelle otomatik bir biimde bir evre deikenini nasl ekleyebiliriz? Bunun iin Windowsta kontrol panel/sistem mens kullanlr. Burada belirli bir kullancnn shelli iin ekleme yaplabilecei gibi tm sistemi etkileyecek ekleme de yaplabilir. Benzer biimde Linux sistemlerinde de login ilemi srasnda baz dosyalar gzden geirilmektedir. rnein /etc/profile dosyas hangi shell kullanlrsa kullanlsn dikkate alnr. Bu dosyann ierisinde evre deikenlerini oluturabiliriz. Yada rnein yaygn kullanlan bash shell i iin. evre deikenleri baz global belirlemeleri yapmak iin sklkla kullanlmaktadr. rnein bir C derleyicisi include dosyalarnn default dizinini elde etmek iin INCLUDE isimli evre deikenine bavurabilir. yada rnein biz bir data dosyasn DATAFILE isimli bir evre deikeninin belirttii bir dizinde arayabiliriz. Bylece kullanc bu data dosyasn baka bir dizine yerletirecekse DATAFILE evre deikenini ayarlamak durumundadr. Anahtar Notlar: Windows sistemlerinde evre deikenlerinin byk harf kk harf duyarll yoktur fakat Linux sistemlerinde vardr. PATH isimli evre deikeni hem Windows hem de Linux sistemlerinde iletim sisteminin kendisi tarafndan da kullanlmaktadr. Windows ta PATH evre deikeninin deeri noktal virgllerle ayrlm dizinlerden oluur. rnein:
set PATH = c:/Windows; c:\test

Linux sistemlerinde dizin ayrmak iin iki nokta st ste karakteri kullanlmaktadr. rnein:
export PATH = /bin: /wr/bin

148

rnein Windows komut satrnda biz PATH evre deikenine aadaki gibi bir komutla ekleme yapabiliriz:
c:\cs cupa > set PATH = %PATH% ; c:\test

Peki, PATH evre deikeni ne ie yarar? PATH evre deikeni iletim sisteminin program aran sistem fonksiyonlar tarafndan dorudan baklmaktadr. Windowsta CreateProcess API fonksiyonu CreateProcess API fonksiyonu eer altrlacak dosya dorudan dosya ismi biiminde belirtilmise PATH evre deikenine bakmaktadr. Dosyay srasyla PATH evre deikeninde ; ile ayrlm blgede arar.
Anahtar Notlar: Yukarda da belirtildii gibi CreateProcess eer dosya ismi bir dizin ierecek biimde belirtilmise PATH evre deikenine bakmaz. Yani rnein biz komut satrndan bir program study/test biiminde altrmak istersek.

Fakat program yalnzca test denilerek baklrsa PATH evre deikenine baklmaktadr. CreateProcess her zaman nce bulunulan dizine sonra PATH ile belirtilen dizine bakmaktadr. Linux sistemlerinde program altrmakta kullanlan exec fonksiyonlarnn pli versiyornlar (execvp, execlp) eer dosya isminde bl karakteri yoksa PATH evre deikenine bakar. Bu fonksiyonlar bu durumda prosesin alma dizinine bakmazlar. phesiz program altran bu sistem fonksiyonlar fonksiyon hangi proses tarafndan altrlmsa o prosesin PATH evre deikenine bakmaktadr.

17.2. Prosesin Default alma Dizini

Bir dosyann hangi dizinde olduunu belirten yazya yol ifadesi (path name) denir. Pek ok sistem fonksiyonu dosya ile ilgili ilem yaparken bir yol ifadesi istemektedir. Dizin geileri dos ve Windows sistemlerinde \ ile Linux sistemlerinde / ile yaplmaktadr. Ayrca Linux sistemlerinde src kavram yoktur.

149

Linux sistemlerinde mount etme kavram vardr. Bir dosya sistemi bir dizine mount edilir (monte edilir) bylece o dosya sisteminin kk dizini o dizin olur. Dos ve Windows sistemleri bunun yerine src kullanmaktadr. Her farkl dosya sistemi bir src biimindedir. Pek ok iletim sisteminde her prosesin bir default alma dizini (current working directory) vardr. Genellikle kullanclar kendilerinin sanki bir dizini ierisinde durduklarn sanrlar. Aslnda byle bir durum sz konusu deildir. Komut satrnda grlen prompt aslnda o komut satr programnn alma dizinidir. Bir prosesin baka bir prosesi altrmas durumunda prosesin default alma dizini alt prosese geirilmektedir. Bir prosesin alma dizini Windows sistemlerinde _chdir, unix/Linux sistemlerinde chdir fonksiyonlaryla deitirilir.
int _chdir(const char *dirname);

Fonksiyon baarl ise 0 deerine, baarsz ise -1 deerine geri dner. Fonksiyonun Windows sistemlerindeki prototipi direct.h, unix/Linux sistemlerindeki prototipi unistd.h ierisindedir. Prosesin alma dizinini elde etmek iin Windows sistemlerinde _getcwd, unix/Linux sistemlerinde getcwd kullanlr.
char * _getcwd(char *buffer, int maxlen);

Fonksiyonun birinci parametresi geerli dizinin yerletirilecei diziyi ikinci parametresi bu dizinin uzunluunu belirtir. Fonksiyon birinci parametresine yazlan adresin ayns ile geri dner.
#include <stdio.h> #include <stdlib.h> #include <direct.h> #define MAX_PATH #define MAX_CMD_LINE int main(void) { char cwd[MAX_PATH]; char cmdLine[MAX_CMD_LINE]; for (;;) { _getcwd(cwd, MAX_PATH); printf("%s>", cwd); gets(cmdLine); } 260 4096

150

return 0; }

Prosesin default alma dizini proses tablosunda saklanmaktadr. Bir PATH ifadesini mutlak (absolute) ve greli (relative) olmak zere ikiye ayrabiliriz. Eer bir yol ifadesindeki src ismi hari ilk karakter Windows ta \, unix/Linux ta / ise bu tr yol ifadelerine mutlak yol ifadeleri denilir. rnein:
/root/sslsl C:\windows\system32

Mutlak yol ifadeleri kk dizinden itibaren yer belirtir. Eer ilk karakter / veya \ deilse bu tr yol ifadelerine greli yol ifadeleri denilir. rnein:
a\b\c.dat x/y/z.dat test.dat

Prosesin default alma dizini greli yol ifadeleri iin balang yerini belirtir. Bunun dnda kullanlmaktadr. rnein: f = fopen(test.dat, r); Burada test.dat dosyas greli bir biimde verilmitir. O halde prosesin alma dizininde aranacaktr. Prosesin alma dizini Windows sistemlerinde CreateProcess API fonksiyonu ile proses yaratlrken belirlenmektedir. Bu fonksiyonda duruma gre programc default alma dizininin st prosesden alnmasn isteyebilir yada bunu kendisi set edebilir. rnein Visual Studio IDE si ctrl+f5 ile program altrrken, altrlacak programn alma dizinini proje dizini olarak ayarlamaktadr. Unix/Linux sistemlerinde prosesin alma dizini fork ilemi srasnda dorudan st prosesden alnmaktadr. Tabi programc exec uygulamadan nce chdir fonksiyonuyla bunu deitirebilir.

18. PROSESLER ARASI HABERLEME


Modern iletim sistemlerinin ounda proseslerin bellek alan izole edilmitir. Bir proses baka bir prosesin bellek alanna eriemez. Bir prosesin baka bir prosese herhangi bir biimde

151

bilgi gnderebilmesi iin iletim sisteminde deiebilecek eitli yntemler uygulanmaktadr. Bu konuya genel olarak prosesler aras haberleme (interprocess communication IPC) denilmektedir. Prosesler aras haberleme ayn makinedeki proseslerin haberlemesi ve adaki herhangi iki makinede alan herhangi iki prosesin haberlemesi biiminde ikiye ayrlmaktadr. phesiz tek bir makinede bir a kabul edilmektedir ve a haberlemeleri tek bir makine zerinde yaplabilir. Yerel makine zerindeki prosesin haberlemesine ynelik farkl sistemlerde pek ok mekanizma vardr. Baz mekanizmalar pek ok iletim sisteminde benzer biimde kullanlr. Bu mekanizmalardan bazlar unlardr: Boru (pipe) haberlemesi Paylalan bellek alanlar (shared memory) Mesaj sistemleri

Bunlar dnda iletim sistemlerine zg yerel makine haberlemeleri vardr. A zerindeki prosesler aras haberlemesi bir protokol gerektirmektedir. nk bir a farkl donanmlara zg farkl iletim sistemlerinin bulunduu eitli makineler balanabilir. Bunlarn ortak bir dilden konuabilmesi iin ortak baz belirlemelere gereksinim vardr. Bu belirlemelere protokol denilmektedir. Yine de baz a haberlemeleri belirli bir sisteme zg olabilir ve belirli bir firmann protokollerini kullanyor olabilir. rnein Microsoft firmasnn Microsoft network, Novell firmasnn IPX/SPX, Apple firmasnn AppleTalk diye isimlendirilen ve a haberlemesinde kullanlan protokolleri vardr. Fakat phesiz 1983 ylnda internetinde kullanmaya balad TCP/IP protokol ailesi, en ok kullanlan protokol ailesidir. Bu blmde a zerindeki herhangi iki makinede bulunan proseslerin haberlemesine ynelik IP ailesinin temel kullanm ele alnacaktr.

18.1. A Kavram ve Tarihsel Geliimi

1960l yllara kadar bilgisayarlar birbirine balama fikri zerinde durulmamtr. Fakat 60l yllarla birlikte a oluturma kavram zerinde uygulama faaliyetleri balamtr. lk ciddi a

152

oluturma faaliyeti Amerikan Savunma Bakanlna bal DARPA diye bilinen alma grubu tarafndan balatlan ARPANET projesidir. Bu proje potansiyel bir nkleer sava durumu iin yrrle sokulmutur ve ilk ciddi a balants bu proje kapsamnda gerekletirilmitir. 1968 ylndaki bu ilk ciddi denemeden sonra Amerikada ARPA ana zamanla niversiteler, devlet kurumlar ve ticari kurumlar katlmtr. 70li yllarda bu a Avrupaya yaylmtr. ARPA a ilk zamanlar NCP (network control protocol)denilen bir protokol kullanyordu. Sonra 1983 ylnda IP protokol ailesine geilmitir. 90l yllarla birlikte kiisel kullanclarda bu aa balanmaya balamtr ve bu aa The Internet denilmektedir. 80li yllarda kiisel bilgisayarlarnda gelimesi ile kurumlar ve irketler kendi kiisel bilgisayarlarn da birbirine balamaya balamtr. Genellikle bir binann dna kmayan balantlar ieren bu alara yerel alar (local area network) denilmektedir. Yerel alar yaygnlamaya balaynca yerel alar birbirine balama temas da gndeme gelmitir. Yerel alarda kullanlan protokoller farkl olabilir. Fakat yerel alar birbirine balanacaksa alarn birbirlerine balanmas konusunda belirlemelere sahip olan protokoller kullanlmaldr. Internet szc alardan oluturulan a anlamna gelir ve bu anlamda pek ok irket, kurum ya da ahs internet oluturabilir. Global dzeyde, herkes tarafndan bilinen dev aa da, halk arasnda internet denilmektedir. Yani internet bir cins isim olmasna ramen zel isim olarak da kullanlmaktadr. IP (Internet Protocol) protokol ailesi hem yerel alarda hem de yerel alarn birbirine balanmas ile elde edilen geni alarda kullanlmak zere tasarlanm geni bir ailedir. IP protokol ailesi herkese ak (public) bir protokoldr (ticari deildir). A oluturmann ilk ve en aa seviyeli aamas bilgisayarlar fiziksel olarak birbirine balamaktr. A ierisindeki her bir bilgisayardan dierine fiziksel bir balant kurulabilmesi gerekir. Bunun iin seri portlar kullanlabilecei gibi ok daha gelimi zel network kartlar (NIC, Network Interface Card) kullanlabilir. Bugn PClerde yaygn olarak Ethernet kartlar olarak bilinen zel network kartlar kullanlmaktadr.

18.2. Protokol Kavram ve Protokol Katmanlar

Bir haberleme iin baz ortak kurallara uyulmas gerekmektedir. Bu ortak kurallara protokol denir. Protokollerde tamamen yazlmdaki ktphaneler gibi st ste ylmtr. Bir protokol

153

dierinin zerinde ise dierinin zaten var olduu fikri ile tanmlamalar yapmaktadr. Bylece hem protokol oluturmada esneklik salanm olur hem de daha bamsz tanmlamalar yaplabilir. rnein TCP protokol IP protokolnn zerinde, FTP ise TCP protokolnn zerindedir. Yani TCP protokol zaten IP protokol kurallarnn var olduu durumda ek bir takm olanaklar sunmaktadr. FTP protokolnde transfer ilemi TCP olanaklar ile gereklemektedir. Katmanl a oluturmak iin eitli nerilerde bulunulmutur. Bunlardan en yaygn bilineni OSI (Open System Interconnection) modelidir. OSI modelinde bir protokol ailesi oluturmak isteyenlerin tipik olarak hangi katmanlar oluturmas gerektii belirtilmektedir. Bu model yalnzca neri sunmakta herhangi bir balaycl bulunmamaktadr. rnein IP protokol ailesi 7 katmanl OSI modeline uymamaktadr. OSI katmanlar unlardr: Application Layer (Uygulama Katman) Presentation Layer (Sunum Katman) Session Layer (Oturum Katman) Transport Layer (letim Katman) Network Layer (A Katman) Data-Link Layer (Veri Ba Katman) Physical Layer (Fiziksel Katman) Fiziksel katman network kart, haberlemede kullanlan kablolama sistemi ve sinyal karakteristikleri gibi belirlemeler iermektedir. rnein Ethernet protokol yani Ethernet kartlar ve genel anlamda bu karakteristikler byk lde fiziksel katmana ilikindir. rnein biz bilgisayarlar seri porttan da birbirine balayabiliriz Ethernet karttan da. Fiziksel olarak bu iletiimler farkldr. Fakat neticede bir bilgisayardaki baytlar dierine gnderilebilmektedir. Bu en aa katmandr ve genellikle IP protokol ailesinde bu katman Ethernet kartlar ve kablolama ve aktarm standartlar oluturmaktadr. Data-Link katman fiziksel katmann zerindeki daha organizasyonel katmandr. Bu katmanda tipik olarak u belirlemeler yaplmaktadr: Makinelerin fiziksel adreslenmesi: rnein Ethernet protokolnde her bir Ethernet kartnn dnya genelinde tek olan bir MAC adresi vardr. Yani bir makine baka bir makineye bilgi gnderecekse o makinedeki Ethernet kartnn MAC adresini bilmek zorundadr. MAC adresi Windows sistemlerinde ipconfig, Unix sistemlerinde ifconfig komutu ile elde edilebilir.

154

Ak kontrol veri ba katman ile ilikilendirilmitir. Hata (Error) kontrol: Gnderilen ve alnan bilginin hatal gnderilip gnderilmediinin belirlenmesi bu katmana ilikindir. Grld gibi Ethernet protokol daha ok fiziksel ve veri ba protokollerinin

birleiminden meydana gelmektedir. A katmannda artk bilgiler fiziksel olarak gnderilip alnabilmekte ve baz mantksal organizasyonlar yaplabilmektedir. A katmannda genellikle mantksal bir adresleme sistemine ilikin belirlemeler yaplmaktadr. rnein fiziksel bakmdan her makinenin MAC adresi bulunabilir fakat alarn birbirine balanmas durumunda pek ok bakmdan MAC adresi kullansz olmaktadr. Bunun yerine adaki her bir elemana baka bir biimde adresler verilebilir. rnein IP protokol tipik olarak a katmanna ilikindir ve burada mantksal adresleme olarak IP adresleri kullanlmaktadr. Ayrca a katmannda bilgi paket paket gnderiliyorsa bunlarn nasl ve hangi rotadan gnderileceine ilikin belirlemeler de bulunmaktadr. letim katmannda artk gvenlii artrmak iin daha yksek seviyeli belirlemeler yaplmaktadr. rnein IP protokol ailesindeki TCP ve UDP protokolleri iletim katmanna ilikindir. Bu katmanda adresleme konusunda daha ince belirlemeler yaplr. rnein port kavram bu katmana ilikin bir tanmlamadr. Yine bu katmanda eer bir balant kullanlacaksa buna ilikin belirlemeler ya da datagram biiminde gnderim alm olacaksa buna ilikin belirlemelerde yaplmaktadr. Yine ak ve hata kontrol bu aamada da uygulanabilir. Haberleme gvenliini artrc unsurlar bu katmana ilikindir. Oturum katmannda iletiimin genel biimi tanmlanr. rnein full-duplex mi half-duplex mi olduu belirlenir. Senkronizasyon ilemleri de bu katmana ilikindir. Sunum katmannda artk haberlemeye ilikin pek ok detay halledilmi durumdadr. Bu katman tipik olarak saysal ve alfabetik dntrmeler, sktrma ve ama ilemleri, ifreleme ve zme ilemleri gibi belirlemeler ile urar. Uygulama katmannda nihayet en yksek seviyeli protokoller bulunmaktadr. Yani artk gerek ii yapan uygulama yazlmlar bu katmana ilikindir. rnein IP protokol ailesinde http, FTP, POP3, SMTP gibi protokoller tipik olarak yksek seviyeli protokollerdir ve uygulama katmanna ilikindirler. phesiz bir protokol ailesinde bu yedi katman iin bire bir karlkl bir katmanlama yaplmayabilir. rnein IP protokol ailesi kabaca 4 katmanldr ve OSI modeline uymamaktadr.

155

OSI modelindeki fiziksel ve veri-ba katmanlar IP ailesinde tek bir katman olarak deerlendirilir. A ve iletim katmanlar OSIde belirtildii biimde kullanlmtr. Oturum ve Sunum katmanlar bir anlamda yoktur, bir anlamda ise belli lde dier katmanlarn iersindedir. Fakat uygulama katman OSIde belirtildii gibidir. IP protokol katmanlar aadaki gibidir: Uygulama Katman letim Katman A Katman Veri-Ba ve Fiziksel Katman

18.3. TCP/IP Protokol Ailesi

IP (Internet Protocol) ailesi denildiinde yalnzca IP protokol deil bunun yukarsndaki tm protokoller anlalmaldr. IP protokol OSI modelindeki a katmanna kar gelmektedir. Paket anahtarlamal (packet switching) bir yapya sahiptir. Bu protokolde aa bal her bir birime host denilmektedir. Host bir bilgisayar olabilecei gibi bir yazc ya da kamera olabilir. Bu protokolde her hostun IP numaras denilen mantksal adresi vardr. IPv4te IP numaras 4 bayt (32 bit) uzunluundadr. IPv6ta 16 bayt (128 bit) uzunlua telenmitir. IP protokoln kullanarak biz bir grup bilgiyi (buna paket denir) farkl yollardan belli bir hosta gnderebiliriz. Bunun iin hostun IP numarasn bilmemiz gerekir. IP protokol alar aras bir protokol olduuna gre ilgili host bizim yerel amzda bulunabilecei gibi baka bir ada da bulunuyor olabilir. IP protokol 1983 ylnda nternetin resmi protokol haline getirilmitir. Dolaysyla biz IP protokol ailesini kullanarak hem kendi yerel amzda (Intranet Uygulamalar) hem de global nternet denilen ada uygulamalarmz altrabiliriz.

18.3.1. TCP ve UDP Protokolleri letim katmanndaki protokoller balantl (connection oriented) ya da balantsz (connectionless) olabilir. TCP balantl, UDP balantsz bir protokoldr. Balantl protokollerde nce gnderici ile alc arasnda bir balant kurulur, sonra paketler gvenli bir biimde aktarlr.

156

Aktarm srasnda balant korunmaktadr. Paket aktarmnn doru yaplp yaplmad belirlenir ve duruma gre hatay telafi etmek iin yeniden gnderim uygulanr. Hlbuki balantsz protokollerde gnderim sonlanana kadar bir balant oluturulmaz. Gnderici paketi gnderir, alcnn alp almad ile ilgilenmez. Balantl protokoller daha gvenli fakat yavatr. Balantsz protokoller daha hzl fakat gvensizdir. Balantsz protokoller bir radyo yaynna benzetilebilir. Yaynn alc tarafndan alnp alnmadn, yayn yapan bilmemektedir. Balantsz protokoller grnt, ses gibi bilgilerin iletilmesinde tercih edilebilir. Genellikle bu tr uygulamalarda arada bir gnderinin baarsz olmasnn ciddi bir nemi yoktur. Fakat IP protokol ailesinin uygulama katmanndaki protokolleri TCP zerine kurulmutur. Bu nedenle TCP tabanl almaya TCP/IPde denilmektedir. UDP tarz almaya UDP/IP denilmektedir. Bir protokol zellikle iletim katman tarafndan stream tabanl ya da datagram tabanl biimde oluturulabilir. TCP (Transmission Control Protocol) stream tabanl bir alma sunar. UDP (User Datagram Protocol) ise datagram tabanl bir alma sunar. Datagram gnderilen ve alnan paketlere verilen bir isimdir. phesiz TCP de paket haberlemeli bir altyapya sahiptir. nk gerek TCP, gerek UDP IP protokol zerine oturtulmutur. Paketlerin gnderilip alnmas IP protokolne ilikindir. UDP deki datagram terimi mesaj tabanl bir almay anlatmak iin kullanlmtr. Stream haberlemesinde bilgiler bir bayt topluluu olarak alcya gelir. Alc gelen bilgilerden istedii kadarn elde edebilir. Hepsini okumak zorunda deildir. Gelen bilginin organizasyonunu ancak kendisi anlayabilir. Halbuki mesaj tabanl sistemde gelen bilgi paketlenerek gelmektedir. Alc taraf bunu belirlenmi bir grup olarak alabilir. phesiz TCP ve UDPnin her ikisinde de arka planda yine IP protokol kullanlarak paketli haberleme yaplmaktadr. Fakat bilgi kar tarafa ulatnda artk paketlemenin hibir nemi kalmamtr. rnein: Biz TCP protokol kullanarak bir miktar bayt gndermek isteyelim. Aslnda TCP, IP protokoln kullanarak bunu paketler halinde gnderecektir. Fakat gnderilecek bilgi tek bir IP paketine smayabilir. Bu durumda TCP protokol birden fazla IP paketi oluturarak bunu gnderir. Her IP paketinin ierisinde bir balk ksm vardr. Alc taraf, paketler deiik rotalardan gidebildii iin farkl sralardan alabilir. Alc taraf bir takm IP paketlerini almtr. Fakat TCP protokolnde bir TCP bal da vardr. Alc taraf TCP protokolnn yerletirdii bu bilgilere dayanarak paketleri birletirir ve nihayet gnderilmi olan bilgileri bir bayt topluluuna dntrr. te stream tabanl almalara karmzda nihayet bir bayt topluluu vardr. Kar taraf

157

3000 bayt gnderdii halde biz istediimiz kadar bayt okuyabiliriz. Fakat mesaj tabanl almada genel olarak bilgi kar tarafta toplandnda bir bayt topluluu olarak deil yine gruplanm bir biimde tutulur. Alc taraf bu grubu alabilmektedir. Ayrca TCP ve UDP protokollerinde artk bir de port numaras devreye girmitir. Buradaki port kavramnn, seri ve paralel portlarda olduu gibi fiziksel bir anlam yoktur. Port numaras hotsa gelen IP paketlerinin uygulama temelinde ayrtrlmas iin dnlmtr. Bir irketteki dhili numaralara benzetilebilir. IP protokol port numaras kavramn kullanmaz, dolays ile bu protokolde belli bir hosta gnderim yaplabilir. O host ierisindeki bir uygulamaya gnderim yaplamaz. rnein bir TCP bilgisi hosta ulam olsun. O host zerindeki pek ok program hosta gelen bilgiyi okumak isteyebilir. Peki, hangi program gelen bilgiyi elde edecektir? te daha gnderim srasnda TCP ve UDP protokollerinde gnderici bir port numaras da belirtmek zorundadr. te o hostta okuma yapan tm programlar aslnda bir port numaras eliinde okuma yaparlar. letim sistemi gelen tm TCP ve UDP paketlerini bir port numaras eliinde organize edip programlara datmaktadr. Toplam port numaras 65536 tanedir. lk 1024 port numaras uygulama katmanndaki yksek seviyeli protokollere ayrlmtr. rnein HTTP 80 numaral portu kullanmaktadr. rnein bir browser bir web sayfasna balanrken, TCP protokoln ve 80 numaral portu kullanmaktadr.

18.4. Client-Server alma Modeli

TCP balantl bir protokol olduu iin tipik olarak client-server bir alma modeli akla gelmektedir. Client-server alma modelinde bir server program bir ya da birden fazla client programlar vardr. Server program gerek ii yapan programdr. Client serverdan istekte bulunur, server ii yapp sonular gnderebilir. Bir server genellikle ayn anda birden fazla clienta hizmet verecek ekilde oluturulmaktadr. Peki, clientlar neden kendi ilerini yapmayp servera ihtiya duyuyorlar? Baz kaynaklar (veri tabanlar, yazclar) fiziksel olarak baz hostlara baldr, yada onlarn kontrol altndadr. Herhangi bir hostun o kaynaklar kullanabilmesi iin client-server modeli bir almaya gereksinim duyulur. rnein veri taban ynetim sistemleri tipik olarak client-server mimarisi ile tasarlanmtr. Biz veri taban ynetim sistemine bir sql

158

cmlesi gnderebiliriz. Veri taban ynetim sistemi pek ok client ile birlikte bize de hizmet verebilir. Ya da rnein printer bir hosta baldr. Biz client olarak bir sayfann yazlmasn ondan isteyebiliriz. Bazen byle bir mimari tamamen bir zorunluluk haline gelebilir. rnein bir ev terminali ya da bir ATM cihaz tm datalar kendi ierisinde bulunduramaz. O halde ATM cihazlar birer client program durumundadr. Server program merkezdedir. Baz durumlarda bir iletiime giren kiinin dierlerini tanyabilmesi gerekir. Bu tr durumlarda client-server alma zorunlu olarak kullanlr. Chat programlar bunlara tipik rneklerdir. Biz sisteme girdiimizde kimlerin bal olduunu bilemeyiz. Fakat server bunu bilebilir. rnein msn program byledir. Msn Messenger bir client programdr. Server a balanldnda server client n veri tabanna bakar ve onu contact listesinde kimlerin olduunu ve onlarn hangilerin online olduunu belirler ve client a mesajlar gndererek onlarn yeil gzkmesini salar. Kii sistemden karken bunu yine server a syler. Server kiinin contact listesindeki herkese mesaj gndererek client programlarn onlar offline gstermesini salar. Server programlarn alt hostlar zel ve gl donanmlara sahip olabilir. Client bu gten faydalanmak iin iini servera yaptrabilir. rnein bir sper bilgisayara balanp hzl bir hesab ona yaptrabiliriz. Cleint-server alma modeli datk uygulamalarda da kullanlmaktadr. Server ii datan program durumundadr ve burada adeta ters bir mantk iletilir. Server ii datarak client lara yaptrr.

18.5. Soket Arayz

IP protokol ailesi iletim sistemi tarafndan, iletim sisteminin bir paras olarak gerekletirilmi olmaldr. Yani iletim sisteminin ierisinde Ethernet kartn kontrol eden srcler, IP paketini oluturan, gnderip alan kodlar, TCP konumasn gerekletiren kodlar hep bulunmaktadr. Fakat bir biimde programc devreye girerek bu ileri yaptrmas gerekir. Nasl

159

iletim sistemlerinin APIleri varsa a haberlemesi iinde buna benzer APIler bulunmaldr. te a haberlemesi iin kullanlan API fonksiyonlarna soket arayz denilmektedir. Soket arayz pek ok protokol iin ortak fonksiyonlar bulunduran genel bir arayzdr. Yani biz soket fonksiyonlarn kullanarak IP protokol ailesinde ya da rnein AppleTalk ailesinde ayn fonksiyonlar ile alabiliriz. Tabi biz kursumuzda bu fonksiyonlar IP ailesi zerinde kullanacaz.

18.6. WinSock Arayz

Soket arayz ilk kez BSD/UNIX sistemlerinde gerekletirilmitir. Daha sonra pek ok sistemde benzer ekilde gerekletirilmitir. Microsoft, orijinal BSD soket arayzn Windows sistemlerine uyumlu hale getirmitir. Microsoftun Windows iin yazd bu soket arayzn WinSock denilmektedir. Microsoftun soket arayznde iki grup fonksiyon vardr. lki kk harflerle isimlendirilmi UNIX uyumlu fonksiyonlardr. kincisi WSA ile balayan Macar notasyonu ile isimlendirilmi soket fonksiyonlardr. WSA fonksiyonlar daha genitir ama tanabilir deildir. Burada, UNIX uyumlu fonksiyonlar kullanlacaktr.

18.6.1. WinSock Arayz in lk ve Son lemler

Windows soket sistemini proses temelinde balatmak iin ve ilemi sonlandrmak iin balangta ve bitimde iki fonksiyon arlmaldr. Bu arlarn UNIX grubu sistemlerde yaplmas gerekmemektedir. Bu arlar windows sistemine zgdr ve UNIX uyumlu fonksiyonlar kullansak bile bu arlar yapmak zorundayz.
Anahtar Notlar: Windows ta soket ilemleri iin, Winsock2.h isimli balk dosyas dahil edilmelidir. Ayrca, WinSock Ktphanesi Ws2_32.dll ierisindedir. Bu nedenle, link aamasnda Ws2_32.lib import ktphanesinin dahil edilmesi gerekir. Anahtar Notlar: Tipik bir TCP/IP client-server uygulama iin bir client bir de server program yazlmaldr. Visual Studio IDE sinde client-server programlar organize etmek iin, bo bir solution ap ierisine client ve server projeleri

160

dahil edilmesi iyi bir tekniktir. Bu ilem iki biimde yaplabilir. Birincisi, dorudan ilgili import ktphanesini projeye eklemektir. kincisi, Linkerdan dependicies blmne lib dosyas eklenir.

WinSock sistemini balatmak iin WSAstartup fonksiyonu kullanlr.


int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

Fonksiyonun birinci parametresi talep edilen WinSock versiyon numarasdr. Son versiyon 2.2 olduu iin bu talep yaplabilir. WORD tr iaretsiz 2 baytlk tamsay trdr. Bu iki bayt yksek anlaml bayt byk numara (major), dk anlaml kk numara biiminde girilir. kinci parametre WSADATA isimli bir yapnn adresini almaktadr. Fonksiyon baar durumunda 0 deerine, baarszlk durumunda hata deerine geri dner. WSAStratup fonksiyonu WSADATA yapsnn iini deerli bilgilerle doldurur. Fonksiyonun birinci parametresinde yksek bir WinSock numaras girilirse fonksiyon yine baarl olur ve sistemde ykl olan en yksek WinSock u kullanr. Fonksiyonun birinci parametresi tipik olarak MAKEWORD makrosuyla oluturulur. O halde fonksiyon tipik olarak yle arlabilir.
WSADATA wsd; int result;

if ((result = WSAStartup(MAKEWORD(2, 2), &wsd)) != 0) { fprintf(stderr, "Cannot load winsock library: %d\n", result); exit(EXIT_FAILURE); }

WinSock sisteminin program sonunda WSACleanup fonksiyonu ile boaltlmaldr. Fonksiyon baarl ise sfra, baarszsa SOCKET_ERROR deerine geri dner. Geri dn deerinin test edilmesine gerek yoktur.
int WSACleanup(void);

Anahtar Notlar: Pek ok soket fonksiyonu baarszlk durumunda SOCKET_ERROR deerine dner. Fakat ayrca baarszln nedenini elde etmek iin Windows sistemlerinde aadaki fonksiyon kullanlmaktadr. int WSAGetLastError(void)

161

Bu fonksiyon, son soket ilemindeki hatann nedenini anlatan bir sayya geri dner. Tm hata deerleri dzenli olarak WSA_XXX biimindeki sembolik sabitler olarak define edilmitir. UNIX sistemlerinde klasik olarak errno yntemi kullanlmaktadr.

18.7. Server Programnn Organizasyonu Server Programnn tipik olarak u aamalardan geilerek yazlr. 1. Dinleme soketi oluturulur. 2. Soket bind edilir. 3. Listen fonksiyonu ile soket dinleme konumuna geirilir. 4. Accept ilemi ile client balantlar kabul edilir. 5. Sent ve recieve fonksiyonlar ile gnderim ve alm yaplr. 6.Shut down ve closeSokect fonksiyonlar ile iletiim sonlandrlr. Windows sistemlerinde bu ilemler iin arlacak fonksiyonlar unlardr.

162

WSAStartUP socket bind listen accept Send/recieve Shut down Closesocket WSACleanup

18.7.1. socket Fonksiyonu

Soket arayz tipik bir handle almas sunmaktadr. Handle sistemini oluturan fonksiyon socket fonksiyondur. Kapatan closeSocket fonksiyonudur.
SOCKET socket(int af, int type, int protocol);

Fonksiyonun 1. parametresi kullanarak protokol ailesini belirtmektedir. Bu parametre iin AF_INET (PF_INET) kullanlr. kinci parametre, kullanlacak soketin stream mi datagram m olduunu anlatan tr parametresidir. TCP alma iin (TCP stream tabanl olduundan) bu

parametre SOCK_STREAM biiminde girilmelidir. UDP iin (mesaj tabanl) SOCK_DGRAM kullanlr. 3 parametre kullanlacak protokol ailesindeki spesifik protokol belirtmektedir. Aslnda IP ailesi iin bu parametrenin girilmesine gerek yoktur. 0 olarak geilebilir. Bu durumda ikinci parametre SOCK_STREAM ise TCP, SOCK_DGRAM ise UDP alma sz konusudur. Fakat 163

yine de 0 yerine IPPROTO_TCP ya da IPPROTO_UDP geilebilir. Baar durumunda SOCKET tr ile temsil edilen handle durumuna geri dner. Fonksiyon baarszlk durumunda SOCKET_ERROR deerine geri dnmektedir. WSAGetLastError ile hatann nedeni alnabilir. Bu durumda, tipik olarak TCP/IP alma iin soket yle oluturulabilir.
SOCKET serverSocket; /******* **** *******/ if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { fprintf(stderr, "can not create"); exit(-1); }

Server program soketi oluturduktan sonra balamaldr. Soketi oluturduktan sonra hangi network kartndan ve hangi porttan gelecek balant isteklerinin kabul edileceini belirlemek iin yaplr.

18.7.2. bind Fonksiyonu Prototipi yledir.


int bind(SOCKET s, const struct sockaddr *name, int namelen);

Birinci parametre soket fonksiyonundan elde edilen handledr. Programc bir yapnn iini doldurarak bunun adresini ikinci parametre olarak gemelidir. Fonksiyon prototipindeki struct sockaddr, tm protokoller iin ortak olan bir yapy belirtmek iin kullanlmtr. Aslnda her protokoln ayr bir yaps vardr. rnein TCP/IP iin socaddr_in isimli yap kullanlmaktadr. Yani bind fonksiyonunun ikinci parametresi void * olabilirdi. phesiz biz sockaddr_in yapsnn iini doldurduktan sonra adresi dntrerek fonksiyona vermeliyiz. Bind fonksiyonu ikinci parametrede aslnda hangi yapnn adresi verildiini nc parametreden anlamaktadr. nc

164

parametreye ikinci parametreye geilen yapnn bayt uzunluu girilmelidir. Bind fonksiyonu baar durumunda sfr, baarszlk durumunda SOCKET_ERROR deerine dner ve baarszln nedeni WSAGetLastError fonksiyonu ile elde edilebilir. imdi sockaddr_in yapsnn iinin doldurulduunu varsayalm. bind fonksiyonunu yle armalyz.
struct sockaddr_in sinServer; /***/ if (bind(serverSocket, (struct sockaddr *) &sinServer, sizeof(sinServer)) == SOCKET_ERROR) { fprintf(stderr, "Cannot bind socket: %d\n", WSAGetLastError()); exit(EXIT_FAILURE); }

sockaddr_in yaps aadaki gibi bildirilmitir.

struct sockaddr_in { short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; };

Kullanc bu yapy doldurmaldr. sin_family elemanna protokol ailesi girilir. (TCP iin) AF_INET girilir. Yapnn sin_port elemanna balantnn kabul edilecei port numaras girilir. Yapnn sin_addr eleman in_addr isimli bir yap trndendir. Bu elemana, dinlemenin yaplaca netwotk kartnn IP numaras girilmelidir. Fakat, zel olarak INADDR_ANY deeri hosta bal tm netwok kartlarn belirtmektedir. Sin_zero eleman kullanlmaktadr. Tipik olarak bu elemanda sfr deerleri bulunur. Bu eleman bo braklabilir. IP ailesinde dikkate alnmamaktadr. Genel olarak protkoller hetreojen makinelarn birbine balanmasnda kulklanldndan endian lk durumu sorun oluturabilir. rnein port numaras Intel ilemcilerinde little, alfa ilemcilerinde big endian olarak kodlanrsa sorun oluur. te protokol ailesinde genel olarak bir byte tan uzun olan tm saylar iin ortak bir endian seilmelidir. te IP ailesinde big endian notasyon kullanlmaktadr. Bu nedenle protokol numaras, IP numaras gibi saylarn hepsi big endian formata dntrlmelidir. Bu dntrmeyi yapan htons ve htonl fonksiyonlar vardr. htons (host to network byte oridiren short) short deeri dntrmer iin, htonl (host to network

165

byte oridiren long) long deeri dntrmek iin kullanlr. O halde, tipik olarak sockaddr_in yapsnn ii yle doldurulmaldr.

struct sockaddr_in sinServer; sinServer.sin_family = AF_INET; sinServer.sin_port = htons(PORTNO); sinServer.sin_addr = htonl(INADDR_ANY);

bind ileminden sonra, artk socket dinleme durumuna getirilmelidir. Bu ilem listen fonksiyonu ile yaplr.

18.7.3. listen fonksiyonu Fonksiyon prototipi yledir.


int listen(SOCKET s, int backlog);

Fonksiyonun birinci parametresi soketin handle deeri. kinci parametresi bekleme kuyruunun uzunluunu belirtir. Client lar tarafndan yaplan balant istekleri bir kuyruk sisteminde saklanr. Accept fonksiyonu kuyrukta srada bulunan balant isteini alarak pnu kabul eder. rnein, server accept fonksiyonunu armadan farkl client balanma isteinde bulunuyor olsun. Bu balant istekleri bir kuyrukta saklanr. Tabi ki bir zaman am periyodu vardr. Daha sonra accept uygulandnda, kuyruktaki sraya gre balant alnr. te ikinci parametre bu kuyruun uzunluunu belirtmektedir. Mesela 8 deeri uygun bir deerdir. Fonksiyon baarlysa sfr deerine, baarszsa SOCKET_ERROR deerine dner. WSAGetLastError ile hatann nedeni alnabilir. Listen fonksiyonu tipik olarak aadaki gibi arabilir.
if (listen(serverSocket, 8) == SOCKET_ERROR) { fprintf(stderr, "Cann not listen"); exit(-1); }

166

Listen fonksiyonu arldnda artk iletim sistemi network kartna gelen paketleri kontrol eder ve balant isteklerini belirleyerek kuyruklar. Yani listen fonksiyonu bu ilemi balatmaktadr, aktif dinlemeyi iletim sistemi yapmaktadr. Ak listen da beklememektedir. Artk balanty kabul etme zaman gelmitir. Accept fonksiyonu arlarak balantlar kabul edilebilir. phesiz bir server birden fazla client balantsn kabul edebilir. Yani accept fonksiyonu bir kez arlmak zorunda deildir. Her arldnda yeni bir balant kabul edilir. O halde ok clientli uygulamalar iin tipik olarak, accept fonksiyonu bir dng ierisinde birden fazla kez arlmaldr.

18.7.4. Accept Fonksiyonu

Blokeli ve blokesiz modda kullanlabilir. Default durum blokeli moddur. Blokesiz mod ilemleri hakknda genel bilgiler verilecektir. Blokeli modda accept fonksiyonu arld zaman, ak accept fonksiyonu ierisinde kalr. Ta ki bir client balants kabul edilene ya da socket kapatlana kadar. Yani accept arldnda eer zaten connect isteinde bulunan bir client varsa, accept bu balanty kabul ederek hemen geri dner. Yoksa, accept bir client connect uygulayana kadar bekler. Accept fonksiyonu ile balant kabul edildiinde fonksiyon yeni bir soket geri verir. Bu soket balanlan client ile konumakta kullanlr. Balant salamak iin kullanlan soketle, balant kabul edildikten sonra elde edilen soket farkldr. Accept fonksiyonu baarszlk durumunda INVALID_SOCKET deeri ile geri dner. Baarszln nedeni WSAGetLastError fonksiyonu ile elde edilebilir. INVALID_SOCKET -1 olarak define edilmitir. Fonksiyon prototipi yledir.
SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen);

Birinci parametre, dinleme soketinin handle deerini alr. kinci ve nc parametreler balantdan sonra client bilgilerini ierecek biimde doldurulur. Yani, balanlan client e ilikin sockaddr_in yaps, buraya doldurulmaktadr. IP ailesinde bu parametre tipik olarak client in IP adresinin elde edilmesi iin kullanlr. nc parametre, IP ailesi iin sockaddr_in yapsnn sizeof deerini tutan int trden bir nesnenin adresi biiminde girilmelidir. Son parametre NULL geilebilir. Bu durumda kar tarafa ilikin bir bilgi edinilmez. Fonksiyonun geri dn deeri

167

kabul edilen client a ilikin, onunla konumak iin gereken soket deeridir. Fonksiyon tipik olarak yle arlabilir.
int addrsize; SOCKET clientSocket; struct sockaddr_in sinClient; addrSize = sizeof(sinClient); if (clientSocket = accept(serverSocket, (struct sockaddr *)&sinClient, &addrSize)) == INVALID SOCKET) { fprintf(stderr, "Can not accept: %d\n", WSAGetLastError()}; exit(-1); }

Accept fonksiyonu birden fazlaca arlarak farkl clientlarla balantlar kabul edilebilir. Artk accept ileminden sonra, balant gereklemitir. Client ile server send ve receive fonksiyonlar ile full duplex haberleme yapabilirler.

18.8. Client Programn Organizasyonu

Client tpk telefonda arama ileminde olduu gibi, servrein IP adresini bilerek ona balanmaya alr. Balant sonrasnda server balanlan clientn IP adresini elde edebilmektedir. Client programn srasyla unlar yapmas gerekir.

168

WSAStartUP socket connect listen

Send/recieve Shut down Closesocket WSACleanup

Grld gibi client nce bir soket yaratr. Sonra o soketle connect fonksiyonunu ararak server a balanmak ister.

18.8.1. Connect Fonksiyonu connect fonksiyonunun prototipi yledir.

int connect(SOCKET s, const struct sockaddr *name, int namelen);

Birinci parametresi yaratlan soketi alr. kinci parametre IP ailesi iin sockaddr_in trnden bir yapnn adresi olarak girilmelidir. Client servern IP adresini bu yapnn ierisine yerletirir. nc parametre yine ikinci parametre ile girilen yapnn uzunluudur. Baar durumunda 0 deerine, baarszlk durumunda SOCKET_ERROR deerine dner. Baarszln nedeni WSAGetLastError fonksiyonu ile elde edilebilir.

169

18.8.2. Server IP adresini sockaddr_in yapsna yerletirilmesi

Client connet fonksiyonunu armadan nce, sockaddr_in trnden bir yap nesnesi tanmlayp bunun iini doldurmaldr. Bu yapnn sin_famlily ve sin_port elemanlar server da olduu gibi AF_INET ve PORTNO(server port numaras) ile doldurulmaldr.
struct sockaddr_in sinServer; sinServer.sin_family = AF_INET; sinServer.sin_port = PORTNO;

Sra IP adresinin yerletirilmesine gelmitir. Anmsanaca gibi, sockaddr_in yapsnn sin_addr eleman struct in_addr isimli yap trndendir. In_addr yaps i aadaki biimdedir.
struct in_addr { union { struct {UCHAR s_b1, s_b2, s_b3, s_b4} S_un_b; struct {USHORT s_w1, s_w2} S_un_w; ULONG s_addr; }S_un; };

Grld gibi yapnn S_un eleman bir birlik trndendir. O birliin s_addr eleman IP adresini bir long deer olarak alr. Birliin dier elemanlar IP adresini dier formatlarda almaktadr. O halde eer IP adresi long bir sayya dntrlrse yle girilebilir.
sinServer.sin_addr.S_un.S_addr = htonl(<ip adresi>);

Aadaki gibi bir makro bulunmaktadr.


#define s_addr S_un.S_addr

Bu durumda ifade u ekilde de yazlabilir.


sinServer.sin_addr.s_addr = htonl(<ip adresi>);

Fakat IP adresinin long bir say biiminde girilmesi pek kullanl deildir. Genellikle byte byte noktal biimde tutulmaktadr. rnein; 88.235.101.131

170

te inet_addr isimli fonksiyon noktal biimde verilen IP adresini long biime dntrmektedir.
unsigned long inet_addr(const char *cp);

Eer yaznn format uygun deilse, fonksiyon INADDR_NONE deerine geri dner. O halde IP adresini yle de yerletirebiliriz.
sinServer.sin_addr.s_addr = inet_addr("88.235.101.131"); if (sinServer.sin_addr.s_addr == INADDR_NONE) { /*******/ }

simler daha kullanl olduundan, IP numaralarnn isimlerle eletirilmesi yoluna gidilmitir. Bir isme karlk hangi IP numarasnn geldii, global internet anda eitli serverlar da tutulmaktadr. Programc, ilgili serverlardan sorarak, isme ilikin IP adresini elde edebilir. Bu hizmete Domain Name System (DNS) denilmektedir. Benzer biimde yerel bir ada alyorsak bu durumda domain isimleri bilgisayar ismi biimindedir ve yerel a tarafndan zlr. Host ismini IP numarasna dntrmek iin gethostbyname fonksiyonu kullanlr.
struct hostent * gethostbyname(const char *name);

Fonksiyon host ismini alr ve static dzeyde tahsis edilmi olan bir hostent yapsnn adresi ile geri dner. Hostent ysps yledir.
struct hostent { char *h_name; char **h_aliases; short h_addrtype short h_length; char **h_addr_list; };

Yapnn hname eleman, host ismini iermektedir. H_aliases host isminin alternatif isimlerini belirten bir dizidir. Grld gibi bir hosta bal birden fazla isim bulunabilir. H_addrtype elde edilen host adresinin trn belirtir. H_lengt host adresinin IP adresinin byte uzunluunu belirtmektedir. H_addr_list host adreslerini gsterir. Bir host ismine kar birden fazla IP adresi gelebilir (rnein www.google.com host ismine bal pek ok IP adresi vardr)

171

h_addr_list

NULL

Tipik uygulamalarda client hem IP adresiyle, hem de host ismiyle balant yapabilecek biimde tasarlanr. Bunun iin klasik kullanlan yntem udur.
char hostname[] = "www.google.com"; sinServer.sin_addr.s_addr = inet_addr(hostname); if (sinServer.sin_addr.s_addr == INADDR_NONE) { host = gethostbyname(hostname); if (host == NULL) { fprintf(stderr, "Unable to resolve server: %s\n", HOSTNAME); exit(EXIT_FAILURE); } memcpy(&sinServer.sin_addr.s_addr, host->h_addr_list[0], host->h_length); }

18.8.3. Send ve Receive lemleri

Send ve receive ilmeleri tipik olarak blokeli ve blokesiz modda yaplabilir. Defult mod blokelidir. Dolaysyla burada send ve receive fonksiyonlarn blokeli moddaki davran ele alnacaktr. Modern sistemlerde hosta IP paketi geldiinde sistem bunu deerlendirerek gelen bilgiyi uygun biimde tamponlar. Benzer biimde bilgi gnderilirken de nce tampona alnmakta, sonra uygun zamanda etkin biimde gnderilmektedir. Bylece okuma iin receive fonksiyonunu ardmzda daha nce gelmi ve network tamponunda bekletilmi olan bilgiyi okuyabiliriz. Send ilemi de byle yrtlmektedir. Blokeli modda receive network tamponunda okunacak hi bir byte yoksa, yeni bir byte gelene kadar blokede bekler. Fakat en az bir byte varsa receive okuyabildii kadar byte I okur. Bloke olumaz. rnein biz receive fonksiyonu ile 100 byte 172

okumak isteyelim. Eer tamponda byte yoksa ak receive ierisinde bekler. Diyelim ki hosta yeni bir 50 byte gelmi olsun. Receive 100 byte n hepsini oukyana kadar beklemez. Bu 50 byte okuyarak baarl biimde geri dner. Ayn davran send fonksiyonunda da byledir. send fonksiyonu nce bilgileri network tamponuna yazar. Belli bir sre sonra bilgi gerek anlamda paketlenerek gnderilir (IO scheculing). Blokeli modda send fonksiyonu network tamponu dolu olduu iin hibir byte tampona yazamazsa blokede bekler. En az bir byte tazldnda bloke zlr. rnein biz 100 byte lk bir bilgiyi send fonksiyonu ile gndermek isteyelim fakat network tamponu dolu olsun. Ak send fonksiyonu ierisinde bekler. Tamponda 10 bytelk yer aldn dnelim. send 100 byte I yazana kadar beklemez. 10 byte yazp geri dner. send ve receive fonksiyonlarnn prototipi yledir.
int send(SOCKET s, const char *buf, int len, int flags); int recv(SOCKET s, char *buf, int len, int flags);

Birinci parametreler haberleme soketini belirtir. Ikinci parametreleri transfer edilecek bilginin bulunduu bellek adresi. nc parametre aktarlacak bilginin byte uzunluudur. Son parametre gnderim ve alm srasndaki baz belirlemeler iin kullanlr. zel bir belirleme de bulunulmayacaksa 0 girilmelidir. Fonksiyonlarn geri dn deerleri, gnderilen ve alnan byte miktardr. Eer kar taraf soketi kapatmsa receive fonksiyonu 0 deerine dner. Dier problemlerde receive fonksiyonu SOCKET_ERROR deerine dner. Benzer biimde send fonksiyonu kar taraf soketi kapatmsa ya da hata durumunda SOCKET_ERROR deerine dner. Bu sistemde, 100 byte okunmak istensin. Receive fonksiyonunu bir kez aramayz. Bir dng ierisinde birden fazla kez armak gerekir. Klasik algoritma yledir:
int read_socket(SOCKET s, void *pBuf, int n) { int result; int index = 0; int left = n; while (left > 0) { result = recv(s, (char *) pBuf + index , left, 0); if (result == 0) return index; if (result == SOCKET_ERROR) return SOCKET_ERROR; index += result; left -= result; }

173

return index; }

Grld gibi fonksiyon n byte okumadan geri dnmemektedir. Fonksiyonun geri dn deeri soket hatas olutuunda ya da kar taraf n byte okuyamadan soketi kapattnda n den farkl olabilir. Send fonksiyonu da benzer biimde yazlabilir.
int WriteSocket(SOCKET s, const void *pBuf, int n) { int result; int index = 0; int left = n; while (left > 0) { result = send(s, (const char *) pBuf + index , left, 0); if (result == 0) return index; if (result == SOCKET_ERROR) return SOCKET_ERROR; index += result; left -= result; } return index; }

18.8.4. Soketin Kapatlmas Soketi kapatmak iin kullanlan closeSocket fonksiyonu alterin kapatlmas gibi an bir kapatma etkisi yapmaktadr. Biz closeSocket uyguladktan sonra artk soketi kullanamayz. Soket kapatldktan sonra artk tampon da boaltlr. Tampona gelmi olan, fakat henz okunmam olan bilgiler okunamaz. Benzer biimde send fonksiyonu ile tampona yazlan bilgiler closeSocket den sonra artk kar tarafa gnderilmez. Ite bu durumu dikkate alarak soketin iyi biimde (graceful) kapatlmas salk verilir. Bunun iin shut down fonksiyonu kullanlmaktadr. Shut down fonksiyonunun prototipi yledir:
int shutdown(SOCKET s, int how);

Fonksiyonun birinci parametresi soketin handle deeri, ikinci parametresi unlardan biri olabilir:
SD_SEND SD_RECEIVE SD_BOTH

174

kinci parametre SD_SEND geilirse artk gnderme ilemi yaplamaz fakat network tamponuna gelmi olan bilgiler recv fonksiyonu ile okunabilir ve tampondaki bilgilerde gnderilebilir. SD_RECEIVE kullanlrsa artk alma ilemi yaplamaz fakat gnderme ilevi yaplabilir. SD_BOTH her ikisinin de yaplabilecei anlamndadr. En ok kullanlan deerdir. Bu ilem kar tarafla balanty normal olarak sonlandrr. Network tamponundaki bilgilerin gnderilmesine yol aar. Eer soket kapanmadan nce tm mesajlamalar bitirildiyse bu parametre SD_BOTH biiminde geilebilir. Kii gnderme ilemini bitirdikten sonra tampondakileri okumak isterse bu parametreyi SD_SEND olarak geebilir. shutdown fonksiyonu IP haberlemesinin sonlandrlmas iin gereken bir takm ilemleri dzenli olarak yapmaktadr.

18.9. Client-Server Uygulamalarda Dzenli Bilgi Gnderilip Alnmas

Client-Server haberlemelerde client serverdan pek ok istekte bulunabilir, serverda client a eitli bilgiler iletebilir. rnein IRC stili bir chat uygulamasnda bir client servera balandnda servera bir nick eliinde bir nick(takma ad) yollar. Server bunu kendi listesi iinde tutar, sonra client bir mesaj yazdnda serverdan bu mesaj herkese datmasn ister. Sonra client sistemden kmadan nce bu istei servera iletir. Server kendi listesinden client siler. Serverda clienta mesajlar gndermektedir. rnein yeni birisi sisteme girdiinde server btn clientlara mesaj gndererek bu kiiyi eklemesini ister. Server bir client dan mesaj geldiinde, bunu gstermesi iin tm clientlara mesaj gnderir. Benzer biimde disconnect ileminde serverdan clientlara mesaj gnderilmektedir. O halde client-server uygulamalarda, client ile server arasndaki tm haberleme iin hangi bilgilerin gnderilip alnaca batan belirlenmelidir. Mesajlar genellikle deiken uzunlukta olma eilimindedir. Client dan servera, serverdan clienta gnderilen mesajlar iin genel olarak sabit uzunlukta bir balk ksm ve deiken uzunlukta bir ierik ksm bulundurulabilir. rnein:

175

Mesaj ID Uzunluk

4 Balk Ksm 4

Mesaj Datas (Deiken Uzu.)

Bu durumda client yada server nce porttan recv fonksiyonu ile balk ksm kadar bilgiyi (rnein 8 bayt) okur. Balk ksmndaki uzunlua bakarak porttan o kadar bilgiyi daha okur. Bylece tm mesaj elde etmi olur. Mesaj verisinin format mesajn IDsine baldr. Rahat bir alma iin her mesaja karlk bir yapnn bulundurulmas uygundur. Mesaj bal gibi bir yap ile temsil edilebilir:
typedef struct tagMSGHEADER { DWORD id; DWORD length; } MSGHEADER;

imdi gnderilen tm mesajlara birer ID verelim:


enum MSGIDS { MSG_CTS_CONNECT, MSG_CTS_SENDMESSAGE, MSG_CTS_DISCONNECT, MSG_STC_CONNECT, MSG_STC_DISCONNECT, MSG_STC_SENDMESSAGE, ... };

imdi her mesaj iin ayr bir yap oluturulabilir. rnein client servera balanacaksa ona bir nick name verebilir. phesiz byk uygulamalarda ok karmak mesajlar sz konusu olabilir. imdi de rnek oluturmak amacyla clientn servera gnderdii mesajlarn serverda ilenmesine bir rnek verelim:

176

MSGHEADER msgHeader; int result; for (;;) { result = read_socket(client Socket, &msgHeader, sizeof(msgHeader)); if (result == 0) break; switch (msgHeader.id) { case MSG_CTS_CONNECT: /****/ break; case MSG_CTS_SENDMESSAGE: /****/ break; case MSG_CTS_DISCONNECT: /****/ break; } }

Mesajn IDsi belirlendiine gre nce veya sonra mesaj uzunluu kadar bilgiyi soketten okuyarak ilevimizi yapabiliriz. Bazen client ve server programlar biz yazmayz da zaten mevcut bir sistem iin client yazmak isteriz. Bunun iin phesiz client ile server arasndaki tm mesaj trafii ayrntlar ile bilinmelidir.

18.10. ok Clientli Uygulamalar

Tipik bir server program birden fazla cliente hizmet verebilecek biimde tasarlanr. Buradaki en nemli problem bir client ile urarken bloke olumas ve dier clientlere hizmet verilememesidir. rnein server baland 10 clientin soket handlelarn bir dizide tutuyor olsun. Bir dng ierisinde server 10 clientin soketinden de mesaj okumaya alrsa recv fonksiyonu blokeli modda beklemeye yol aabilir. Bu durumda bir clientteki bekleme dier clientleri etkilemektedir. te bu problemi zmenin tipik olarak iki yolu vardr: 1. Ak oluturma yntemi: Bu yntemde server blokeli modda almaya devam eder, fakat her bir client balantsnda ayr bir ak oluturarak (tipik olarak bir thread) o clientle o ak ierisinde konuur. Bylece o ak bloke olsa bile dier aklar bu olaydan etkilenmez. Bu yntem

177

basit olmasna karn ok fazla sayda client iin kullanszdr. nk her yeni client iin bir ak oluturulduunda fazla miktarda sistem kayna kullanlmaktadr. 2. Etkin yoklama yntemi: Bu yntemde soketler blokeli moddan kartlr. Bylece send ve recv fonksiyonlar blokeye yol amazlar. Bu yntemde server rnein o dng ierisinde srekli 10 sokete recv fonksiyonunu uygular. Her client iin ayr bir tampon oluturur. Hangi clientten bilgiyi okuduysa onun tamponuna bilgiyi ekler. Bilgi istedii noktaya geldiinde ileme sokar. Fakat bu yntem megul bir dng (busy loop) oluturarak CPUyu gereksiz bir biimde megul etmektedir. te iletim sistemleri bu tr durumlarda uygulanacak baz yntemler oluturmulardr. Bu yntemlerde en ok kullanlanlardan biri select modelidir. Select modelinde iletim sistemi tarafndan salanan select isimli bir fonksiyon vardr. Select fonksiyonu bir grup soketi parametre olarak alr ve bunlar izlemeye alr. Eer hibir sokete bilgi gelmemise select threadi izelge dna kartr. Bylece CPU zaman harcamadan etkin bekleme durumu oluur. Soketlerden en az birine bilgi geldiinde iletim sistemi bunu fark eder ve threadi yeniden izelgeye yerletirir ve select fonksiyonu sonlanr. Select fonksiyonundan kldnda programc hangi sokete bilgi geldiinden dolay fonksiyondan kldn sorgular. Hangi sokete bilgi geldiyse o sokete recv fonksiyonu uygulanr ve yeniden select fonksiyonuna girilir.

Windows sistemlerinde select modelinden ziyade asenkron modeller daha ok tercih edilmektedir. rnein IO Completion port denilen asenkron yntem ok tercih edilmektedir ve .NET ve Java platformlar arka planda modern Windows sistemlerinde bu mekanizmay kullanmaktadr. Bu yntemde programc ilevi balatr. Hem ak devam eder, hem de arka planda iletim sistemi ilemi yapar. lem bitince iletim sistemi programcnn belirledii bir fonksiyonu arr.

178

19. THREADLER
Bir prosesin ayn adres alanndaki farkl aklarna thread denilmektedir. Threadli sistemler ilk olarak 80li yllarda gerekletirilmeye balanm fakat ciddi anlamda 90l yllarda yaygnlamtr. Bugn Windows, Unix/Linux, MacOSX gibi sistemlerin hepsi thread zelliine sahiptir. Bu sistemlerde her proses bir veya birden fazla thread akndan oluur. Proses almaya tek bir akla yani threadle balar. Bu ana thread main fonksiyonunun balad aktr. Dier threadler alma zaman srasnda fonksiyonlarla oluturulur. Her thread ak sanki bir bamsz bir programm gibi iletim sistemi tarafndan dierlerinden bamsz izelgelenmektedir. Windows ve Linux iletim sistemleri thread temelinde izelgeler uygulamaktadr. Bu sistemde thread hangi sisteme ilikin olursa olsun izelgeleme bakmndan sistemde prosesler yoktur, threadler vardr. rnein:

P1 . Sis. P2

T1 T2

T1

P3

T1 T2 T3

Her bir kuanta sresi bittiinde almakta olan threade ara verilir, bekleyen dier threade geilir. Geilen thread ya ayn prosesin threadidir ya da farkl bir prosesin threadidir. Genel olarak ayn prosesin threadleri arasndaki gei daha hzldr.

179

19.1. Threadli almann Avantajlar

1. Arka planda yoklama yntemiyle izlenmesi gereken olaylarn sz konusu olduu durumlarda threadler organizasyonu ok kolaylatrmaktadr. rnein hem bir porttan gelen bilgileri hem alp hem de baka bir eyleri yapacamz dnelim ya da rnein programmz ekrann sa st kesine canl bir saat karacak olsun. te threadli sistemlerde bir thread oluturulur, bu arka plan olaylar threade braklr, dier ak normal bir biimde devam eder. 2. Threadler, blokeden dier aklarn etkilenmemesi iin youn olarak kullanlmaktadr. rnein on soketten bilgi okumak iin threadli model kullanlabilir. Bylece recv fonksiyonu bir sokette bloke olsa bile dier threadler almaya devam etmektedir. 3. Threadler paralel programlama ya da datk algoritmalarn gerekletirilmesi amacyla da kullanlmaktadr. rnein biz bir iin bamsz paralarn, seri olarak deil de ayn anda paralel olarak yaptrabilirsek daha hzl bir alma sz konusu olur. CPUdan ektiimiz toplam zaman artacaktr. phesi tek CPUlu ya da tek ekirdekli sistemlerde gerek bir paralel alma sz konusu olmaz. Fakat yine de bir hz kazancnn salanaca aikrdr.

19.2. Threadlerin Bellek Alanlar

Bir prosesin tm threadleri ayn veri ve heap alann kullanmaktadr. Yani rnein bir thread global bir deikene bir deer yazsa, dier thread bu deeri grebilir. Fakat threadlerin stackleri birbirinden ayrlmtr. Her bir threadin ayr bir stacki vardr. Yerel deikenler ve parametre deikenleri stackde oluturulduuna gre her thread ak yerel deikenlerin farkl bir kopyasn kullanyordur. rnein 2 farkl thread ayn fonksiyon zerinde ilerlerken deikenler birbirine karmaz. Kod ayndr. Fakat her thread yerel deikenlerin o threade zg kopyasn kullanmaktadr. phesiz statik yerel deikenlerde data blmnde oluturulduu iin threadler arasnda tpk global deikenler gibi paylalr.

180

19.3. Threadler zerinde lemler

Thread mekanizmas iletim sisteminin proses yneticisinin kontrol altndadr. Modern iletim sistemlerinde thread oluturmak iin ve threadleri ynetebilmek iin eitli sistem fonksiyonlar vardr. rnein Windows iletim sisteminde Kernel32.dll ierisinde bulunan bir grup API fonksiyonu ile thread ilemleri yaplmaktadr. Linux sistemlerinde threadler yine klasik fork ilemi ile oluturulur. Fakat fork ilemi srasnda bellek kopyalamas yaplmaz. Bylece adeta ayn bellek alannda alan iki farkl proses biiminde thread oluturulmaktadr (lightweight process). Fakat Linux sistemlerinde, Windowsta olduu gibi sistem fonksiyonlarn dorudan ararak thread ilemlerini yapmak ok zor olduu iin bu sistemlerde thread ilemleri iin eitli ktphaneler kullanlmaktadr. pthread ktphanesi diye bilinen ktphane ok yaygndr ve POSIX standartlar tarafndan desteklenmektedir.

19.4. Windows Sistemlerinde Thread lemleri

Windows sistemlerinde thread ilemleri iin API fonksiyonlar kullanlmaktadr. Windows API fonksiyonlarnn byk blmnn prototipleri windows.h ierisinde bulunmaktadr.

19.4.1. CreateThread Fonksiyonu

Thread yaratmak iin CreateThread API fonksiyonu kullanlmaktadr. Fonksiyonun prototipi ierisinde windows.h ta typedef edilmi olan bir ok tr ismi bulunmaktadr.
HANDLE CreateThread { LPSECURITY_ATTRIBUTES IpThreadAttributes, SIZE_T dwStacksSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId };

Fonksiyonun birinci parametresi thread kernell nesnesinin gvenlik bilgilerini belirtir. Bu parametre security attributes denilen bir yapnn adresini alr. Bu parametre NULL geilebilir. Bu

181

durumda gvenlik uygulanmaz. Fonksiyonun ikinci parametresi threadin stack uzunluunu belirtmektedir (SIZE_T unsigned int biiminde typedef edilmitir.). Bu parametre 0 geilirse, bu durumda PE (portobal executable) formatnda belirtilen stack uzunluu alnr. PE formatn linker oluturduu iin bu deer linker seeneklerinden ayarlanabilmektedir. Microsoft linkerlar default olarak 1MB deerini yazmaktadr. O halde bu parametreyi 0 geersek default stack 1MB uzunluunda olacaktr. Fonksiyonun nc parametresi thread aknn balatlaca fonksiyonun adresini almaktadr. LPTHREAD_START_ROUTINE aadaki gibi bir typedef ismidir.
typedef DWORD (__stdcall * LPTHREAD_START_ROUTINE)(void *);

Yani thread fonksiyonunun geri dn deeri DWORD, parametresi void * olmak zorundadr.
Anahtar Notlar: windows.h ierisinde BYTE, WORD, DWORD srasyla, 1,2,4 baytlk iaretsiz tamsay trlerini belirtir. Trn nne p yada lp eki getirilirse adres tr anlalr. pc ya da lpc gsterdii yer const olan adrestir. Ba h ile balayan typedef isimleri void * anlamna gelmektedir. Anahtar Notlar: Fonksiyonun geri dn deeri ile ismin arasna getirilen anahtar szcklere fonksiyon belirleyicileri (function specifiers) denilmektedir. Standartlarda fonksiyon belirleyicileri diye bir konu yoktur. Fonksiyon belirleyicileri eklenti biiminde bulunmaktadr. __stdcall, __pascal, __cdecl Intel sisteminde pek ok derleyicinin kulland belirleyicilerdir. Bu belirleyicilere fonksiyon arma biimi (call convention) denilmektedir. Microsoft derleyicilerinde default durum __cdecl biimindedir. Yani hibir ey yazmamakla __cdecl yazmak ayn anlamdadr. Thread fonksiyonlarnn __stdcall arma biimine sahip olmas zorunludur.

CreateThread fonksiyonunun 4. parametresi thread fonksiyonuna gnderilecek parametredir. Fonksiyonun 5. parametresi olan dwCreationFlags yaratlan threade ilikin baz belirlemelerin yaplmas iin kullanlr. rnein bu parametre CREATE_SUSPENDED biiminde geilebilir. Bu durumda thread yaratlr fakat ResumeThread fonksiyonu uygulana kadar almaz. Bu parametre 0 olarak geilebilir. Bir threadin handle ve ID deeri vardr. CreateThread threadin handle deeri ile geri dner. te fonksiyonun son parametresi DWORD bir nesnenin adresini alr, ID deeri oraya yerletirir. Baz fonksiyonlar bizden handle deerini baz fonksiyonlar ise ID deerini ister. CreateThread fonksiyonu, baar durumunda threadin handle deerine, baarszlk durumunda NULL deerine geri dner.

182

Anahtar Notlar: Konsol ekrannn herhangi bir yerine cursor den bamsz olarak yazy basan fonksiyon yle yazlabilir: void Writes(int row, int col, const char *str) { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); DWORD dw; COORD coord; coord.X = col; coord.Y = row; WriteConsoleOutputCharacter(hStdout, str, strlen(str), coord, &dw); }

19.4.2. Threadlerin Sonlandrlmas

Bir threadin sonlandrlmas eitli biimlerde gerekletirilebilir: 1. Thread fonksiyonu sonlandnda threadte sonlanm olur. Herhangi bir thread ak ExitThread API fonksiyonu ile arlrsa thread sonlanr.
void WINAPI ExitThread(DWORD dwExitCode);

Ana threadin dier threadlerden hibir ayrcal yoktur. Yani ana thread sonland halde dier threadler almaya devam edebilir. Fakat bir prosesteki son threadte sonlandnda proses otomatik olarak sonlandrlr.

2. Prosesi sonlandran standart exit fonksiyonu Windows sistemlerinde ExitProcess sistem fonksiyonunu, Unix/Linux sistemlerinde _exit sistem fonksiyonunu ararak sonlandrma yapmaktadr. Bir proses sonlandnda tm threadlerde otomatik olarak sonlandrlmaktadr. Main fonksiyonu bittiinde exit ilevi uyguland iin btn threadlerde sonlanacaktr.
Anahtar Notlar: Sample.c kaynak dosyasn bir projeye ekleyip build ilemi yapm olalm. Sample.c dosyas derlenerek sample.obj haline getirilecek ve link ilemi yaplacaktr. Fakat derleyici link aamasnda sample.obj dosyas yan sra ismine start up module denilen ve genellikle crt0.obj biiminde bulunan bir dosyay da link ilemine sokmaktadr. Gerek programn balang noktas bu dosyann ierisindedir ve main fonksiyonu da aslnda buradan arlmaktadr. Yani C programnda ilk altrlan kod main deildir. Derleyicinin balang kodudur. /******

183

******* *******/ call _main call _exit /****** ******* *******/ Derleyicinin balang kodu gerekli pek ok ilemi yapmaktadr. rnein komut satr argmanlar, bu balang kodu tarafndan main fonksiyonuna aktarlmaktadr. Anahtar Notlar: Main fonksiyonunda hi return uygulanmazsa main fonksiyonuna zg olarak 0 ile return edildii varsaylr. Ayrca standartlarda main fonksiyonundan elde edilen geri dn deeri ile exit fonksiyonunun arlaca sylenmitir. Yani main fonksiyonunda n deeri ile return etmek ile exit(n) armas ayn sonuca yol amaktadr.

3. Bir thread baka bir threadi TerminateThread fonksiyonu ile sonlandrr.


BOOL WINAPI TerminateThread(HANDLE hThread, DWORD dwExitCode);

Fonksiyonun birinci parametresi threadin handle deeri, ikinci parametresi k kodudur. Fakat threadlerin bu ekilde sonlandrlmas tavsiye edilmez.

19.5. Threadlerin Senkronizasyonu

Thread konusunun nemli bir blmn senkronizasyon konusu kaplamaktadr. nk ok threadli uygulamalar yaparken threadlerin birbirlerini beklemesi gerekebilmektedir.

19.5.1. Kritik Kodlarn Oluturulmas

Bandan sonuna kadar tek bir thread ak tarafndan altrlmas gereken kodlara kritik kodlar denilmektedir. Bir thread bir kritik koda girdiinde baka bir thread bu kritik koda ya da bu kritik kodun ilikin olduu bir koda girmemelidir. Thread ak kritik koddayken threadler aras gei oluabilir. Fakat baka bir thread nceki thread kana kadar bu koda girmemelidir. Kritik kodlar ortak kaynaklara eriirken sklkla kullanlmaktadr. rnein iki thread ayn bal listeye ekleme yapyor olsun. Ekleme srasnda dmler birbirine balanrken threadler aras gei oluabilir. Baka bir threadte ekleme ya da silme gibi ilemleri yapmaya alrsa bal liste kararsz durumda olduu iin sorunlar oluabilir. Ekleme yapan thread ilemini bitirmeden

184

dier threadler bu bal listeyi kullanmaya almamaldr. Yada rnein rand gibi bir fonksiyon global bir deikeni kullanmaktadr. ki threadte bu fonksiyonu arrsa yanl deerler oluabilir. Grld gibi ortak kaynaklara eriimde, eriimlerin seri hale getirilmesi paralel yaplmamas gerekmektedir. Windowsta kritik kod oluturmak iin InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection fonksiyonlar kullanlr. Bu fonksiyonlarn kullanm yledir: 1. CRITICAL_SECTION trnden bir nesne tanmlanr. rnein:
CRITICAL_SECTION g_cs;

2. Programn banda InitializeCriticalSection fonksiyonu ile bu nesneye ilk deerleri verilir.


void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

3. Fonksiyon parametre olarak CRITICAL_SECTION nesnesinin adresini alr. rnein:


InitializeCriticalSection(&g_cs);

4. Kritik kod yle oluturulur:


EnterCriticalSection(&g_cs); /*************/ LeaveCriticalSection(&g_cs);

Kritik Kod

Bir thread ak EnterCriticalSection fonksiyonuna girdii zaman baka bir ak fonksiyona girmeye alrsa bloke olarak izelge dna kartlr ve bekleme durumuna geer. Ta ki kritik koddaki thread LeaveCriticalSection fonksiyonunu arana kadar. Birden fazla thread EnterCriticalSection fonksiyonunda bekliyorsa kritik koddaki thread, kritik koddan knca hangisinin girecei konusunda resmi bir bilgilendirme yaplmamtr.
void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

Nihayet tm ilemlerin sonunda DeleteCriticalSection fonksiyonu arlmaldr.

void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); DeleteCriticalSection(&g_cs);

185

Kritik kod uygulamas manel yolla yaplamaz. rnein aadaki gibi bir kritik kod oluturmak isteyelim.
BOOL g_flag = false; /*******/ while (g_flag) ; g_flag = TRUE; /********/ g_flag = FALSE;

Kritik Kod

Ok ile belirtilen noktada threadler aras gei oluursa baka bir thread kritik koda girebilir. Peki, EnterCriticalSection ve LeaveCriticalSection gibi fonksiyonlar bu mekanizmay nasl salamaktadr? te bu tr yntemler genellikle kernel moda geilerek yada geilmeden uygulanabilmektedir. nrein biz flag kontroln yapmadan nce kesme oluumunu zel makine komutlar ile engellersek flag ilemini gvenli bir biimde yapabiliriz. Fakat bu zel makine komutlarn kullanabilmek iin kernel moda gemek gerekir. Fakat pek ok modern ilemcide bu tr ilemleri atomik yapabilmek iin test ve set ilemlerini birlikte yapp jump eden zel makine komutlar vardr.
Anahtar Notlar: Preemptive bir iletim sisteminin kernel yaps, preemptive veya non-pre-emptive olabilir. Pre-emptive kernel demek bir sistem fonksiyonu arlp kernel moda geildiinde de threadler aras gei oluabilir demektir. Yani ak kernel modda iken kuanta sresi dolduunda yine threadler aras gei uygulanmaktadr. Fakat non-preemptive sistemlerde, kernellarda ak kernel modda iken kana kadar kesilme yaplmamaktadr. Non-preemptive kernel tasarm daha kolaydr. nk pek ok kernel veri yapsnn senkronize edilmesine gerek kalmaz. rnein Linux iletim sistemi 2.6ya kadar non-preemptive bir kernel a sahipti, 2.6 ile byk lde pre-emptive yaplmtr. Anahtar Notlar: Kernel mimarisi iin bir izginin iki ucunda mikro kernel ve monolitik kernel tasarmlar sz konusudur. Tabi bir kernel bu arada bir yerlerde olabilir. Mikro kernel mimaride, kernel minimal dzeyde ok temel ilemleri yapacak biimde tasarlanr, kernelin dier ilevleri istee bal olarak yklenen modller ile gerekletirilir. Monolitik yapda kernel tek para byk bir dosya halindedir. Boot ilemi srasnda bellee btnsel olarak yklenir.

Kritik kod iine alma ilemi ne kadar kk bir kodu ierirse o kadar iyidir. nk bu durumda bloke olma olasl azalr. rnein bir bal listeyi biz dardan veya ierden senkronize edebiliriz. Dardan senkronizasyonda fonksiyon arlar senkronize edilir. Fakat bu durumda

186

geni bir blok kritik kod ierisine alnm olur. Halbuki bal liste fonksiyonlarnn ierisinde tam dm balantlar yaplrken senkronizasyon uygulanabilir. Bu durumda bal liste kendiliinden thread gvenli olur. Fakat tek threadli uygulamalarda gereksiz bir senkronizasyon sz konusu olacaktr. Bu tr durumlarda sklkla ayn ktphanenin tek threadli ve ok threadli versiyonlar ayr ayr bulundurulmaktadr.

19.5.2. Windows Kernel Senkronizasyon Nesneleri

Windows sistemlerinde kernel moda geerek alan bir grup senkronizasyon nesnesi prosesler arasnda kullanlabilmektedir. Bu senkronizasyon nesnelerinin hepsi WaitForxxx fonksiyonlarnda beklenebilmektedir. Kernel senkronizasyon nesneleri dier iletim sistemlerinde de benzer biimlerde bulunmaktadr. rnein Mutex, Semaphore ve Event nesneleri pek ok sistemde benzer biimde bulunmaktadr.

19.5.3. WaitForSingleObject Fonksiyonu

WaitForSingleObject fonksiyondur.

fonksiyonu

senkronizasyon

nesnelerini

bekleyen

genel

bir

DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

Fonksiyonun birinci parametresi senkronizasyon nesnesinin handle deeridir. kinci parametre zaman am (time out) parametresidir. Bir senkronizasyon nesnesinin iki durumu vardr. Nesne ak (signaled) durumda iken WaitForSingleObject fonksiyonu bekleme yapmaz. Nesne kapal (non-signaled) iken, fonksiyon nesne ak duruma gelen kadar bekler. Ak ve kapal durumlar beklenen nesneye bal olarak tanmlanmaktadr. Fonksiyon eer zaman amndan dolay sonlanmsa WAIT_TIMEOUT deerine, nesne ak duruma geldiinden dolay sonlanmsa WAIT_OBJECT_0 deerine geri dner. Fonksiyon yanl handle geilmesi gibi nedenlerden dolay baarsz olabilir. Bu durumda WAIT_FAILED deerine geri dner.

187

19.6.

Event Nesnelerinin Kullanm

Event nesneleri zellikle bir olay gerekleene kadar bekleme oluturmaktadr. Tipik olarak retici-tketici problemlerinin zmnde kullanlabilir. Event nesnesinin kullanm yledir: 1. Event nesnesi CreateEvent fonksiyonu ile oluturulur. Handle deeri global bir deikene yerletirilebilir.
HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName );

Fonksiyonun birinci parametresi nesnenin gvenlik bilgilerini belirtir. NULL geilebilir. kinci parametre event nesnesinin manuel mi yoksa otomatik mi olduunu belirtir. Bu parametre FALSE geilirse otomatik, TRUE geilirse manueldir. nc parametre nesnenin balangta ak m yoksa kapal m olacan belirtir. Son parametre prosesler aras kullanm iin gereken ismi belirtir. Eer ayn prosesin threadleri arasnda senkronizasyon uygulanacaksa bu parametre NULL geilebilir. Fonksiyon baar durumunda event nesnesinin handle deerine baarszlk durumunda NULL deerine geri dner. 2. Event nesnesi WaitForSingleObject fonksiyonu ile beklenir. 3. SetEvent fonksiyonu ile event nesnesi ak duruma geirilebilir.
BOOL SetEvent(HANDLE hEvent);

Fonksiyon Event nesnesinin handle deerini parametre olarak alp onu ak duruma getirmektedir. 4. Nihayet ilem bitince Event nesnesi CloseHandle fonksiyonu ile yok edilir. Fonksiyon Event nesnesinin handle deerini parametre olarak almaktadr.
BOOL CloseHandle(HANDLE hObject);

Event nesnesi otomatik modda ise WaitForSingleObject fonksiyonu ile nesnenin ak duruma gelmesinden dolay gei yapldnda otomatik olarak nesne yeniden kapal duruma geer. Aksi halde nesneyi kapal duruma geirmek iin ResentEvent fonksiyonu uygulanmaldr.

188

19.7.

retici Tketici Problemi

retici-tketici problemi (producer-consumer problem) ok threadli uygulamalarda ve prosesler aras haberlemelerde sk gereksinim duyulan bir durumu belirtmektedir. Bu problemde threadlerin biri bir deer elde eder ve bunu bir ortak kullanlan nesneye yazar. Bu threade retici denilmektedir. Dier thread ise yazlan deeri paylalan nesneden alarak kullanr. Buna da tketici thread denilmektedir. retici ve tketici threadler bunu dng ierisinde birden fazla kez yapmaktadr. rnein bir thread bir asal say bulup bunu bir global bir deikene yerletirebilir, dieri de bunu alarak kullanabilir ve bu ilem byle devam edebilir. Bu tr uygulamalarda reticinin tketici almadan yeni bir deeri yerletirmemesi tketicinin de retici yeni bir deer koymadan almaya almamas gerekir. Bu ok karlalan klasik bir durumdur. retici-tketici probleminde paylalan alan yani tampon blge bir elemanlk olabilir. Fakat daha genel bir biimde tampon alan nlik bir kuyruk sistemi olabilmektedir. Ayrca bu problemin genel hali n*m lik olabilir. Yani yukarda tipik olarak 1*1 lik ve 1 elemanlk durum aklanmtr. rnein 3 thread deer olutururken, 5 thread deer almaya alabilir.

19.7.1. retici Tketici Probleminin Event Nesneleri le zm

1*1 lik ve tek elemanl retici tketici problemi 2 Event nesnesi kullanlarak zlebilir. Ancak ayn problemin k elemanlk biimi, yani paylalan blgenin bir kuyruk sistemi olduu biimi Event nesneleri ile zlemez. Tampon blgenin k elemanlk olduu genel biim ancak semaforlar ile zlebilir.
HANDLE g_h ConsumerEvent, g_h ProducerEvent; /***/ g_h ConsumerEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

189

g_h ProducerEvent = CreateEvent(NULL, FALSE, FALSE, NULL); RETC for (;;) { WaitForSingleObject(g_h ConsumerEvent, INFINITE); <Datay global nesneye yaptr> SetEvent(g_h ProducerEvent); } TKETC for (;;) { WaitForSingleObject(g_h ProducerEvent, INFINITE); <Datay global nesneden al> SetEvent(g_h Consumer Event); }

Anahtar Notlar: Threadlerin ve proseslerin kendisi de bir senkronizasyon nesnesi gibi kullanlabilir. Threadler yada prosesler alyor durumda iken nesne kapal durumdadr. alma bittiinde ak duruma geer. Dolaysyla bir thread sonlanana kadar yle bekleme yaplabilir. WaitForSingleObject(hThread, INFINITE); Anahtar Notlar: Windows kernel senkronizasyon nesnelerinin hepsi kernel modda almaktadr. Yani kernel moda gei yapt iin bir gecikme sz konusu olabilmektedir.

19.7.2. Semafor Nesneleri

Semafor nesneleri de pek ok iletim sisteminde benzer biimde bulunmaktadr. rnein Linux sistemlerinde de semaforlar vardr. Semafor nesneleri bir kritik koda en fazla n tane akn girmesini salayan sayal nesnelerdir. rnein:

Kritik Kod

Daha nce kritik koda tek bir akn girmesini salamtk. Semaforlarla kritik koda birden fazla, fakat en fazla n tane akn girmesi salanabilir. rnein kritik koda en fazla 3 tane akn girmesini isteyelim. 1, 2, 3 numaral aklar kritik koda girerler. Ama bunlardan biri kmadan yeni bir ak kritik koda giremez. Bir kritik koda en fazla n tane akn girmesinin anlam nedir? Kritik kodda n tane kaynaktan birinin tahsis edildiini dnelim. Her giren ak iin bir kaynak tahsis edilir. Bu durumda yeni bir aka kaynak kalmamsa onun beklemesi gerekir. Win32 sistemlerindeki semafor kullanm yledir.

190

1. Semafor nesnesi CreateSemaphore fonksiyonu ile oluturulur. Semafor oluturulurken kritik koda ka akn girecei belirtilir. Fonksiyon prototipi yledir:
HANDLE CreateSemaphore ( LPSECURITY_ATTRIBUTER lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName );

Fonksiyonun birinci parametresi nesnenin gvenlik bilgileridir. NULL geilebilir. kinci parametre kritik koda en fazla ka akn gireceini bildiren saya parametresidir. nc parametre sayacn kabilecei maksimum deerdir ve genellikle ikinci parametreyle ayn deerde verilir. Son parametre prosesler aras paylam iin gerekli olan isimdir. NULL geilebilir. Fonksiyon baar durumunda semaforun handle deerine, baarszlk durumunda NULL deerine geri dner. 2. Kritik kod aadaki gibi oluturulur:
WaitForSingleObject(...) ; /***/ ReleaseSemaphore(...);

Kritik Kod

Semafor nesnesi, semafor sayac 0 dndaysa ak, 0 ise kapal durumdadr. WaitFor fonksiyonlarndan her girite semafor sayac bir azaltlr. ReleaseSemaphore ise semafor sayacn artrr. ReleaseSemaphore fonksiyonunun prototipi yledir:
BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount );

Fonksiyonun birinci parametresi semaforun handle deeri, ikinci parametresi artrm deeridir (Tipik 1 olarak verilir.). Semafor sayacnn deeri hibir zaman CreateSemaphore da belirtilen deeri geemez. Fonksiyonun son parametresi LONG bir nesnenin adresini alr ve sayacn nceki deerini oraya yerletirir. Bu parametre NULL geilebilir, bu durumda bir yerletirme yaplmaz. 3. Kullanm bittikten sonra semafor nesnesi CloseHandle fonksiyonu ile kapatlr.

191

Anahtar Notlar: Windows sistem programlama konusunda u kaynaklara bavurulabilir: - Jeffrey Richterin ierii benzer, fakat her basksnn ismi farkl olan kitaplar (bu kitabn klasik versiyonu: Programming Applications for Microsoft Windows) Bu kitabn son versiyonu Windows via C/C++ ismindedir. - Matt Pietrekin Windows 95 Programming Secret kitabdr. Bu kitapta kernela ilikin pek ok veri yaps aklanmaktadr. - Windows System Programming (The Addison-Wesley Microsoft Technology Series) - Solomonun Classic Windows Internals. - Solomonun eski sitesi sysinternals artk Microsoft tarafndan alnmtr. Burada ok sayda makale bulunmaktadr. (www.sysinternals.com) - Reactos Operating Systemin sitesi open source Windows yazma projesidir. Dolaysyla buradaki kaynak kodlar, Windowsun gerek kodlar hakknda iyi bir fikir verebilir. (www.reactos.org) - Windowsun alnm kaynak kodlar belirli alt sistemler hakknda bilgi vermektedir. Anahtar Notlar: http://fxr.watson.org/ sitesinde kod inceleme yaplabilir.

19.7.3. ok Tamponlu retici-Tketici Problemlerinin Semafor Nesneleri le zmlenmesi

Bu tr retici-tketici problemleri en fazla karlalanlardandr. Burada reticinin bilgiyi yerletirecei veri yaps bir kuyruk biimindedir ve kuyruun belirli bir snr vardr. retici thread gelen bilgiyi kuyrua yerletirir, kuyruk dolduunda blokede bekler. Tketici threadte kuyruk tamamen bosa bekler. Bu sistem retici ve tketicinin daha az beklemesine yol at iin phesiz daha verimlidir. Bu zmde tipik olarak bir retici bir de tketici iin iki semafor oluturulur. retici semaforunun balang saya deeri n, tketicinin 0 olacaktr. retici her WaitFor fonksiyonundan getiinde kuyrua yeni bir elaman yerletirir. Bylece kuyrua en fazla n tane eleman yerletirebilir. retici ReleaseSemaphore ile tketicinin, tketicide reticinin semafor sayacn artrr. phesiz yine de retici ve tketici threadler ayn anda kuyruk sistemi zerinde ilem yapyor durumda olacaklardr. Kuyruk sisteminin ayrca senkronize edilmesi gerekir. ok tamponlu yani kuyruk sistemli retici-tketici problemi yle zlebilir:
HANDLE g_hConsumerSem, g_hProducerSem; g_hConsumerSem = CreateSemaphore(NULL, n, n, NULL); g_hProducerSem = CreateSemaphore(NULL, 0, n, NULL);

192

RETC WaitForSingleObject(g_hConsumerSe m, INFINITE); <Kuyrua deeri ekle> ReleaseSemaphore(g_hProducerSem, 1, NULL);

TKETC WaitForSingleObject(g_hProducerS em, INFINITE); <Kuyruktan deeri al> ReleaseSemaphore(g_hConsumerSem, 1, NULL);

19.8. Mutex Nesneleri

Mutex (Mutual Exclusion) neredeyse her iletim sisteminde bulunan bir senkronizasyon nesnesidir. Mutex nesnesinin sahiplii bir thread tarafndan alnabilir ve ancak o thread tarafndan braklabilir. Pek ok sistemde Mutex nesneleri sayaldr (rnein Windows sistemlerinde byledir. POSIX sistemlerinde istee baldr.). Yani ayn thread sahiplii birden fazla kez alabilir. Bu durumda birden fazla kez sahipliin braklmas gerekir. Mutex kritik kod oluturmak iin kullanlabilir fakat critical section ilemlerinden fark vardr. Sahiplik thread temelindedir. Baz uygulamalarda bunun tipik kullanmlar vardr. Mutex aslnda temel bir senkronizasyon nesnesidir ve baz sistemlerde dier senkronizasyon nesneleri dolayl biimde nutex nesneleri kullanlarak gerekletirilmektedir. Mutex kullanm tipik olarak yledir: 1. Nutex nesnesi CreateMutex fonksiyonu ile yaratlr.
HANDLE CreateMutex( LPSECURITY_ATTRIBUTE lpMutexAttributes, BOOL bInitial Owner, LPCTSTR lpName );

Fonksiyon birinci parametresi kernel nesnesinin gvenlik bilgilerini belirtir ve NULL geilebilir. kinci parametre mutex nesnesinin sahipliinin iin banda yaratan thread tarafndan alnp alnmayacan belirtmektedir. Bu parametre TRUE ise alnr, FALSE ise alnmaz. Son parametre prosesler arasndaki paylamda kullanlan isimdir. Fonksiyon baar durumunda mutex nesnesinin handle deerine, baarszlk durumunda NULL deerine geri dner. 2. Mutex nesnesi eer sahiplik alnmsa ak durumda alnmamsa kapal durumdadr. Kritik kod yle oluturulur:
WaitForSingleObject(); /****/ ReleaseMutex();

193

Eer thread mutex nesnesinin sahipliini alm durumdaysa WaitFor fonksiyonlarndan geer. ReleaseMutex mutex nesnesinin sahipliini brakr. Eer mutex nesnesinin sahipliini hibir thread almamsa nesne yine ak durumdadr WaitFor fonksiyonu sahipliini alarak geer. Yani eer mutexin sahipliini baka bir thread almsa WaitFor fonksiyonlarndan gei yaplamaz. Fakat sahiplik botaysa ya da sahiplii zaten alm durumdaysak gei yaplr. ReleaseMutex fonksiyonu ancak sahiplik ilgili thread tarafndan alnmsa sahiplii brakabilir. Yani biz sahipliini almadmz bir mutexin sahipliini brakamayz.
BOOL ReleaseMutex(HANDLE hMutex);

3. CloseHandle fonksiyonu ile kullanm bitince mutex nesnesinin sahiplii braklabilir. 19.9. ok lemcili alma letim sistemleri birden fazla ilemciyi (ok ekirdekli sistemler birden fazla ilemcili sistemler gibi davranr.) thread temelinde izelgelemektedir. Yani bir ilemciye bir thread atanmaktadr. Genellikle modern sistemler tek bir izelge oluturup belli kriterlere de bakarak sradaki threadi boalm olan ilemciye atamaktadr. rnein iki ekirdekli bir Intel ilemcisini dnelim ve sistemde 7 tane thread bulunuyor olsun. letim sistemi bir threadi bir ilemciye dierini dier ilemciye verir. Kuanta sresi bittiinde hangi ilemci boalmsa sradaki ona atar. T7

T1 T2

P1

P2

T6

T5 T4

T3

letim sistemi thread temelinde atama yaptna gre hibir zaman bir T annda programmz birden fazla ilemci tarafndan altrlyor durumda olmayacaktr. Tek threadli bir program ok ilemcili sistemlerde yine daha hzl alabilir. Fakat bu birim zamanda toplam altrlan kod miktarnn artmasnn doal bir sonucudur. Biz programmz ok threadli tasarlarsak gerekten

194

ayn anda alma mmkn olabilir. Bu durumda iletim sistemi threadlerden birini bir ilemciye dierini dier ilemciye verebilir. Aslnda ok ilemcili sistemlerde bir ilemci boaldnda hangi threadin ilemciye atanaca konusunda baz ince hesaplar yaplmaktadr. Hemen sradakinin atanmas yerine bekleyen baka bir threadin atanmas daha uygun olabilir. rnein bir thread daha nce ilemcilerin birine atanmsa sonraki kuantada gene ayn ilemciye atanmas isel cache mekanizmas yznden toplam performans artrmak iin daha uygun olabilir. Tabi bu faktrlerden yalnzca biridir. Baka faktrlerde vardr. O halde kabaca unlar sylenebilir: lemciye thread atanaca zaman izelgede bekleyen threadler gzden geirilir ve en uygun olan seilir. phesiz dngsel bir izelgeleme sz konusu yine olabilir ve iletim sistemi mmkn olduunca gene adil davranabilir. rnein kuyrukta ok beklemek seilmek iin bir avantajdr. Yani son ara verilmi threadin o kadar thread beklerken yeniden ele alnmas adil bir durum deildir. ok ilemcili sistemlerde bu ilemcilerin hepsi ayn RAMe erimektedir. Fakat bir ilemci RAMe eriirken dierini durdurmaktadr. Aslnda eriimi mikro dzeyde ayn anda yaplmamaktadr. ki ilemci tek bir makine komutuyla ayn bellek blgesine eriiyor olsun. rnein bir thread bir global bir deikene bir deer yazarken dieri okuyor olabilir. Eriimler tek bir makine komutuyla yaplyor olsa bile bir makine komutunun ileyiinde batan sona kadar dier ilemcinin erimesi engellenmemektedir. Makine komutu iletilirken nano saniyeler mertebesinde RAMi tutup brakabilmektedir. te kt bir tesadf ile bu srada bir i ie geme oluabilir. Bu anlatmlardan kan sonu udur: ok ilemcili sistemlerin ounda farkl threadler ayn global deikene eriiyorsa bu ilemler byk bir tesadfle farkl ilemciler tarafndan ayn anda yaplrsa bozulmalar oluabilir.
Anahtar Notlar: Modern gl ilemcilerin bir zellii de birbirinden bamsz ardk komutlar belirtilen srada deil de farkl srada yaparak bundan bir avantaj salamaktr (instruction reordering). Fakat bu durum senkronizasyon konusunda ok ilemcili sistemlerde baz problemlere yol aabilmektedir. Yine modern ilemcilerde branch prediction denilen gelimi zellikler vardr. Bu sayede komut altrrken sonraki hangi komutlar iin hazrlklar yaplaca tahmin edilmektedir.

zetle ok ilemcili sistemlerde garanti program yazmak istiyorsak global deikenlere eriirken yine bir eit senkronizasyon kullanmalyz. Bu nedenle programda yanl deerler oluma olasl vardr fakat ok zayftr. Global deikenlere eriirken yukarda ele alnm olan senkronizasyon nesnelerini kullanmak ilemleri ok yavalatr. te bunlar iin InterLock fonksiyonlar denilen zel fonksiyonlar bulunmaktadr. Intel ilemcilerinde ve pek ok ilemcide 195

Lock ilemcili makine komutu (prefix) sonraki makine komutu altrlrken dier ilemcileri durdurmaktadr. O halde global deikenlere eriirken Lock gibi ilemleri kullanmak gerekir. te InterLock fonksiyonlar eriim srasnda bu gibi makine komutlarn kullanr. Global bir deikene erimek iin Windows sistemlerinde InterLockedxxx fonksiyonlar kullanlmaktadr. rnein bir global deikene deer atamak iin InterlockedExchange fonksiyonu kullanlr. LONG InterlockedExchange( PLONG Target, LONG Value); Fonksiyonun birinci parametresi deerin yerletirilecei long bir nesnenin adresini alr. kinci parametre yerletirilecek deeri belirtmektedir. Fonksiyon geri dn deeri olarak deikenin eski deerini vermektedir. rnein aadaki gibi global bir deikenimiz olsun. long g_i; Biz buna yle deer atamalyz: InterlockedExchange(&g_i, 100); Bir deikenin deerini bir artrmak iin InterlockIncriment fonksiyonu kullanlabilir. LONG InterlockIncriment(PLONG Adde); Fonksiyon artrm yaplacak nesnenin adresini alr ve bunun deerini bir artrr. Bir deikenin iindeki n artrmak iin InterlockedExchangeAdd kullanlmaktadr. rnein byk bir global diziyi iki farkl thread ok ilemcili bir sistemde belli bir deerle doldurmak istesin. long g_a[SIZE]; long g_i; Biz burada diziye atama veya artrm srasnda Interlocked fonksiyonlarn kullanmak zorundayz. InterlockedIncrement(&g_i); Ya da rnein bir thread deikeni set edip dier treadten okunduu durumda da benzer biimde bir nlem alnmaldr.

196

19.10. volatile Nesnelerin ok Threadli almalarda nemi

Global nesnelerin volatile anahtar szc ile bildirilmesi onlarn geici sre yazmalarda tutulmasn engellemektedir. Standartlara gre volatile bir nesneye her eriildiinde gerek bir bellek eriimi yaplmak zorundadr. rnein threadlerden biri bir global deikene bakarak dngde ilem yapyor olsun.
while (g_flag) { //..... }

Biz baka bir threadten g_flage 0 atayarak bu dngy bitirmek isteyebiliriz. derleyici optimizasyonlar tek aka ynelik yaplmaktadr. yani derleyici programn tek aktan olutuunu varsaymaktadr. Optimizasyon seenekleri aldnda derleyiciler bellek eriimini azaltmak iin yazmalar kullanabilirler. rnein:
for (;;) { //********* g_flag = ifade; //-------} Foo();

Burada derleyici g_flag deikenini bir yazmaca ekip dng ierisinde hep o yazmac kullanabilir. Nihayet Foo fonksiyonu arlmadan nce yazmataki deeri yeniden g_flag deikenine yerletirerek Foo fonksiyonunu arabilir ya da nceki rnekte while ierisinde g_flag deikenine bakmak yerine, g_flag ierisindeki deeri yazmaca ekip aslnda yazmaca bakan kod retebilir. nk derleyici default olarak threadli bir almay gz nne almamaktadr. te biz Cde bu tr global deikenleri her ihtimale kar volatile bildirmeliyiz.
volatile int g_flag; while (g_flag) { } for (;;) { //********* g_flag = ifade; //-------}

Tabi volatile olmamasndan dolay Derleyicimizi tanyorsak ya da kod optimizasyonu yapabiliyorsak bir sorun ortaya kmaz. 197

19.11. Windows Sistemlerinde Thread izelgelemesi

Windows sistemlerinde kuanta sresi 20 msnden 120 msnye ye kadar eitli etkenlere bal olarak deimektedir. Bu konudaki ayrntlar Microsoft tarafndan dkmante edilmemitir. Server grubu sistemlerde kuanta sresi 60 ms yada 120 msn civarndadr. 9598 grubu sistemlerde 20 msn civarndadr. (Linux sistemlerinde tipik 60 msn biimindedir.) Windows sistemleri thread izelgelemesi iin ncelik snflar temelinde dngsel izelgeleme yntemini kullanmaktadr. Windows sistemlerinde her threadin 031 aras bir ncelik derecesi vardr.
Anahtar Notlar: Threadin ncelik derecesi Windows sistemlerinde iki deerin toplam ile elde edilmektedir. Deerlerden biri threadin iinde bulunduu prosesin ncelik snfdr. Proseslerin ncelik snf bir taban deer belirtir. Bu taban deere threadin greli ncelik derecesi eklenmektedir. Prosesin ncelik snf SetPriorityClass API fonksiyonu ile deitirilebilir. Threadin greli ncelik derecesi ise SetThreadPriority Fonksiyonu ile belirlenmektedir. Bu izelgeleme yntemine gre her farkl thread ncelii iin bir ncelik grubu oluturulur ve sistem sanki dier threadler yokmu gibi en yksek ncelikli grubu dngsel izelgeler. Bu gruptaki tm threadler biterse bir sonraki ncelik grubuna geilir. rnein izelgede aadaki nceliklere ilikin ncelikler bulunsun: 18 18 18 17 16 16 9 8 8 8 8 4 0 Burada nce dngsel ncelikteki 3 thread dngsel izelgelenir. Bu threadlerin hepsi biter veya bloke olursa bu kez 17 ncelikli thread izelgede tek bana yer alr. 17 de bloke olursa bu kez 16l grup izelgelenir. Bu biimdeki alma adaletsizmi gibi gelebilir. lk anda dk ncelikli threadlerin hi almayacan sanabiliriz. Fakat ne olursa olsun blokelerden dolay dk ncelikli threadlerde alma ans bulabilmektedir. Windows sistemlerinde 0 ncelikli bir thread iletim sisteminin Idle threadidir ve hibir ilem yaplmyorsa devreye girer. Windowsta default ncelik derecesi 8dir. Yksek ncelikli threadler bloke olduunda dn ncelikli threadler alma ans bulabilir. Fakat bu durumda yksek ncelikli bir threadin blokesi zldnde hemen alma yksek ncelikli threade verilir. Bir thread arada srada bireyler yapt halde yksek bir ncelik derecesine sahip olabilir. Bylece thread etkileime abuk geer ve yapt ii de hzl yapar.

Ayrca

Windows

sistemlerinde

priority

boosting

denilen

bir

mekanizma

da

kullanlmaktadr. Bu mekanizma ana hatlaryla aklanmtr fakat ayrntlar dokmante edilmemitir. Bu mekanizmaya gre bir pencere aktif hale getirildiinde bu tr prosesler ve threadler belirli bir kuanta iin ncelik ykseltmesine sokulur. Sonra ncelii programcnn belirledii duruma getirilir. Bylece kullancnn etkiletii pencereler ilikin threadler daha etkin olur.

Anahtar Notlar: letim sistemine ilikin bir kod ka biimde alma frsat bulabilir? Tipik senaryolar unlardr.

198

1. eitli donanm kesmeleri olutuunda iletim sisteminin kodlar altrlmaktadr. 2. letim sisteminin de tpk bizim sradan proseslerimizin threadleri gibi hi bitmeyen kernel threadleri vardr. Kernel threadler izelgeleme bakmndan sradan threadlerle ayn biimde altrlr. ou kez arada bir devreye girer ve baz kritik ilemleri yapar. 3. Sistem fonksiyonlar ya da aygt srcler yoluyla iletim sistemlerinin kodlar altrlabilir. 4. letim sistem boot edilirken zaten iletim sistemi kodlar altrlarak sistem almaktadr. izelgeleme konusunda iletim sistemini temsil eden ortadaki yuvarlakk timer kesmesi ile devreye giren iletim sisteminin izelgelemesini gerekletiren kernel kodlarn belirtmektedir.

20. DERLEYCLERN KOD OPTMZASYONU


Modern derleyiciler derleme srecinde eitli iyiletirmeler yaparak kodun daha iyi almasn salamaktadr. Bu tr derleyicilere kod optimizasyonu yapan derleyiciler (optimizing compilers) denilmektedir. Kod optimizasyonu eitli aamalarda gerekletirilebilir. Tipik olarak ara kod retiminden sonra nemli optimizasyonlar ara kod zerinde gerekletirilir. Ayrca kod retimi aamasnda da hedef mimariye ilikin optimizasyonlar yaplmaktadr.
Lexical Analyzer Syntax & Semantic Analyzer (Parser) Code Optimizer

nyz

Intermediate Code Generator Target Code Generator

Orta yz

Arka yz

Kod optimizasyonu her ne kadar ara kod retiminden sonra tek bir modl biiminde gsterilmise de sentaks analizinden sonra pars tree zerinde ve hedef kod retimi srasnda da ciddi optimizasyonlar yaplmaktadr. Fakat gerekten de klasik optimizasyonlarn byk blm ara kod retiminden sonra gerekletirilir. Optimizasyon kodun edeerlii bozulmadan yaplan bir faaliyettir. Yani yazdmz programn anlam deimez. Kod daha etkin alacak biimde retilir.

199

Kod optimizasyonu eitli tipik kategorilere ayrlarak ele alnabilir. Dngler en nemli optimizasyon kaynadr. Yani dnglere younlalmas nemlidir nk program yaamnn byk bir ounluu dnglerde geer. Optimizasyon ilemi hz ve kaynak kullanm ltlerine bal olarak yaplabilir. Yani kod daha hzl alacak biimde ya da daha az yer kaplayacak biimde optimize edilebilir. Ancak hz optimizasyonu ok daha baskn olarak tercih edilmektedir. nemli optimizasyon temalar aada aklanmaktadr.

20.1. l Kod Eliminasyonu (Death Code Elimination)

Bu optimizasyon genellikle kodu kltme hedefindedir. Derleyiciler eriilemeyen kodlar elimine ederek bunlar iinde gereksiz biimde kod retmezler. rnein:
void Foo(void) { //****** return; a = 10; b = 20; } l kod l kod

Burada ak return deyiminden ileri gemeyeceine gre bu atamalarn bulunmasna hi gerek yoktur. Pek ok C derleyicisi bu durumlarda unreachable code biiminde uyar da vermektedir. Bir deikene bir deer atandn fakat o deerin hi kullanlmadn dnelim. Bu da l kod statsndedir. rnein:
{ int a = 10; //********* }

Burada derleyici eer a hi kullanlmadysa a iin yer ayrmayabilir ya da aya atama yapmayabilir. C derleyicilerinin ou yine bu durumda uyar vermektedirler (a declared not used). Bazen l kodlar deyimlerin yanl kullanlmasyla da oluabilir. rnein:
if (0) ifade;

200

Burada ifade asla altrlamayacaktr. Elimine edilebilir. Ya da rnein:


char ch = 0xFC; if (ch == 0xFC) { /**********/ }

Derleyici if always false gibi bir uyar verebilir. Eer char tr default iaretliyse bu ifade hibir zaman doru olmaz. Ya da rnein:
short a; if (a > 150000) { /*****/ }

short hibir zaman 150000i geemeyecekse bu kodda anlamsz ve l koddur. Gereksiz kodlamalar da bu biimde ele alnabilir.

20.2. Gereksiz Kodlarn Elemine Edilmesi

Derleyici aksal analiz yaparak gereksiz kodlar elemine etmeye alr. rnein:
if (ifade) { /**** ****/ ifade1; } else { /*** ***/ ifade1; }

Burada ifade1in if dna yerletirilmesi edeerlii bozmaz. Fakat gereksiz bir kod elimine edilmi olur. rnein:
if (a) return 1; else return 0;

Burada yaplmak istenen udur.


return a != 0;

201

20.3. Ortak Alt fadelerin Elemine Edilmesi (Common Subexpression Elemination)

Pei sra ifadeler ierisindeki ortak alt ifadeler bir geici deikene yada yazmaca alnarak hz kazanc salanabilir. rnein:
a = x + y + z; b = x + y + k; c = x + y + l;

Burada x + y ortak alt ifadedir. Dolaysyla aslnda aadaki kod daha hzl alr.
temp = x a = temp b = temp c = temp + + + + y; z; k; l;,

Burada gereksiz bir biimde x + y tekrar tekrar yaplmayabilir. phesiz burada temp bir yazma olabilir. Byle deerlendirme yapldnda tek bana deikenlerinde bir alt ifade biiminde yorumlanabilecei grlr. rnein:
a = x; b = x; c = x;

Burada her defasnda bellekteki xi yeniden ekmektense bir kere yazmaca ekip yazmatan atama yapmak daha hzl almaya yol aar.
Anahtar Notlar: Kritik kodlar dnda programc iin okunabilirlik ok daha nemli olmaldr. Yani derleyicilerin zaten yapabildii optimizasyonlar kod ierisinde yapmak kodun okunabilirliini azaltabilir. Yukardaki rnekte x + y alt ifadesinin tempe programc tarafndan yerletirilmesi kt bir tekniktir. Gl derleyicilerin hemen hepsi bu tr eliminasyonlar yapabilmektedir.

20.4. Sabit fadesi Yerletirme (Constant Folding)

Sabit

ifadelerinin

deerleri

alma

zamanna

braklmadan

derleme

zamannda

hesaplanabilir. rnein:
x = 10 + y + 2;

Derleyici bu kodu x = 12 + y; biimine dntrebilir.

202

20.5. Sabit fadelerinin Yaydrlmas (Const Propegation)

Bu optimizasyon temasnda derleyici deimeyeceini bildii ifadelerin deerlerini ya batan hesaplar ya da deiken yerine sabit kullanr. Sabit kullanm da pek ok mimaride hz kazanc salamaktadr. rnein:
int x = 10 + 2; int y; y = x + 5;

Burada derleyici x ierisindeki ifadenin deimediini grerek y = x + 5; yerine y = 17; yerletirebilir. Tabi burada x volatile yaplrsa derleyici byle bir optimizasyonu yapmaz. 20.6. Ortak Blok (Basic Block)

Bu tema kodu kltmek iin uygulanmaktadr. Eer kod ierisinde tekrarlanan bloklar varsa bu bloklara tek yerden girilip tek yerden klyorsa derleyici bu ortak kodlardan bir tane yerletirip oraya jump ilemi yapabilir. rnein:
if (test1) { ifade1; ifade2; ifade3; } /***** *****/ if (test2) { ifade1; ifade2; ifade3; }

Burada if deyiminin doruysa ksm ortak bloktur. Dolaysyla tpk bir fonksiyon gibi ele alnabilir.
if (test1) call REPEAT; /****/ if (test2) call REPEAT; /*****/ REPEAT: ifade1; ifade2; ifade3; ret;

203

20.7. Gstericilerin Eliminasyonu

Gstericilerin gsterdii yerlere eriim, yani * operatrnn kendisi pek ok sistemde en az iki makine komutuna yol amaktadr. rnein 32 bit Intel mimarisinde *p= val gibi bir ilem
mov eax, p mov [eax], val

gibi bir makine koduyla gerekletirilir. Bir dng ierisinde srekli *p ifadesinin kullanldn dnelim.
for (;;) { /*****/ a[i + 2] = *p; }

Eer derleyici pnin gstericii yerdeki bilginin deimeyeceinden emin olsa *pyi bir geici deikene ya da yazmaca alr ve onu kullanabilir. Fakat buna emin olabilir mi? Optimizasyon ilemi tek threadli sistemde alld varsaylarak yaplmaktadr. Dolaysyla baka bir threadin *pyi deitirmesi gibi bir analizi derleyici yapmak zorunda deildir (Programc *p global bir nesneyse gstericiyi volatile yaparak threadler aras kullanmda bu optimizasyonu engellemek isteyebilir.) . Derleyici *pnin gsterdii yerin deimeyeceinden emin olmaldr. rnein p gstericisi bir nesneyi gsteriyor olsun o nesnede dng ierisinde deiiyor olsun. Bu durumda derleyici bu optimizasyonu yapamaz. rnein:
for (;;) { x = i; /*****/ a[i + 2] = *p; }

Burada rnein eer p xi gsteriyorsa, derleyici *pnin deerini yazmaya yerletirerek hep o yazmac kullanamaz. te derleyicinin buna emin olmas gerekir. Ya da rnein:
for (;;) { /***/ a[i + x] = *p; func(); }

Ya p global deikeni gsteriyorsa ve func fonksiyonu da onu deitiriyorsa? Derleyicinin pnin global bir nesneyi gsterdiini anlayabildiini dnelim. Eer func baka bir modlde

204

tanmlanmsa, derleyici onun kodunu gremeyecei iin artk *p ilemini optimize edemez. Eer func ayn kaynak dosya ierisinde ise derleyici inceleyerek buna karar verebilir. Derleyicilerin bu analizi yapmas vakit alc bir ilemdir.

20.8. Inline Fonksiyon Am

Inline fonksiyonlar C90da yoktur. C99 ve C++ta vardr. Inline fonksiyonlar optimizasyon konusudur nk her ne kadar bu tr fonksiyonlar inline anahtar szcyle programcnn istei dorultusunda oluturuluyorsa da pek ok derleyicide kod optimizasyonu srasnda

deerlendirilmektedir. Bir fonksiyon inline anahtar szcyle bildirilirse derleyici bu fonksiyon arldnda fonksiyon ars deil fonksiyon i kodunu koda yerletirir. rnein:
inline int Kare(int a) { return a * a; }

imdi biz bu fonksiyonu yle arm olalm:


a = Kare(b);

Derleyici muhtemelen yle bir kod aacaktr:


a = b * b;

Grld gibi inline fonksiyonlar makrolara olduka benzemektedir. Fakat ok daha kolay ve gvenli yazlabilmektedir. Ancak inline anahtar szc bir emir deil tavsiye niteliindedir. Derleyiciler uzun kodlar ya da ok zaman alan dngler ieren kodlar bir fayda salanamayaca gerekesiyle amayabilirler. Her ne kadar inline fonksiyonlar C90da yoksa da pek ok C derleyicisinde uzun yllardr bir eklenti biiminde bulunmaktadr. Inline fonksiyonlarn uygunsuz kullanmlar kodu bytr. C99 ile C++taki inline fonksiyonlar arasnda baz kk semantik farkllklar vardr. Inline fonksiyonlarn alm yaplmas iin kodlarnn derleyiciler tarafndan grlmesi gerekir. Bunun iin bu fonksiyonlarn balk dosyalarna yerletirilmesi anlamldr. Fakat bu fonksiyonlar yine external linkage ye sahiptir. Yani baka bir modlden normal bir fonksiyon gibi de arlabilir. Inline fonksiyonlarnn baka ayrntlar da vardr. Fakat burada optimizasyon konusu zerinde durulmutur.

205

20.9. Dng Deimezleri (Loop Invariants)

Dng deimezlerinin dngnn dna kartlmas en klasik dng optimizasyonlarndan biridir. rnein:
for (;;) { x = 10; /****/ }

Dng ierisindeki fonksiyon arlarnn dng deimezi olarak deerlendirilmesi ou kez mmkn deildir. rnein:
for (;;) { x = Func(); /****/ }

nk fonksiyon baka yan etkilere yol aabilir. rnein bir global deikeni deitiriyor veya bir dosyaya bir eyler yazyor olabilir. Programc bu yan etkinin birden fazla kez olumasn salamak iin ary dng ierisine alm olabilir. Tabi derleyici fonksiyonu tanmlamasn grrse ve bunun bir yan etkiye yol amadn belirlerse bu durumda ary dng dna kartabilir. rnein bir karakter dizisinin aadaki gibi dolalmas kt bir fikirdir:
for (i = 0; i < strlen(s); i++) { /*****/ }

Derleyiciler standart C fonksiyonlarnn ne yaptn bilmek zorunda deildir. Hatta derleyiciler standart C fonksiyonlarnn farknda da deildirler. Dolaysyla derleyici strlen fonksiyonunun bir yan etkiye sahip olabileceini dnd iin her defasnda bunu yeniden armak zorunda kalr. O halde bu kodun programc tarafndan yle dzeltilmesi gerekir:
length = strlen(s); for (i = 0; i < length; i++) { /*****/ }

Fakat pek ok iddial derleyicide intrinsic function denilen fonksiyon kavram da vardr. rnein Microsoft C derleyicilerinde pek ok standart C fonksiyonu intrinsic function dr. Bu tr fonksiyonlarn derleyici ne yaptn bilir. Hatta bunlar iin prototip de istemez. Dolaysyla bu tr fonksiyonlar dng deimezi olarak deerlendirilebilir. Baka ilave ek optimizasyonlara yol aabilir. rnein:

206

x = strlen(s); y = strlen(s + 1);

Burada eer strlen intrinsic function ise derleyici bu fonksiyonun yaz uzunluunu bulduunu bilir dolaysyla ikinci ary hi yapmadan y = x 1 gibi bir kod retebilir.

20.10. Dng Am (Loop Unrolling)

Bu optimizasyon temasnda bir dngnn dnme miktar azaltlr. Bunun iin derleyici dngy geniletir, dng ierisindeki ifadeleri birden fazla kez yazar, bylece de dngnn az dnmesini, dolaysyla daha az dng kontrol yaplmasn salar. rnein:
for (i = 0; i < 10; i++) ifade; for (i = 0; i < 5; i++) { ifade; ifade; }

Aadaki kod daha fazla yer kaplamasna karn daha hzl alr. Hatta abartl olarak tamamen dngy kaldrp pei sra 10 tane ifadeyi yazabilirdik. Tabi bunun bir snr vardr. Yani milyon kez dnen bir dngnn tam almas dnlemez. Fakat 4 kat ya da 8 kat alm yaplabilir. Bazen dng amlar daha karmak bir biimde yaplabilir. Buna loop unwindning denir. rnein:
for (i = 0; i < 100; i++) Func(i);

Yerine aadaki kod yazlabilir:


for (i = 0; i < 100; i += 5) { Func(i); Func(i + 1); Func(i + 2); Func(i + 3); Func(i + 4); }

207

20.11. Dng Ayrmas (Loop Splitting)

Bazen bir dngnn ierisinde if gibi deyimler varsa bu if deyiminden kurtulmak iin derleyici dngleri ayrabilir. rnein:
for (i = 0; i < 100; i++) if (i % 2 == 0) ifade1; else ifade2;

Yerine aadaki alm yaplabilir:


for (i = 0; i < 100; i += 2) ifade1; for (i = 1; i < 100; i += 2) ifade2;

Tabi dngy blmek gerekten bir avantaj salyorsa yaplabilir.

20.12. Kod retimi Aamasnda Yaplan Optimizasyonlar

Klasik optimizasyonlar ara kod zerinde ya da pars tree zerinde yaplmaktadr. Bu optimizasyonlardan geildikten sonra optimize edilmi olan kod iin retim yaplr. te baz optimizasyonlar kod retimine yneliktir. Bunlarn en nemlileri unlardr. Tipik olarak CISC tabanl ilemcilerde komutlarn cycle sreleri birbirinden farkl olma eilimindedir. Yani ok sayda komut vardr ve bunlarn alma sreleri farkldr. Halbuki RISC tabanl ilemcilerde komutlarn alma sreleri eit olma eilimindedir. Bu durumda girii yapabilmek iin farkl makine komutlar seilebilir. te derleyicinin hz optimizasyonunda en hzl bir biimde alacak komutlar semesi gerekir. Benzer biimde byklk optimizasyonunda da derleyici en az yer kaplayacak makine komutlaryla programcnn istedii ileri yapmaya alr. Genel olarak CISC tabanl ilemcilerde komutlar farkl uzunluklarda olma eilimindedir. Halbuki RISC ilemcilerinde eit uzunluktadr. Komut seimi en nemli problemlerden biridir. Bu aama RISC ilemcilerinde daha kolay, CISC ilemcilerinde daha zor gerekletirilir. nk RISC ilemcilerinde komut says azdr ve aralarnda ciddi bir performans fark yoktur. 208 Komut seimi (instruction selection)

20.13. Yazma Tahsisat (Register Allocation)

Derleyiciler prensip olarak mmkn olduu kadar ok deikeni, mmkn olduu kadar uzun sre yazmalarda tutmak isterler. Genel olarak RISC tabanl ilemcilerde fazla sayda yazma bulunma eilimindedir. ALFA gibi ou RISC ilemcisinde 32 tane genel amal yazma, 32 tane de gerek say yazmac bulunmaktadr. Fakat Intel, Pentium gibi CISC ilemcilerinde yazma says ok azdr. te derleyici yazma says n olmak zere ne zaman ve hangi n tane deikeni yazmata tutacana karar vermelidir. Bu NP tarzda bir problemdir ve eitli hevristic (iyi zm veren) zmleri vardr(ACM de bu konuya ilikin birok makale bulunabilir.).

20.14. Komut izelgelemesi (Instruction Scheduling)

Pek ok programda baz ifadelerin ya da deyimlerin yerlerinin deitirilmesi edeerlii bozmaz. rnein:
x y z k = = = = a; b; c; a;

Burada biz x = a ile k = a y pe pee getirsek de deien bir ey olmayacaktr. Fakat bu sralama performans etkileyebilir. te komut izelgelemesi komutlarn yerlerini deitirerek bundan bir kar salamaya ynelik ilemlerdir. Baz komutlarn baz komutlardan nce yada sonra gelmesi eitli nedenlerden dolay performans etkileyebilir.

20.15. Derleyicilerin Optimizasyon Seenekleri

Optimizasyon mekanizmasna sahip derleyicilerin ounda her bir optimizasyon seenei Duruma gre alp kapatilabilir. Ap kapatma ilemi #pragma komutlaryla kod iinde yaplabilecei gibi komut satrnda derleyici seenekleri ilede yaplabilmektedir. Ayrca IDE li

209

sistemlerde ayarlama ilemi menden yaplabilir. Bylece derleyici komut satrnda bu belirlemeleri kullanabilir. Microsoft ve Borland derleyicilerindeki optimizasyon seenekleri gcc ve intel derleyicilerine gre daha azdr. Seenekleri tek tek ap kapatmak zahmetli olduu iin bu derleyicilerde katagori olarak ap kapatmak seenekleri de vardr.

20.15.1.

Microsoft Derleyicilerindeki Optimizasyon Seenekleri

Microsoft derleyicilerinde /Od seenei derleyici optimizasyonlarn kapatr. Bu durum default durumdur. nk debug ilemleri optimizasyon kapatldnda daha salkl

yrtlmektedir. (komut satrndan c: cl /O1 rnek program)/O1 seenei Sizeof optimizasyonu yapmak iin kullanlr. Yani bu optimizasyon da derleyici hzl almadan ziyade daha az yer kaplayacak kod retmeye alr. /O1 seenei aslnda daha ayrntl olan u seeneklerin hepsinin almasyla edeerdir: /O2 seenei hzl kod retmek iin kullanlan seenektir. Burada derleyici yukarda aklanan optimizasyon temalarn kullanarak kod u hzl alacak hale getirmeye almaktadr. O2 seenei relaese mod iin default durumdur.
Anahtar Notlar: Derleyicinin eitli ayarlarndan bir konfgrasyon oluturulabilir. Microsoft ide lerinde proje oluturulduunda 2 temel konfgraasyon yaratlm durumdadr. Bunlarda biri Debug dieri relaese knfgrasyonlardr. Fakat programc isterse baka konfgrasyonlarda oluturabilir. Debug konfgrasyonu proje yaratldnda default aktif olan konfgrasyondur. Konfgrasyon deitirmesi Ara ubuundan ya da buid/Confgrasyon manager mensnden yaplabilir. Debug konfgrasyondaki default optimizasyon seenei /Od Relaese konfgraasyondaki ise /O2 dir.

/Od seenekleri /Ob0 /Ob1 ya da /Ob2 biiminde kullanlr. Bu seenek Inline fonksiyon amlar iin kullanlmaktadr. /Ob0 Inline ilemini kapatr ve default durumdur. /Ob1 inline anahtar szc ile belirtilmi fonksiyonlar amaya alr. /Ob2 inline belirlemesi yaplmam olsa bile derleyicinin uygun fonksiyonlar inline aabilmesini salar. /Ob seeneklerinin kullanlabilmesi iin mutlaka /O1 ya da /O2 ya da /Og seeneklerinin kullanlm olmas gerekir.
Anahtar Notlar: zellikle C++ da inline fonksiyonlar youn kullanlr. nk snfn private elemanlarna erimekte kullanlan get ve set fonksiyonlar youndur. Programcnn derleyicinin inline amn yapabilmesi iin en azndan /O1 ya da /O2 seenekleri iinde olmas gerekir. Mademki /Od proje yaratldnda default durumdur. O halde bu durumda microsoft derleyicileri kesinlikle am yapmamaktadr.

210

Microsoft derleyicilerindeki tm optimizasyon seenekleri /Oxxx biiminidedir. Yani bu seenekler /O karakteriyle balamaktadr. Yukarda da belirtildii gibi /O1 ve /O2 aslnda bir seenek grubudur. Optimizasyon konusunda aklanan alt ifadelerin elimine edilmesi gibi ok kullanlan deikenlerin yazmata tutulmas gibi dng de deimeyen ifadelerin dng dna karlmas gibi optimizasyon temalarnn ou /Og seenei ile aktif hale getirilmektedir. Kategori olarak /O1 ve /O2 seenekleri aldnda zaten /Og de otomatik olarak alr. Fakat biz /O1 ya da /O2 yi kullanmadan /Og seeneini kullanabiliriz. Dier optimizasyon seenekleri derleyici

dkumanlarndan izlenebilir.

20.15.2.

GCC Derleyicilerindeki Optimizasyon Seenekleri

GCC derleyicilerinde -fxxx biiminide yani -f harfleriyle balayan pek ok optimizasyon seenei vardr. Neredeyse her bir optimizasyon temas iin ayr bir seenek bulunmaktadr. Fakat bu kadar seenein alp kapatlmas ok zahmetlidir. Bunun yerine gcc programclar yine baz kategorileri kullanrlar. nemli kategoriler unlardr. -o0: Bu durum default durumdur.(gcc -O0 program ad) Bu seenek optimizasyonu kapatmaktadr. Microsoft un /Od seeneine karlk gelmektedir. -o1: Bu seenek temel baz alt optimizasyon seeneklerini aktive etmektedir. Hangi alt optimizasyon seeneklerinin aktive edildii burada ele alnmayacaktr. Fakat -o1 seenei temel optimizasyonlar yerine getiren bir seenektir. Bu seenekte daha fazla optimizasyon seenei alm durumdadr. Fakat bu seenekte alan alt seenekler kod u ar biimde bytmemektedir. -o2: -o1 seeneinden farkl olmaqk zere derleme sras daha uzar pek ok ak yazlm (rnein Linux iletim sistemi) bu seenekle derlenmektedir. -o3: Agresif optimizasyon seeneidir. Dng am gibi optimizasyonlarda bu seenein iindedir. Kod daha hzl alacak hale getirilir. Fakat bu seenek kod bymesine de yol amaktadr. -os: Bu seenek microsoft un /O1 seeneine benzer Size optimizasyonu yapmaktadr. [Ek - 1] Options That Control Optimization

211

21. BELLEK LEMLER


Bilgisayar ortamnda bilgilerin daha sonra ilenmesi iin sakland birimlere bellek denir. Bellekler birincil(primary) ve ikinci(secondary) olmak zere iki blme ayrlmaktadr. Birincil belleklere ana bellek(main memory) denilmektedir. CPU ile elektriksel olarak dorudan balantl belleklere 1.cil bellekler denir. Bu bellekler tarihsel geliim dikkate alndnda RAM ve ROM bellekler olmak zere ikiye ayrlr. Birincil Bellek

RAM Random Access Memory

ROM Read Only Memory

PROM

SRAM

DRAM
EPROM EEPRO M

RAM ler hem okunabilen hem yazlabilen yar ,letken belleklerdir. Kendi aralarnda statik ve dinamik olmak zere iki blme ayrlmaktadr. SRAM ler ok transistrle Flip Flop biiminde tasarlaanmlardr. rnein bir bit iin bir SR tarzda tutucu devre 2 logic kap iermektedir. Bu logic kaplar birden fazla taransistrle gerekletirilir. SRAM ler ok hzldr. (Tipik 1 nano saniyenin altnda) Fakat bu RAM ler greli olarak daha byk yer kaplar daha pahaldr. Tm bilgisayar belleini SRAM olarak oluturmak yerine Cache sistemi kurarak Cache sistemini SRAM olarak oluturmak daha ekonomiktir.

212

DRAM belleklerin 1 biti tipik olarak bir tansistr bir kapasitr olarak tasarlanmtr. Kapasitif elemann belirli periyotlarda arj edilmesi gerekir ve buna tazeleme denilmektedir ve DRAM lerin en nemli problemidir. Pek ok CPU nun DRAM lar tazelemek iin zel ular bulunmaktadr. Bugn kullandmz DDR tarz RAM ler de DRAM grubundadr. DRAM larn hzlar 10 nano saniye ivarna kadar drlmtr. Daha ucuzdur ve daha az yer kaplamaktadr. ROM lar g kaynan kesince bilgiyi tutmaya devam eden yar iletken birincil belleklerdir. Tarihsel sre iinde evrim geirmilerdir.
Anahtar Notlar:

RAM CPU ROM

Her bilgisayar sisteminde bir ROM blgesinin olmas gerekir. Micro ilemciler ve Micro Denetleyiciler Reset edildiinde alma belli bir adresten balar. Buna Reset Vektr denilmektedir. Genellikle reset vektrleri ya bellein banda ya da sonunda bulunur. Bilgisayarn g kaynan atmzda RAM blgesi sfrlandna gre ve CPU reset vektrnden almaya baladna gre reset vektrnde hazr bir programn bulunmas gerekir. te reset vektrnn bulunduu blgenin Rom blm iinde bulunuyor olmas gerekir. Bylece bilgisayar kapattmzda RAM blgesi silinir fakat ROM blgesindeki bu programlar kalmaya devam eder. (POST Power on self test)ROM da altrlan ilk kod POST denilen self test programdr. Masast sistemlerde daha sonra sra iletim sisteminin yklenmesine gelir. Yani iletim sisteminin yklenmesi tamamen ROM dan balatlan bir eylemdir. Pek ok micro denetleyici sisteminde bir iletim sistemi olmadan allr. Bu tr sistemlerde programc yazd program micro denetleyicinin iindeki ROM alanna aktarr. Bylece Micro denetleyici reset edildiinde alma ROM a yerletirilmi programdan balam olur.

Tarihsel olarak ilk ROM tr belleklere PROM (Programmable ROM) denilmektedir. Bu belleklere genellikle retici firma tarafndan yalnzca 1 kez bilgi yerletirilir. Daha sonra uzun yllar EPROM lar(Erasable Proagrammable ROM) retilmitir. EPROM lar zel EPROM silicilerle silinerek yeniden programlanabilmektedir. Nihayet son teknoloji olarak EEPROM (ElectricalyErasable Proagrammable ROM) denilen ROM tr bellekler tasarlanmtr. Bu tr bellekler RAM gibi ROM dur. Yani bunlara hi silmeden program yerletirilebilir. Bu ilem iin zel bir devreye gereksinim duyulmaz ve g kayna kesilince de bilgiyi tutarlar. Benzer bir teknoloji de Flash EPROM teknolojisidir. EEPROM ve Flash EPROM ok benzer yapdadr. Bugn kullandmz MP3 valar gibi ev bilgisayarlar gibi tanabilir bellekler gibi birimler hep 213

bu

biimde

retilmektedir.

Bylece

bu

cihazlara

firma

tarafndan

yerletirilmi

programlar(firmware) gncellenebilmektedir. Bugnk masast bilgisayarlarda ve tanabilir bilgisayarlardaki ROM tarz bellekler Flash EPROM belleklerdir. rnein bilgisayar Reset edildiinde alan program ve kesme kodlarn BIOS update yaparak yenisiyle yer deitirebilmekteyiz. kincil Bellekler

21.1.

Bu bellekler CPU ile dorudan balantl olmayan

bilgisayar sistemi kapatldnda

bilgilerin kalc olmasn salayan belleklerdir. Tipik olarak diskler floppy disketler, CD ve DVD ler, flash EPROM teknolojisi ile oluturulmu memory stikler, teyp bantlar Diskler bugn iin en nemli ikincil belleklerdir. Belki gelecekte disklerin yerini EEPROM veya Flash EPROM lar alabilirler.

21.2.

Disk lemleri

Disk terimi floppy disketleri de iine alan manyetik tabanl medyalar iin kullanlmaktadr. Diskin her yzeyi track denilen yuvarlar yollardan olumaktadr. Disk kafas track hizasna getirilir, kafa yzeye demez ama ok yaklar, okuma ve yazma ilemleri disk dnerken kafa tarafndan yaplmaktadr. Disk birden fazla yzey ieriyorsa her yzey ayr bir kafa tarafndan okunur ve yazlr. Kafalar ayn eksene monte edilmitir, birlikte hareket eder. Hard diskler bir ubuk ierisine geirilmi birden fazla platterdan oluabilmektedir. platter platter rnein 2 platterl bir hard disk 4 yzeyden olumaktadr. Bu drt yzn her biri kafa tarafndan okunur. Yz says ile kafa says ayn anlamdadr. Diskin dn hz dakikadaki devir says ile belirtilir. rnein floppy disketler 360 RPM civarnda dnmektedir. Hard disklerdeki dn hzlar, hard diske gre deiebilmektedir. rnein tipik olarak 5400, 6000, 7200, 9000 gibi deerler sz konusudur.

214

Ayn zamanda diskin her yzeyi mantksal olarak pasta dilimlerine ayrlmtr. Bu dilimlere sektr dilimleri denir.

Sektr dilimi

Sektr

Tracklerin sektr dilimleri ierisinde kalan her bir parasna sektr denilmektedir. Sektr bir diskten okunabilecek ya da diske yazlabilecek en kk birimdir. Sektrlerin yay uzunluklar farkl olsa da her sektrde eit uzunlukta bilgi vardr.

Anahtar Notlar: Son 10 senedir hard disk teknolojisinde baz deiiklikler yaplmtr. rnein her sektre eit sayda bayt yerletirmek yerine d sektrlere daha fazla bilgi yerletirmek yoluna gidilmektedir. Burada klasik sektr tanmnn dna klsa da gene sektr kavram muhafaza edilmitir. Yani disk bize, bizde diske yine sektr numaras vererek eriiriz. Anlatmmzda nceki teknoloji dikkate alnmakla birlikte aslnda iki sistem arasnda soyutlama bakmndan nemli bir fark yoktur.

Bir diskin hz sektr transferi ile belirtilmektedir. Bir sektrn ortalama olarak ka msnde yazlp okunduu bir hz gstergesidir. Bugn en iyi diskler bu hz 6 msn civarndadr. Ortalama bir diskte 12 msn civarndadr. phesiz bir sektrn okunmas ya da yazlmas kafann o andaki durumu ile ilgilidir. Ortalama hzlar simlasyon yoluyla elde edilmi deerlerdir. Bir sektrn transferi ile ilgili transfer zamann etkileyen 3 bileen vardr. 1. Kafann Konumlanma Sresi (Seek Time): Bu sre kafann bulunduu durumdan transfer edilecek sektrn bulunduu track hizasna konumlandrlmas iin gereken zaman belirtir. Bu sre hz asndan etkili olan en nemli bileendir. 2. Dnme Zaman (Retational Delay): Transfer edilecek sektrn bulunduu dilimin dnerek kafa hizasna gelmesi arasnda geen sredir. Hz konusundaki ikinci nemli bileeni

215

oluturur. phesiz bu sre diskin dn hzyla ilgilidir. O halde hzl dnen disklerin greli olarak biraz daha hzl olmas beklenir. 3. Transfer Zaman: Bu zaman kafann sektr okuyarak d dnyaya ilettii zamandr. Greli olarak en ksa zaman budur.

21.3.

Disk IO lemi

Tipik bir bilgisayar sisteminde anakart zerinde diskleri ynetmek iin bir disk denetleyicisi denilen ilemci bulunmaktadr. Sistem programcs bu ilemciyi programlayarak sektr transfer isteini sisteme bildirir. Disk denetleyicisi hard disk zerindeki ilemcileri programlayarak transfer ilemini balatr. Sistemlerin ounda CPU anakart zerindeki ilemciyi programladktan sonra artk bota kalr. Sektrn bellee aktarm DMA(direct memory Access) denilen yardmc bir ilemcinin kontrolnde yrtlmektedir. Disk denetleyicisi ilem bittikten sonra bir kesme yoluyla bunu CPUya bildirir. Bu aktarm ekilsel olarak yle gsterilebilir:

C P U

B E L L E K

DMA

Programc

Disk Denetleyici

Bu transfer ilemindeki nemli noktalar unlardr:

216

CPU yani bizim programmz aslnda yalnzca disk denetleyicisini ve DMAy programlamaktadr. Geri kalan ilemlere CPU karmaz.

Diskten bellee aktarm DMA denilen ilemci yardmyla otomatik gerekletirilir. CPU yani programz ilemi balatr. Fakat ilem bitene kadar bekler. ok ilemli sistem (multi threading) sistemlerde tipik olarak ilgili proses yada thread ilem bitene kadar izelge dna kartlarak blokede bekletilir.

Transfer bittiinde donanm kesmesi yoluyla CPU durumdan haberdar edilir bylece iletim sistemi devreye girerek prosesi yada threadi yeniden izelgeye sokar.

Anahtar Notlar: Tipik olarak ok ilemli iletim sistemlerinde izelgede prosesler ya da threadler bir kuyruk sistemi ile ifade edilir. Bloke olutuunda ilgili proses ya da thread bu kuyruk sisteminden kartlp bir bekleme kuyruuna (wait queue) alnr. Genellikle bekleme kuyruu bir tane deildir. Deiik olaylar iin deiik bekleme kuyruklar vardr.

21.4.

Sektr Transferi leminin Programlama Yolu ile Gerekletirilmesi

Tipik olarak PC sisteminde daha iletim sistemi bile yklenmeden yukarda akland gibi disk denetleyicisini ve DMAy programlayarak transferi gerekletiren makine dilinde yazlm ROM bellekte bulunan bir kod vardr. 13H kesmesi diye bilinen bu kod silinmeyecek biimde her zaman hazrda bulunmaktadr. Bylece iletim sistemi yklenirken bu kodlardan

faydalanlmaktadr. Fakat iletim sistemi yklendikten sonra artk transfer ilemi iin iletim sisteminin kendi kodlar kullanlr. Windows sisteminde tipik olarak bu ilerden sorumlu bir aygt src vardr. Sistem program ise aygt srcden istekte bulunur ve bylece kernel moda geilir, transfer yaplr. Linux sistemlerinde ayn biimde aygt srcler yoluyla transfer yaplmaktadr. /dev dizininde bulunan hda, hdb gibi hard diskleri temsil eden aygt srcler open fonksiyonu ile alr ve sektr okuma yazma ilemleri read/write fonksiyonlaryla dosya ilemi gibi gerekletirilir. Kursumuzda Windows sistemleri altnda sektr transfer edebilmek iin aygt srcleri kullanan ReadSektor ve WriteSektor gibi iki fonksiyon yazlmtr ve bunlar kullanlacaktr. phesiz bu fonksiyonlar kendi ilerinde aygt srcleri kullanarak transfer ilemini yapmaktadr.

217

Aygt srcde yukarda anlatld gibi disk denetleyicisini ve DMAy programlayarak ilemini yapmaktadr.

21.5.

Sektrlerin Numaralandrlmas

Transfer ilemi iin sektrlerin numaralandrlm olmas gerekmektedir. Bunun iin iki koordinat sistemi kullanlmaktadr. Bunlar fiziksel ve mantksal sistemlerdir. Fiziksel koordinat sisteminde sektrn yeri kafa: thread: sektr dilimi biiminde 3 bileenle belirlenir. Kafa ile yzey ayn anlamdadr. Yzeylere sfrdan balayarak numara verilmitir. Trackler de sfrdan balayarak numaralandrlmtr. En dtaki track 0 numaral tracktir. Son bileen sektr dilimidir. Her sektr diliminin de bir numaras vardr. Sektr dilimleri birden balayarak

numaralandrlmtr. rnein 3:28:5; 3. yzey, 28. thread, 5. sektr dilimi ile belirlenen sektr gsterir. Mantksal koordinat sisteminde sektrn yeri tek deerle belirtilir. Her sektre bir numara verilmitir. Numaralandrma yle yaplmtr. 0h:0t:1s numaral sektr 0 olmak zere nce sektr dilimleri, sonra kafalar, sonra trackler dolalarak artan sayda numaralandrma sz konusudur.
for (track) for (head) for (sektr dilimi)

Eer sektr dilimlerinin says ve kafa says bilinirse mantksal sektr fiziksel sektre, fiziksel sektr de mantksal sektre dntren formller yazlabilir.
Anahtar Notlar: Disk ile ilgili bir kavram da silindir kavramdr. Silindir her yzeydeki yani kafadaki n numaral tracklerden oluan kmedir. rnein 4 yzeyli yani kafal bir disk dnelim. 5. silindir demek 0. yzdeki 5. track, 1. yzdeki 5. track, 2. yzdeki 5. track ve 3. yzdeki 5. trackin oluturduu kmedir.

21.6.

letim Sistemlerinin Dosya lemlerine likin Disk Organizasyonlar

Programcya gre bir dosya ardk bayt topluluundan oluan bir kavramdr. Fakat aslnda dosya mantksal bir kavramdr ve iletim sistemi tarafndan organize edilmektedir. Aslnda diskte

218

tek gerek sektr kavramdr. Dosya yksek seviyeli ve uydurma bir kavramdr. Aslnda bir dosyann paralar disk zerinde eitli sektrlere yaylmtr. letim sistemi dosyann hangi paralarnn hangi sektr zerinde olduunu bir biimde bilmektedir. letim sistemi diskte sektrlere yaylm olan paralar bize sanki ardk bir bilgiymi gibi gstermektedir. letim sisteminin dosya alt sisteminin iki nemli blm vardr. Bunlardan biri bellekte yaplan organizasyonlar ile ilgilidir. Dieri diskte yaplan organizasyonlar ile ilgilidir. Bu nedenle birine bellek taraf dierine disk taraf denir. Bir dosya aldnda bellekte oluturulan veri yaplar disk cache sistemi bellek tarafna ilikin konulardr. Dosyalarn hangi sektrde saklanaca, dosyalarn hangi paralarnn hangi sektrlerde bulunaca disk tarafna ilikindir.

21.7.

Cluster ya da Blok Kavram

Dosyann paralarnn disk zerinde rasgele sektrlerde bulunmas dosyaya erimek iin gereken kafa hareketlerini fazlalatrr dolaysyla performans drr. O halde ilk akla gelecek organizasyon dosyann paralarn ardk sektrlere yerletirmektir. Fakat dosyann ardk sektrlere yerletirilmesi blnme (fragmentation) denilen probleme yol amaktadr. Blnme bellek konusuna ilikin nemli kavramlardan biridir. Disk

219

Bir dosyann paralar diskte ardl yerletirilmek zorunda deildir. Eer byle bir zorunluluk olsayd, dosyalarn tahsis edilip silinmesi srecinde blnme(fragmentation) durumu oluurdu.

Blnme ok sayda kk fakat ardl olmayan bo blgelerin olumas anlamna gelir. Blnme kavram yalnzca disk iin deil her trl bellek sistemi iin sz konusudur. rnein heap blgeside zamanla blnmeye maruz kalmaktadr. Yani heap blgesinde de ok sayda kk alanlar oluabilmekte ve orta byklkte tahsisatlar bile yaplamayabilmektedir. Blnme sorunu ardl yerlestirme zorunluluunun ortadan kaldrlmasyla zmlenebilir. Bylece kk paralarda byk bir birimin paralar olarak kullanlabilir. Blnmenin ortadan kaldrlmas iin tipik olarak ilgili bellek eit uzunlukta bloklara ayrlr. Yerletirme ilemi blok temelinde gereklestirilir. pesiz yerletirilen bilginin hangi paralarnn hangi bloklarda olduu bir biimde tutulmaldr. Bir dosyann paras olabilecek en kk birime cluster yada blok denilmektedir. letim sistemi diski eit uzunlukta cluster yada bloklara ayrr, dosyann paralarnda cluster yada bloklara yerletirir. pesiz her dosyann hangi numaral parasnn hangi cluster yada blokta bulunduu bir biimde tutulmaldr. Bu sistemin anahtar noktalar unlardr. - Disk yada volume eit uzunlukta cluster yada bloklara ayrlmtr.

0 5 10

1 6

2 7

3 8

4 9

rnein diskimiz 100k uzunlukta olsun. Bu durumda diskimizde toplam 100 cluster yada blok vardr. Bunlar 0 dan 99 a kadar numaralandrlm olucaklardr.

220

- letim sistem dosyalar paralara ayrr ve bo olan cluster yada bloklara yerletirir, ve bunu bir biimde bir yerde tutar. rnein yukardaki diski dikkate alalm, 6k lk bir dosya iletim sistemi tarafndan 6 farkl cluster yada bloa yerletirilecektir. Bunlarn 8 9 13 14 25 - 26 numaral bloklar olduunu farz edelim. letim sistemin bu dosyalarn bu paralarnn bu yerlerde olduunu bir yerde tutmas gerekir. - Cluster yada blok kavram iletim sisteminin belirledii mantksal byklktr. Diskteki gerek fiziksel byklk sektr kavramdr. Bir cluster yada blok ardl 2 zeri n sektr olabilir. rnein 1, 2, 4, 8, 16, 32 gibi. - Bir cluster yada blok ka sektrden olumaldr ?. Eer bir cluster yada blok az sektrden oluursa, dosyann paralar diske ok yaylr, bu da diskin kap hareketlerini fazlalatrr ve performans drr. stelikte dosyann hangi paralarnn hangi cluster yada bloklarda tutulmas daha fazla yer gerektirir. Bir cluster yada blok ok sayda sektrden oluursa bu sefer isel blnme (internal fragmentation) artar. sel bnme her dosyann son parasnn yerletirildii cluster yada blokta bo alanlarn olumas durumudur. rnein bir cluster yada bloun 1k olduu bir sistemde 1500 byte uzunluktaki bir dosya 2 cluster yada blok yer kaplayacaktr. Bu durumda (2048 1500) byte lk bir alan boa harcanm olacaktr. sel blnme sfrlanamaz fakat bir cluster yada blok ne kadar az sektrden oluursa ona bal olarak azaltlabilir. O halde bir cluster yada bloun ka sektrden olumas gerektii iin unlar sylenebilir : Cluster yada blok ne kadar az sektrden oluursa, isel blnme miktar o kadar azaltlr, fakat disk performans o oranda ktleir. Bu nedenle iyi bir noktann bulunmas gerekir. Eer disk kkse alan daha nemlidir. Bu durumda bir cluster yada bloun daha az sektrden olumas anlamldr. rnein flopy disketlerde bir cluster yada blok 1 sektrdr. Fakat medya bydke alan ok olduuna gre hz daha nemli duruma gelir. rnein byk disklerde 1 clustrer yada blok 16 yada 32 sektr kadar olabilir. Bir cluster yada bloun ka sektrden oluacana formatlama srasnda karar verilmektedir. letim sistemi dosyann paralarn pesiz mmkn olduunca ardl cluster yada bloklara yerletirir. Fakat zamanla dosyalarn paralar disk de yaylabir. Defrag gibi programlar dosyalarn cluster yada bloklarn birbirine yaknlatrmaktadr. pesiz her trl dosya sisteminde cluster yada blok kavram kullanlmak zorunda deildir. rnein read-only medyalardaki dosya sistemlerinde dosyalarn paral yerletirilmesinin bir anlam yoktur. nk dosyalar silinp yerine baka dosyalar yaratlmayacaksa pek ala dosyalar ardl bir biimde depolanabilir. Cd lerdeki ve teyip bandlarndaki durum byledir.

221

21.8.

eitli letim Sistemlerinin eitli Disk Organizasyonlar

eitli iletim sistemleri diski kendilerine gre organize edip dzenlemeleri oluturmutur. Microsoftun dos iletim sistemin dosya sistemine fat sistemi denilir. Daha sonra Microsoft bu dosya sistemini biraz geniletmitir ve Windows sistemlerinde kullanlan bu geniletilmi FAT sistemine VFAT denilmektedir. Daha sonra Microsoft NTFS diye isimlendirilen ok ayrntl ve geni dosya sistemini oluturmutur. Bugnk Windows sistemler tm bu dosya sistemleri tarafndan organize edilmi olan diskler zerinde ilem yapabilmektedir. Unix trevi sistemlerin dosya sistemleri birbirinden farkl olsada birbirlerine benzemektedir. Btn bu dosya sistemlerine ksaca inode sistemler denilmektedir. lk unix sistemlerinde UFS diye isimlendirebileceimiz klasik bir dosya sistemi kullanlyordu. BSD trevi sistemler FFS (Fast File System) ismi ile bu dosya sistemine eklemeler yapmtr. Linux sistemlerinde ext, ext2, ext3, reiser fs biiminde isimlendirilen fakat bu sistemlere ok benzeyen dosya sistemleri kullanlmaktadr. Bunlar dnda irili ufakl pek ok dosya sistemide vardr. rnein OS/2, HPFS IBM tarafndan uzun sre kullanlmtr. Cd lerde ve DVD lerde kullanlan ISO 9660 ve trevleri hemen her iletim sistemi tarafndan desteklenmektedir.

21.9.

Disk Organizasyonlar Fat Trevi Dosya Sistemlerinin Disk Organizasyonlar

Bugn hala Microsoft tarafndan desteklenen Microsoft un fat sistemi basit ve temel bir disk organizasyonudur. VFAT bunun zerine baz eklemeler yapmtr. Fakat temel mantk ayndr. NTFS yine FAT tablosu kullanmakla birlikte olduka karktr ve hala tam olarak Microsoft tarafndan dkmante edilmemitir. O halde bir disk organizasyonun ayrntlar iin incelenecek en temel sistem FAT dosya sistemidir. Bir diski FAT dosya sistemi ile formatladmzda diskte 4 blm oluur. 1) Boot Sektr : 512 byte uzunluundadr (1 sektr uzunluunda) ve diskin tm parametrik bilgileri bu sektde tutulur. 2) FAT : (File Allocation Table) hangi dosyalarn hangi paralarnn hangi clusterlarda olduu bilgisini tutan bilgidir. FAT dosya sistemi bu tablo sisteminin yapsna gre FAT12, FAT16 ve FAT32 olarak 3 biime ayrlr.

222

3) Root Dir : Bu blm kk dizindeki dosyalar tutan blmdr. 4) Data : Dosya paralarnn depoland ana blmdr. Data blmndeki cluster lar yukarda akland gibi numaralandrlmtr.

Anahtar Notlar Bir diski manuel olarak incelemek iin disk editrleri denilen zel programlar kullanlr. Bu programlar sayesinde disk sektr sektr incelenebilir ve dosya sistemine bal olan pek ok disk blm incelenebilir. Disk editr programlarnn en nllerinden birisi Norton isimli programdr fakat uzun sredir gncellenmemitir. Yine WinHex isimli program Disk Editr olarak kullanlabilmektedir. Anahtar Notlar Bir hard disk e tamamen birbirlerinden bamsz birden fazla iletim sistemi ve dolaysyla dosya sistemi kurulabilir. Bir hard disk in birbirinden bamsz sanki ayr bir diskmi gibi kullanlan her bir blmne bir disk blm (partitian) denilmektedir. rnein biz bir disk blmne window su dierine Linux u kurabiliriz. Bu iki sistem birbirleri ile karmaz. Bir iletim sistemi dierinin disk alann bozmaz. Hard disk in ilk sektrnde disk blnleme tablosu (partitian table) denilen bir tablo vardr. Bu tablo da tm disk blmlerinin nereden balad ve ne kadar uzunlukta olduu bilgisi bulunmaktadr. Her disk blmne farkl bir iletim sistemi kurulaca gibi hi iletim sistemi kurmadan sadece organizasyon yaplabilir. Yani rnein biz hard diskimizi iki disk blmne ayrp ikisinide NTFS olarak organize edebiliriz. Windows sisteminde birinci partitian a ykleyebiliriz.

21.10.

Boot Sektr

Boot Sektr fat dosya sisteminin ilk sektrdr. Fat dosya sistemi ile formatlanm her disk blmnn ayr bir boot sektr vardr. Boot Sektr ilgili volumun ilk sektrdr. pesiz flopy disketlerde blmlendirme kavram olmad iin Boot Sektr flopy sektrn ilk sektr durumundadr. Boot sektr kendi iersinde 2 blmden oluur.

BPB (Bios Parameter Block)

Ykleyici Program

223

BPB FAT dosya sisteminin kalbidir. Burada bir tablo vardr ve bu tablo dosya sisteminin btn parametrik bilgilerini tutar. (rnein biz bir disk editrle 40-50 byte uzunluunda olan BPB tablosunu bozarsak artk iletim sistemi bu disk blmne eriemez.). Boot sektr BPB blounun format yledir :

Offset Hex(decimal) 0(0) 3(3) B(11)

Uzunluk

Anlam

3 BYTE 8 BYTE WORD

Jmp Code OEM yorum Sektrdeki byte says

D(13)

BYTE

Clusterdaki sektr says

0E(14)

WORD

Ayrlm sektrlerin says

10(16)

BYTE

FAT says

kopyalama

11(17)

WORD

Root says

girilerinin

13(19)

WORD

Toplam says

sektr

15(21)

BYTE

Ortam belirleyicisi

16(22)

WORD

FAT

in

bir

kopyasnn sektr uzunluu 18(24) WORD Sektr dilimlerinin says 1A(26) WORD Kafa says

224

1C(28) 20(32)

DWORD DWORD

Sakl sektr says Yeni toplam

sektr says 27(39) 8 BYTE Volume number 2B(43) 11 BYTE Volume label serial

Jmp Code BPB

Ykleyici program

Jump code : Burada BPB blmn atlayarak ykleyici programa dallanan intel 80x86 ilemcilerine ilikin bir jump komutu bulunur. OEM yorum : Buradaki 8 byte dikkate alnmamaktadr format programlar genellikle bu alana iletim sisteminin versiyon numarasn yazmaktadr. Sektrdeki byte says : Burada disk sektrnn ka byte dan olutuu bilgisi yer almaktadr. Tipik olarak burada 512 deeri bulunmaktadr. Cluster daki sektr says : Burada bir cluster n ka sektrden olutuu bilgisi yer almaktadr. Ayrlm sektrlerin says : Burada boot sektrden sonra, boot sektrde dahil olmak zere FAT sektrne kadar ka bo sektrn bulunduu bilgisi vardr. Baka bir deile burada FAT blmnn balang mantksal sektr numaras bulunur. rnein burada 1 deerinin bulunmas boot sektrden hemen sonra FAT blmnn geldiini belirtir. Yani arada boluk yoktur. FAT blmnn bazen sonraki track den balatlmas tercih edilebilir. FAT kopyalama says : FAT blm nemli olduu iin onun birden fazla zde kopyasnn tutulmasnn faydal olaca sanlmtr. Fakat birden fazla FAT dosyasnn ciddi bir

225

faydas grlmemitir. Microsoft eskiden beri FAT in 2 kopyasn bulundurmaktadr. Dolaysyla bu alanda 2 says grlecektir. Root girilerinin says : Rootdir blmnde kk dizindeki dosya bilgileri yer alr. Her dosya bilgisi 32 byte lk giriler ile ifade edilmektedir. Bu blgede aslnda dolayl olarak rootdir blmnn sektr uzunluu belirtilmektedir. Burada yazlan say 32 ile arplp 512 ye blnrse rootdir blmnn sektr uzunluu elde edilir. Toplam sektr says : Burada eskiden volum n ka sektrden olutuu bilgisi yer almaktayd. Maalesef Microsoft 1981 ylnda bu format (BPB) tasarladnda disk lerin bu kadar byyeceini dnmemi. Bu nedenle toplam sektr says iin 2 byte lk yer ayrmtr. Gerektende 1986/87 ye kadar, yani dos 4.01 versiyonuna kadar srf bu yzden volume deki sektr says 65535 ile snrlanmtr. 40Mb ve 60Mb lk disklerin km olmasna karn dos 3.30 da ve daha ncesinde bir disk blm 33Mb geemiyordu. nk 2 9 216 = 2 25 33Mb. Fakat daha sonra Microsoft dos 4.01 ile toplam sektr says alann 4 byte a ykseltmitir. Gemie doru uyumu korumak iin BPB nin 20h ofsetin de yeni bir 4 byte lk toplam sektr says alann oluturmutur. Bugn iletim sistemleri nce 13h ofsetine bakmaktadr, eer buradaki deer 0 (sfr) ise 20h ofsetindeki 4 byte dikkate almaktadr. Ortam belirleyicisi : Burada ki 1 byte lk say volum n nasl bir medya ierisinde olduunu belirtmektedir. rnein F8 hard disk anlamna gelmektedir. FAT in bir kopyasnn sektr uzunluu : FAT in bir kopyasnn sektr uzunluu rootdir alann balangcnn belirlenmesi iinde gerekmektedir. FAT blm ileride ele alnacaktr. Sektr dilimlerinin says : Burada toplam sektr dilimlerinin says yer almaktadr. Kafa says : Burada disk in ka kafaya sahip olduu yani ka kafaya sahip olduu bilgisi yer almaktadr. Sakl sektr says : Sakl sektr kavram ciddi anlamda kullanlmamaktadr. Sakl sektr aslnda ilgili volume n boot sektrnn yerini belirlemekte kullanlmaktadr. Yani boot sektrden nce diskte ki sektr says burada yer alyor olsada bu alann ciddi bir kullanm yoktur. Yeni toplam sektr says : Burada eskiden 2 byte ile ifade edilen toplam sektr saysnn 4 byte lk yeni biimi bulunmaktadr. Volume serial number : Disk formatlandnda rastgele retilmi olan 8 byte lk bir deer boot sektre yazlmaktadr. pesiz bu deer baka bilgisayarlardaki disklerde ki deerlerle

226

akabilir. Genellikle disketlerde disket deitirmeler srasnda olas hatalar engellemek iin kullanlmtr. Volume label : Volume label hem kk dizinde bir dosya ismi olarak hemde boot sektrde giri olarak bulunmaktadr.

21.11.

Sektr okuma yazma ilemleri

Makine ilk aldnda henz iletim sistemi bile ykl deilken, sektr okuyup yazma ilemleri iin, makine dilinde yazlm olan BIOS fonksiyonlar kullanlabilir. letim sistemi de bu fonksiyonlar kullanarak okuma yazma yapmaktadr. letim sistemi yklendikten sonra kendisi de sektr okuyup yazmaya ynelik mekanizmalar sunmaktadr. Kod korumal modda alan iletim sistemlerinde, BIOS fonksiyonlar dorudan kullanc tarafndan kullanlamaz. Artk bu sistemlerde iletim sisteminin saladu olanaklarla bu ilemler gerekletirilir. Windows sistemlerinde aygt src yoluyla sektr okuma yazma ilemleri gerekletirilmektedir. Fakat 95 grubu sistemlerle, NT grubu sistemler farkl aygt srcler kullanlmaktadr. Unix/LINUX sistemlerinde tpk Windows sistemlerinde olduu gibi dosya sistemleri de birer aygt src biiminde sisteme dahil edilmektedir. Dolaysyla NT grubu sistemlerde olduu gibi ilgili aygt src dosyas alp, read-write ilemleri yapldnda, zaten sektr okuyup yazma ilemleri gerekletirilmi olur. Kursumuzda Windows sistemleri altnda aygt src armas yaplarak sektr okuma yazma ilemleri c++ da bir snf biiminde olturulmutur. Ayrca bu snf kullanlarak C den arlabilecek sarma fonksiyonlar da oluturulmutur. Kursumzda yazlm olan fonksiyonlar kullanabilmek iin ncelikle OpenDisk fonksiyonunun arlmas gerekir. Prototipi yledir.
HWIN32DISK OpenDisk(int volume);

Fonksiyonun parametresi alacak volume belirtir. A = 0; B = 1; gibi. Fonksiyon baar durumunda handle deerine, baarszlk durumunda NULL adrese geri dner. Volume kapatmak iin CloseDisk fonksiyonu kullanlr.
void CloseDisk(HWIN32DISK hW32Disk);

227

Parametre olarak handle deerini almaktadr. Sektr okuma iin ReadSector fonksiyonu kullanlr.
BOOL ReadSector(HWIN32DISK hW32Disk, DWORD dwStart, WORD wNumberOfSectors, PVOID pBuf);

Fonksiyonun birinci parametresi HANDLE deeri, ikinci parametresi balang mantksal sektr numarasn belirtir. nc parametre okunacak sektr saysn belirtir. Son parametre tranfer edilecek yerin adresidir. Write sector fonksiyonu da ayn parametrik yapya sahiptir.
BOOL WriteSector(HWIN32DISK hW32Disk, DWORD dwStart, WORD wNumberOfSectors, LPCVOID pBuf);

Kullanm yle olabilir.


HWIN32DISK hW32Disk; unsigned char boot[512]; if ((hW32Disk = OpenDisk(5)) == NULL) { fprintf(stderr, "Cannot open file!...\n"); exit(EXIT_FAILURE); } if (!ReadSector(hW32Disk, 0, 1, boot)) { fprintf(stderr, "Cannot read disk!..\n"); exit(EXIT_FAILURE); } CloseDisk(hW32Disk);

21.12. BPB blmnn Elde Edilmesi

FAT dosya sisteminde BOOT sektr-BPB blmm kritik nemlidir. Gerekten iletim sistemi de her disk eriiminde buradaki bilgilerden faydalanr. Tabii her defasnda BPB yi okumak yerine eer harddisk szkonusu ise al srasnda bir kez okumak daha anlamldr. BPB bilgilerini ele geiren aadaki gibi bir fonksiyon yazlabilir.

BOOL GetBPB(HWIN32DISK hW32Disk, BPB *pBPB);

228

Fonksiyonun birinci parametresi BPB blou elde edilecek olan diske ilikin handle deerini belirtir. kinci paramtre BPB bilgilerinin yerletirilecei yapnn adresini alr. BPB yaps ve GetBPB fonksiyonu eklerde verilmitir.
Anahtar Notlar: p, BYTE cinsinden bir adres olmak zere, p adresinden n byte ilerden bir word ekme ilemi yle yaplabilir. *(WORD *)(p + n)

21.13.

FAT Blm

FAT (File Allocation Table), bir dosyann hangi paralarnn hangi clusterlarda olduunu tutan, dosya sisteminin en nemli blmlerinden biridir. FAT blm 12bit, 16bit ya da 32bit olabilmektedir. Volume deki toplam sektr says belirli bir deeri ayorsa, 12bit yerine 16bit FAT kullanlr. Yine belirli bir deerin ztnde 32bit FAT kullanlmaktadr. FAT blmnn hangi sektrden balad BPB blmndeki, sakl sektrlerin says alan ile belirlenmektedir. Yine BPBde FAT in ka kopya olduu ve bir kopyasnn ka sektrden olutuu BPB alannda yazmaktadr. getBPB fonksiyonu btn bu deerleri dzenli olarak verecek biimde yazlmtr. Bylelikle programc tm FAT alann readSector fonksiyonu ile okuyabilir. Disk analiz programlar ve .S. Nin kendisi FAT alannn tamamn bellee okuyamayabilir. Bu durumda bir cache sisteminin oluturulmas gerekir. rnein Linux FAT dosya sistemini gerekletirirken FAT elemanlarndan bir cache oluturmakta, bylece gereksiz FAT okumalarn mmkn olduunca engellemektedir. Ilgili FAT elemanna erimek iin bir HASH tablosu kullanmaktadr. Yeni Linux da bu cache sistemi bir hash tablosu biiminde organize edilmitir. FAT tablosu FAT elemanlarndan olumaktadr. 12 bit FAT de bir FAT eleman 12bit (1.5 byte), 16bit FAT de 16bit(2 Btye), 32bit fat de 32 bit (4 byte) dir. FAT tablosundaki her fat elemanna bir numara verilmitir. FAT tablosu her dosya iin ayr bir bal liste ieren bir tablodur. Dosyann hangi clusterlarda olduu yle tespit edilir: Dosyann ilk cluster numaras dizin giriinden elde edilir. rnein burada 3 yazsn. Sonra 3 numaral FAT elemanna baklr. Dosyann sonraki cluster numaras burada yazar. 6 olsun. 6

229

numaral fat elemanna baklr. Burada 7 yazsn.7 numaral FAT elemannda zel bir deer vardr. Bu son fat elemann belirtir. Bu durumda bu dosyann cluster zinciri 3-6-7 den oluur. FAT Tablosu

7 EOF

grld gibi FAT tablosundan biribirinden bamsz bal liste biiminde dosyas says kadar zincir vardr. phesiz bu sistemde dosyann cluster zincirini elde etmek iin onun balang cluster numarasnn biliniyor olmas gerekir. Balang cluster numarasnn eldesi daha sonra anlkatlacaktr. FAT elemanlarnn says, data blmndeki cluster says kadardr. Dolaysyla formatlama srasnda iletim sistemi volume de ka sektr olduunu hesaplar. Buradan data blmnde ka cluster olsuunu elde eder ve FAT blmnn sektr uzunluuna bu biimde karar ver. Hangi clusterlarn bo olduuna yine FAT tan baklarak karar verilmektedir. Bir FAT elemannda 0 deeri varsa, bu durum o fat elemannn dolaysyla o cluster n bo olduu anlamna gelir. Dolaysyla, diskteki bo alan miktar bo FAT elemanlarnn saysyla hesaplanabilmektedir. Bir FAT elemanndaki deerler ne ifade eder ? FAT16 da fat elemanndaki deerler u anlama gelmektedir.

230

Deer 0000 0001 0002 FFEF FFF0 FFF6 FFF7 FFF8 FFFF

Anlam Bo cluster Kullanlmyor Sonraki cluster Kullanlmyor Bozuk cluster Son cluster (EOF)

12bit fat de ise durum yledir. Deer 000 001 002 FEF FF0 FF6 FF7 FF8 FFF Anlam Bo cluster Kullanlmyor Sonraki cluster Kullanlmyor Bozuk cluster Son cluster (EOF)

32bit fat burada ele alnmayacaktr. 0 ve 1 numaral clusterlar kullanmad iin DATA blmnn ilk cluster 2 numaradr. Bu nedenle ilk 2 FAT eleman dikkate alnmamaldr. 16 bit fat de ilk 2 fat elemannda <med des> FF FF FF 12 bit FAT de <med des> FF FF Deerleri bulunur. Burdak, med des boot sektrde de bulunan ortam belirleyici byte dr.

21.14. Fat Elemanlarndan bir Catch sisteminin oluturulmas

Bir cache sistemi tipik olarak bir hatch tablosu biiminde oluturulabilir. Bylece bu catch sistemine dayanarak bir Fat elemanndan sonraki elaman okunabilir. Bu modl test amal fatcatch.h ve fatcatch.c dosyalar biiminde oluturulacatr. Hash tablosundaki her bir dm aagdaki gibi organize edilebilir.

231

typedef struct tagNODE { WORD clu; WORD nextClu; struct tagNODE *pNext; }NODE;

Bu durumda hatch tablosu aagdaki gibi kurulabilir.


Node *hashTable[TABLE_SIZE]

Bizim bu catch sisteminde bir cluster verildiinde sonraki clustern numarasn veren bir fonksiyona gereksinimimiz olacaktr.
WORD GetNextClu(const BPB *pBPB, WORD clu);

Burada fonksiyon BPB yapsnn adresini ve sonraki cluster parametre olarak almtr. Fonksiyon sonraki cluster numarasna geri dnmektedir. Buradadisk iin gereken HWIN32DISK handle BPB yapsnn iine yerletirilebilir. GetNextClu fonksiyonu yle yazlabilir:

WORD GetNextClu(const BPB *pBPB, WORD clu) { int index; NODE *pNode; BYTE sector[512]; int fatSector, sectorOffset; WORD nextClu; NODE *pNewNode; /*hASH TABLE LOOKUP*/ index = HashFunc(clu); pNode = g_hasTable[index]; while (pNode != NULL) { if (pNode -> clu == clu) return pNode -> nextClu; pNode = pNode -> pNext; } /*Catch miss! read from fat*/ fatSector = clu * 2 / 512; sectorOffset = clu % 256 * 2; if (!ReadSector(pBPB -> hW32Disk, Pbpb -> fatOrigin +fatSector, 1, sector)) return 0; nextClu = *(WORD *) (sector + sectorOffset);

232

/*Insert hash table*/ if ((pNewNode = (NODE *) malloc (sizeof(NODE))) == NULL) return 0; pNewNode -> clu = clu; pNewNode -> nextClu = nextClu ; pNewNode -> pNext = g_hashTable[index]; g_hashTable[index] = pNewNode; return nextClu; }

Buradaki catch sisteminin baz tipik problemleri vardr : 1) Hash tablosu ve catch sistemi snrsz olarak bymektedir. Halbu ki bu durum kesinlikle istenmemektedir. Gerek uygulamalarda tablodaki eleman says belirli miktara eritiinde tablodan eleman kartlmas gerekir. Peki tablodan hangi elemanlar kartlacaktr? Genellikle bu tr durumlarda LRU (Least Recently Used) algoritmas kullanlr. Bu algoritmada bir bal liste alnr, eleman kullanldka bal listenin nne alnr. Bylece bal listenin sonunda son zamanlarda en az kullanlan elamenlar kalm olur. Cache den eleman karlaca zaman bal listenin sonundan kartlm olur. 2) Yukardaki rnekte dm yaps kolaylk olsun diye tek bal liste biiminde alnmtr. Halbu ki cash ten eleman silinebileceine gre, dmlerin ift bal liste olmas silme srasnda avantaj salar. Bu durumda aslnda Node yapsnn aadaki gibi olmas daha gerekidir:
typedef struct tagNODE { WORD clu; WORD nextClu; struct tagNODE *pNext; struct tagNODE *pPrev; struct tagNODE *pLRUNext; struct tagNODE *pLRUPrev; }NODE;

Grld gibi bir dm hem hash tablosunda hemde LRU listesinden referans edilmektedir. Burada eletiriebilecek bir nokta tek bir cluster numaras iin byk bir dmn tahsis edilmesidir. Pratikte dosyann cluster numaralar byk oranda pei sra gittiine gre bir dmde birden fazlada cluster numarasda tutulabilir. Yani bir dm tek bir cluster tutmayabilirde birden fazla cluster tutabilir. Bu durumda arama yine benzer biimde yaplabilir.

233

Tabi ayn dmdeki cluster larn ayn hash deerlerini vermesi gerekebilir. Fakat buda basit olarak salanabilir. pesiz yukardaki GetNextClu fonksiyonu FAT16 iin mevcuttur. Fat12 iin farkl olacaktr. Dosyann cluster zincirinin elde edilebilmesi iin aadaki gibi bir fonksiyon yazlabilir:
WORD *GetCluChain(const BPB *pBPB, WORD clu, int *pCount);

Fonksiyon 1.parametresi BPB yapsn, 2.parametresi dosyann ilk cluster numarasn almaktadr. 3.parametre cluster zincirindeki eleman saysn belirtmektedir. Fonksiyon cluster zincirinin adresi ile geri dnmektedir. Fonksiyon geri verdii adres ierde malloc ile tahsis edilmitir. Fonksiyonu aran kii free etmelidir.
#define CHAIN_BLOCK_SIZE 32 WORD *GetCluChain(const BPB *pBPB, WORD clu, int *pCount) { WORD *pChain = NULL; int i; for (i = 0; clu < 0xFFF8; ++i) if (i % CHAIN_BLOCK_SIZE == 0) { pChain = (WORD *) realloc(pChain, ((i + CHAIN_BLOCK_SIZE) * sizeof(WORD))); if (pChain == NULL) return NULL; } pChain[i] = clu; clu = GetNextClu(pBPB, clu); } *pCount = i; return pChain; }

21.15. Cluster Okuma Yazma lemleri letim sistemi dzeyinde artk sektr okuyup yazmaktan ziyade cluster dzeyinde okuma yazma ilemleri daha yaygndr. O halde cluster okuyup yazan fonksiyonlara gereksinimimiz vardr. Cluster okuyup yazan fonksiyonlar yle olabilir:
BOOL ReadCluster (const BPB *pBPB, DWORD cluNo, void *pClu); BOOL WriteCluster (const BPB *pBPB, DWORD cluNo, const void *pClu);

1. parametresi BPB yapsn, 2.parametresi cluster numarasn almaktadr. 3.parametre transfer adresidir. ReadCluster ve WriteCluster fonksiyonlar yle yazlabilir:
BOOL ReadCluster (const BPB *pBPB, DWORD cluNo, void *pClu)

234

{ DWORD sectNo = pBPB->dataOrigin + (cluNo - 2) * pBPB->spc; return ReadSector(pBPB->hW32Disk, sectNo, pBPB->spc, pClu); } BOOL WriteCluster (const BPB *pBPB, DWORD cluNo, const void *pClu) { DWORD sectNo = pBPB->dataOrigin + (cluNo - 2) * pBPB->spc; return WriteSector(pBPB->hW32Disk, sectNo, pBPB->spc, pClu); }

21.16.

Rootdir Blm ve Dizin Organizasyonu Fat12 ve Fat16 sistemlerinde kk dizindeki tm dosyalarn her biri 32 byte lk kaytlar

biiminde rootdir blmnde tutulmaktadr. Yani rootdir blmnn organizasyonu yledir: Dizin giri Dizin giri Dizin giri Dizin giri . 32 byte 32 byte 32 byte 32 byte

Rootdir blmnde yalnzca kk dizindeki bilgileri vardr. Dizin giriinde bir dosyann ismi,uzants, yaratm tarihi, uzunluu ve dosyann ilk clusternn numaras bilgileri bulunmaktadr. letim sistemi bir yol ifadesi verildiinde dosyann ilk clusteron dizin giriinden elde etmektedir. Dizin giriinin format yledir.

Offset hex(decimal) Uzunluk Anlam

0(0) 8(8) B(11)

8 BYTE 3 BYTE 1 BYTE

Dosya ismi Uzant zellik

235

C(12) E(14) 10(16) 12(18) 1A(26) 1C(28)

2 BYTE WORD WORD 8 BYTE WORD DWORD

Rezerved Yaratm zaman Yaratm tarihi Rezerved lk cluster no Dosya uzunluu

Dosya ismi : Dosta klasik olarak dosya isimleri 8 karakterdir. Bu limit Windows sitemleri ile 260 karaktere uzatlmtr. Uzant : Dosya uzants klasik olarak dosta 3 byte dr. Uzant kavram kaldrlm, dosya ismi birden fazla nokta ierebilir. zellik : Daha ncede _findfirst ve _findnext fonksiyonlarnda grld gibi dosya zellii bir byte iersinde bitlerden olumu durumdadr. Bitlerin anlam yledir:

Arc

Dir

Volume System Hidden Read label Only

Yaratma zaman : Dosya zaman bit olarak aadaki gibi kodlanmtr:

15 h

14 h

13 h

12 11 10

7 m

3 s

2 s

1 s

0 s

h h m m m

m m s

236

Grld gibi saniye iin alan yetmedii iin 5 bit verilmitir. letim sistemi burayasaniye deerinin yarsn yazmaktadr. Yani rnein saniye deeri 50 ise, iletim sistemi buraya 25 yazar fakat 2 ile arpp gsterir. Yani tek saniyeler tutulmamaktadr. Yaratm Tarihi : Burada 2 byte ierisinde bit-bit kodlanm bir biimde yatatm tarihi bulunur. Yl iin epoch 1981. Dolaysyla burada yazlan deere 1980 eklenmelidir. 15 y 14 y 13 y 12 11 10 y y y 9 y 8 m 7 m 6 5 4 3 s 2 s 1 s 0 s

m m s

Anahtar Notlar Dos iletim sistemi yani Fat dosya ilemi yalnzca dosyann yaratm tarihi ve zamann tutmaktadr. Halbuki NTFS ve Unix/Linux sistemleri son deitirme tarih ve zamanlarn, son eriim tarih ve zamannda tutmaktadr.

lk cluster no : Dosyann ilk cluster numaras dizin giriinde yazmaktadr. Dier cluster lar Fat zincirinden elde edilir. Yani iletim sistemi nce dosyaya ilikin dizin giriini elde etmektedir. Dosya uzunluu : Burada 4 byte lk bir alanda dosya uzunluu bulunur. Alt Dizinlerin Organizasyonu ve Yol fadesinin zlmesi lemi

21.17.

Root-dir blmnde yalnzca kk dizindeki dosyalara ilikin bilgiler bulunmaktadr. Aslnda sradan bir dosya ile sradan bir dizin arasnda hibir farkllk yoktur. Her ikiside bir fat zincirine sahip olan dosyalardr. Bir giriin sradan bir dosyam yoksa dznmi olduu 32 bytle dizin giriindeki zellik byte ndan anlalmaktadr. Bir yol ifadesi verildiinde iletim sistemi o yol ifadesinin sonundaki dosyann 32 byte lk dizin giriine erimek ister. Buna yol ifadesinin zlmesine(pathname resolution) denir. rnein \a\b\c.dat dosyasnda c.dat dosyasnn dizin giriini bulmak isteyelim. Bu mutlak yol ifadesi yle zlmelidir. 1) letim sistemi nce kk dizinde yani rootdir blmnde 32 byte lk girilerde a ismini arar. a dosya ismini bulursa, onun bir dizin olduunu dorular sonra onun cluster zincirinde 32 bytle lk girilerde b yi arar. 2) b ismini bulursa onun cluster numarasndan faydalanarak onun cluster zincirindeki 32 bytle lk girilerde c.dat dosyasn arar.

237

Modern iletim sistemleri yol ifadesinin zlmesi srasnda dizin girilerinden bir cache sistemi oluturmaktadr. Bylece ayn dizinin yada dosyann yeniden aranaca zaman gereksiz disk okumalar yaplmam olur. 21.18. Formatlama lemi

Formatlama bir volume n kullanma hazr hale getirilmesidir. Formatlama iki aamada yrtr. 1) Aa seviyeli formatlama 2) Yukar seviyeli formatlama

Aa seviyeli formatlama srasnda donanmn diski kullanabilmesi iin eitli ilemler yaplr. Aa seviyeli formatlama iletim sistemine bal deildir ve hangi iletim sistemi kullanlyor olursa olsun kesinlikle yaplmak zorundadr. Harddisk lerde aa seviyeli formatlama retici firma tarafndan iin banda yaplm durumdadr. Kullanclarn aa seviyeli formatlama yapmas tavsiye edilmemektedir. Dolaysyla rnein Windows da harddisk i formatlamak istediinizde sz konusu olan formatlama aa seviyeli formatlama deildir, yksek seviyeli formatlamadr. Ancak floppy disketlerde aa seviyeli formatlama yaplabilir. Yksek seviyeli formatlamada yalnzca diskin organizasyonel blmleri uygun deerlerle doldurulur. Yksek seviyeli formatlama iletim sisteminden iletim sistemine gre (dosya sisteminden dosya sistemine) deimektedir. rnein Fat dosya sisteminde yksek seviyeli formatlama srasnda boot sektr bilgileri oluturulur, Fat blm sfrlanr rootdir blmde tam olarak sfrlanr. Aslnda data blmnn ayrca sfrlanmasna gerek yoktur. Windows yksek seviyeli formatlamay hzl(quick) ve yava olmak zere ikiye ayrmtr. Hzl formatlamada baka ilave bir ilem yaplmaz. Fakat yava formatlamada tek tek sektrler verify ilemine sokulmaktadr. Verify ilemi sektrlerin tek tek muayine edilmesi anlamna gelmektedir. Bylece bozuk sektrlerin ilikin olduu cluster lar bad cluster olarak iaretlenir. Hzl formatlama ileminde data blmne dokunulmaz ve verify ilemi yaplmaz. Ancak yava formatlama ileminde tm data blmde formatlamaktadr.

238

21.19.

Fat Dosya Sistemine likin Disk Organizasyon Bozukluklar

Bir disk bozukluu fiziksel yada organizasyonel olabilir. rnein disk kafalarnn bozulmas, diskin izilmesi gibi sorunlar ciddi sorunlardr ve genellikle tedavisi mmkn deildir. Fakat disk bozukluklarnn ou organizasyoneldir. Diskteki bilgilerin kaybedilmi olduu kabul edilirse, disk yeniden formatlanarak kullanlabilir. Fat dosya sisteminde ok sk karlalan nemli oragnizasyon problemleri unlardr.(Buradaki bozukluu anlatan ifade check-disk ve scan-disk programlarnn raporlarna gre belirtilmitir.) 1) General error reading/writing : Microsoftun disk onarc programlar boot sektr BPB blou ierik bakmndan bozuk ise disk zerinde bir ilem yapmaz. Nortonun klasik NDD program yada Final Data program bu durumda bozuk BPB yi onarmaktadr. Bu hata BPB blou ierik bakmndan bozuk olduunda ortaya kar. 2) Bad Fat : Eskiden Microsoft Fat blmnn ilk iki elemann Fatin sihirli numaras olarak kontrol ediyordu. Eer Fatin ilk iki elemannda yukarda aklanan zel deerler yoksa Fat zerinde ilemler yapmyordu. Fakat Windows un yeni versiyonlar buna hi bakmamaktadr. 3) Lost Cluster : Bu bozuklukta Fat de bir zincir vardr fakat bu zinciri gsteren volume de hibir dizin girii yoktur. Genellikle elektrik kesintileri srasnda olumaktadr. Onarc programlar genellikle bu zinciri gsteren yeni bir dizin girii yaratrlar. 4) Coss Linked Files : Bu bozuklukta birden fazla Fat zinciri belirli bir noktadan sonra birleerek tek bir zincir olarak devam etmektedir. Dosyalardan biri silindiinde dieride sorunlu hale gelir. Bu bozuklukta elektrik kesilmeleri gibi nedenlerle olumaktadr. Cross Linked Files durumu genellikle Lost Cluster durumu ile birlikte grlmektedir. Onarc programlar genellikle zincirin aprazlat yerden itibaren ortak ksmn dosyaya zg yeni kopyasn oluturmaktadr. 5) Allocation Error : Bu bozuklukta dosyaya ilikin cluster zincirinin belirttii uzunluk ile dizin giriinde ki uzunluk rtmemektedir. rnein bir clustern 2 sektr olduu sistemde dosyann cluster zincirinin 5 cluster olduunu dnelim. Bu dosya 9 * 512 ile 10 * 512 arasnda bir uzunlukta olmaldr. Fakat bu dosyann uzunluu iin dizin giriinde rnein 100 byte lkk gibi bir deer yazyorsa bir tuhaflk sz konusudur. Onarc programlar genellikle dosyann cluster uzunluuna gvenip dizin giriini gncellemektedir.

239

21.20.

Disk Blmleme Tablosu ve Disk Blmlerinin Anlam

Harddiskler birden fazla dosya sistemi veya iletim sistemi yklenebilsin diye birbirinden bamsz blmlere ayrlmlardr. Her disk blm bamsz bir harddisk blm gibi iletim sistemleri tarafndan deerlendirilirler. Bylece biz bir disk blmne Windows u , bir disk blmne Linux u kurarak, istediimiz iletim sistemi ile bilgisayarmz aabiliriz.. Her disk blm ardl sektrlerden oluur. Her disk blmnn hangi sektrden balayp ka sektr uzunlukta olduu bir tabloda tutulur(bu tabloya partitian table, yani disk blmleme tablosu denir.). Disk blmleme tablosunun ilk blmne MBR(Master Boot Record) denilmektedir. Bu sektr fiziksel olarak sfr numaral sektrdr. Disk blmleme tablosu MBR nin sonundadr. MBR nin son 2 byte 55A sihirli saylardr. te disk blmleme tablosu bu sihirli saynn ncesindeki 64 byte dr. MBR nin banda ykleyici program vardr.

Ykleyici program Disk blmleme tablosu (64byte) 55A

Disk blmleme tablosu 16 ar byte lk drt partition dan olumaktadr. . Her 16 byte lk kayt bir disk blmnn nereden baladn, nerede bittiini ve o disk blmnde hangi dosyann olduunu bildirir. Her dosya sisteminin bir ID numaras vardr. Bylece disk blmleme tablosuna bakan bir kii orada hangi dosya sisteminin bulunduunu anlayabilir. Disk blmleme tablosu 4 giriten olutuuna gre acaba drt den fazla disk blm oluturulamaz m ? te geniletilmi(extended) disk blm kavram ile bu durum mmkn hale getirilmitir. Geniletilmi disk blm bir disk blmdr fakat sanki ayr bir harddisk gibi

240

deerlendirilmektedir. Geniletilmi disk blmnn ilk sektrnde de geniletilmi disk blmleme tablosu vardr. rnein;

241

DISK Disk Blm Disk Blm(Extended) Bo Bo D.B.T

Disk Blm

Disk Blm Disk Blm Bo Bo D.B.T

Disk Blm

Disk Blm Bo 2. Genile tilmi blm Bo Bo D.B.T

1. Genile tilmi blm

Disk Blm

242

uayrntlar nemlidir ;

Ana girite en fazla 4 tane disk blm oluturulabilir, fakat diskte 4 ten fazla disk blm oluturmak istiyorsak, ana girilerden bir tanesini geniletilmi disk blm olarak yaratmalyz.

Bir disk blmleme tablosunda birden fazla geniletilmi disk blm bulunamaz. Geniletilmi disk blmndeki disk blmleme tablosu 0, 1 yada 2 eleman ierebilir. Daha fazla eleman ieremez.

Microsoft terminolojisine gre MBR deki disk blmleme tablosunun ana girilerine ilikin disk blmleri birincil disk blmleri(primary partition) denilmektedir.

Microsoft terminolojine gre geniletilmi disk blmlerindeki disk blmlerine mantksal olarak, mantksal srcler(logical drives) denilmektedir. rnein biz 100Gb lik bir harddiskimizi Windows da 20 er Gb lik 5 srcye ayrmak

isteyelim. Bu ilem tipik olarak yle yaplmaldr: nce ana girite 20Gb lik bir primary partiton yaratlr. Daha sonra geri kalan 80Gb lik alan extended partition olarak oluturulmaldr. Sonra bu extended partition iersinde mantksal disk blmleri oluturulur. Her disk blm oluturulduunda, ilgili program disk blm iersinde yeni bir disk blm oluturarak yukarda belirtilen zinciri oluturur. letim Sistemimin Yklenmesi ve Boot lemi

21.21.

Bilgisayarmz atmzda iletim sistemimimizin yklenmesi otomatik bir biimde yaplr. letim sisteminin yklenmesi bir dizi olaylar sonucunda gerekleir. Bilgisayar aldnda alma EPROM iersindeki kod dan balatlr. Bu kod POST(Power On Self Test) ilemini yaptktan sonra setup ta belirtilen sraya gre(burada nce a sonra c olduunu farz edelim) ilgili srcnn ilk sektrn, bellekte 7C00 adresine okur ve oraya jump eder. Grld gibi bilgisayar atmzda boot sektr ierisindeki program bellee yklenerek altrlmaktadr. Floppy disketlerde MBR diye bir sektr yoktur. Eer sz konusu medya hard disk ise ilk sektr MBR dir, bylece MBR deki program altrlm olur. MBR deki

243

program disk blmleme tablosunu inceler, oradaki aktif disk blmn belirler. Aktif disk blmnn ilk blmn bellee ykleyerek bu kez oraya jump eder. Artk iletim sisteminin yklenmesi aktif disk blmn ilk sektrndeki programa braklmtr. rnein ilgili disk blmnn ilk sektr Fat sistemi ieriyorsa, Fat sisteminin boot sektrndeki program altrlr. Anmsanaca gibi boot sektrnn banda bir jump kod vardr. Bu jump BPB blmnn zerinden atlayarak ykleyici programa geer.

jmpcode BPB

Ykleyici Program

Boot sektr iersindeki ykleyici program iletim sistemini yklemektedir. pesiz kcck bir programn koskoca bir iletim sistemini yklemesi beklenemez. Tipik olarak ykleme birka aamada yaplmaktadr. rnein boot sektr ierisindeki ykleyici program Linux ta asl ykleyici program bellee ykleyerek oraya jump eder. Linux ta setup program denilen bu ykleyici program kernal dosyalarn bellee ykler ve oraya jump eder. Bir disk blmnden boot ilemi salayabilmek iin o disk blmnn aktif hale getirilmesi gerekmektedir. nk MBR deki default program byle almaktadr. te bu ilemi grsel bir hale getirebilmek iin boot-loader programlar kullanlmkatadr. Boot-loader programlar birka biimde organize edilebilmektedir.

1) Boot-loader program dorudan MBR ye yklenebilir. Bu durumda orijinal MBR program bozulacaktr.(Windows da fdisk/MBR yazarsan orjinali ykler). pesiz boot-loader program bir sektre smayacana gre, MBR den sonraki sektrleride kullanmaktadr. Zaten genellikle ilk disk blm MBR den hemen sonra deil birinci track in bana hizzalanmtr. 2) Orijinal MBR program bozulmaz(bu yntem tercih edilebilir). Boot-loader program aktif disk blmnn boot sektrne yerletirilir.

244

Boot-loader nereye yerletirilmi olursa olsun, bir men eliinde boot edilecek disk blmn sorar ve o disk blmnn boot sektrn ykleyerek ak oraya devreder. I-Node Dosya Sistemlerine likin Disk Organizasyonun Genel Yaps

21.22.

Linux/Unix sistemlerindeki dosya sistemlerinin disk organizasyonu birbirine ok benzerdir.Bu disk organizasyonlar Fat sisteminden olduka farkldr. Bu organizasyonlardan bugn iin en fazla kullanlan ext2(second extended file system) organizasyonudur. Tipik bir Inode grubu sistemin disk organizasyonunda disk blm 3 blme ayrlr.

Disk Blm

Super Block

i-node block

Data Block

Super Block : Super Block Fat dosya sistemindeki BPB blmne benzemektedir. Burada disk blmlerinin nereden balad, ka sektr uzunlukta olduu, bir bloun ka sektrden olutuu gibi temel bilgiler vardr. I-node block : i-node block i-node elemanlarndan oluur. Her i-node elemannn ilk eleman sfr olmak zere bir numaras vardr. Dosyann btn bilgileri i-node elemannda saklanr. Her dosyann bir i-node numaras vardr. Dosyann i-node numaras o dosyann bilgilerinin ka numaral i-node elemannda olduunu belirtir. I-node dosya sistemlerinde dosyann hangi

245

blocklarda(yada cluster larda) bulunduu yine i-node elemannda belirtilmektedir. Yani ayrca Fat gibi bir durum yoktur. Bir i-node elemannda kabaca u bilgiler vardr: - Dosyann uzunluu - Eriim bilgileri - Dosyann userid ve grupid deerleri - Dosyann tarih ve zaman bilgileri - Dosyann tr - Dosyann paralarnn hangi blocklarda olduu bilgisi Data block : Data block Fat dosya sistemindeki data blm ile ayn anlamdadr. Bu dosya sistemindede dizin ile dosya arasnda bir fark yoktur. Bu dosya sisteminde de dizinler dizin girilerinden oluur. Bir dizin girii dosyann ismi ve i-node numarasndan olumaktadr.

Dizin Dosyas sim sim sim . i-node numaras i-node numaras i-node numaras ..

Sfr numaral i-node eleman kk dizine ilikindir. Bu sistemlerde yol ifadesinin zmlenmesi yle yaplmaktadr. rnein /a/b/c.dat dosyasna ilikin i-node eleman bulunmak istensin. Burada nce sfr(0) numaral i-node eleman elde edilir, kk dizinin data blocklarnn nerede olduu belirlenir. Orada a ismi aranr. a nn i-node numaras elde edilir ve bu kez a dizinin data blocklarnda b aranr. b nin i-node numars elde edilir ve sonra benzer biimde c.dat dosyasnn i-node numaras elde edilir. Bu dosya sisteminde dosyann ismi dndaki btn bilgileri i-node elemannda saklanmtr. Bu sistemde i-node blocktaki i-node elemanlarnn saysndan daha fazla dosya yaratlamaz.

246

22. KESME LEMLER

Kesme(interrupt) micro ilemcinin alt kod a ara verip baka bir kod u altrmas durumudur. Ortaya k mekanizmasna gre kesmeler blme ayrlmaktadr. Yazlm kesmeleri(Software interrupt): Yazlm kesmeleri programc tarafndan Makine komutuyla oluturulan kesmelerdir. rnein intel ilemcilerinde int Makine komutu yazlm kesmesi oluturmak iin kullanlmaktadr. Donanm Kesmeleri(Hardware Interrupt): Kesme denildiinde akla gelen kesmeler donanm kesmeleridir. Bu kesmeler CPU nun kesme ucunun(iny ucu) elektriksel olarak uyarlmasyla asenkron biimde oluur. Her mikro ilemcide ve microdenetleyicide bir kesme ucu(int ucu) vardr. Bu kesme ucu 5 volt ya da sfr volt kenara tetiklemeli ya da sabit uyarmal olarak aktive edilebilir. Bu u aktive edildiinde micro ilemci altrmakta olduu koda ara vererek nceden belirlenmi bir kesme kodunu altrr. Micro ilemciler bir Makine kodu alrken almaya ara veremezler. Birmak,na komutunun almas bittikten sonra kesme koduna dallanabilirler. Yani tek bir Makine kodu atomiktir. sel Kesmeler(Internal Interrupt): sel kesmeler microilemcinin bir Makine kodunu altrrken kendisinin oluturduu kesmelerdir. rnein intel gibi byk micro ilemcilerin ok sayda isel kesmesi vardr. Kesme olutuunda Ne Olur? Kesmenin oluum biimi nasl olursa olsun kesme olutuunda baz tipik ilemler micro ilemci tarafndan yaplamamaktadr. rnein ilemci geri dne olanak salamak iin sonraki komutun adresini stack e push eder. Yine baz ilemciler bayrak yazmacndaki baz bitleri otomatik olarak resetlemektedir. Yine micro ilemciler kesme olutuunda bir kod a dallanrlar. Hangi kod a dallanacaklarn kesme vektr denilen bir yerden elde ederler. Pek ok kk micro ilemci ve micro denetleyicide kesme vektr tek elemanlktr. Kesme vektrne altrlacak kod un adresi yazlr. Sistem programcs bu sstemlerde kesme kodunu bellekte oluturur. Onun adresini kesme vektrne yazar. Intel gibi baz yksek kapasiteli micro ilemcilerde vektr birden fazla elemandan oluturulur. rnein intel de toplam 256 kesme

247

sz konusudur. Her kesmenin bir numaras vardr. Kesme bir numarayla birlikte oluur. Yani bir kesme olumas deil 5 numaral kesmenin olumas szkonusudur. Intel ilemcisinin int ucu dorudan deil 8259 kesme denetleyicisi yolu ile dsal aygtlara balanmtr. 8259 kesme denetleyicisi 70 li yllarda tasarlam eski bir denetleyicidir. Fakat hala bu uyum kullanlmaktadr. Ayrca yeni board larda APIC(Advanced Programmable Interrupt Controller) denilen modern bir kesme denetleyiciside kullanlmaktadr. 8259 kesme denetleyicisinin int ucunu nun int ucuna balanmtr ve 8 giri ucu vardr. Pc ler ilk ktnda tek bir kesme denetleyicisi vard, AT ler ile birlikte 2 kesme denetleyicisi kullanlmaya balanmtr. Kesme denetleyicisinin her bir giri ucuna IRQ(Interrupt Request) denilir ve her bir u dsal bir birime balanmtr. Ayrca 1. kesme denetleyicisinin 2. numaral giri ucu, 2. kesme denetleyicisinin int ucuna balanmtr. (2 tane 8259 denetleyicisini balamak iin 1. denetleyicinin herhangi bir ucunun 2.denetleyicinin int ucuna balanmas gerekir, PC mimarisinde bunun iin 2 numaral u seilmitir). Kesme denetleyicilisi ile ilemci arasndaki balant daha gereki olarak aadaki gibidir.

Intel CPU INT INTA D7 ......... D0

INT INTA D7 ......... D0 8259 (Master) CAS 0 1 2 3 4 5 6 7

CAS

INT 8259 (Master) 0 1 2 3 4 5 6 7

Dsal bir kesme yle olumaktadr. 1) Kesme denetleyicisinin bir IRQ ucunu dsal bir birim aktive eder.

248

2) Kesme denetleyicisi CPU nun int ucunu aktive eder. CPU IF bayrann durumuna bakarak, IF yi ya kabul eder yada etmez. Eer kesmeyi kabul ederse, inta ucunu aktive eder. 3) Kesme denetleyicisi kesmenin kabul edildiini anladnda D0-D7 ularndan kesmenin numarasn CPU ya bildirir. 4) CPU kesme koduna geerek kesme kodunu altrr.

22.1.

IRQ Kaynaklar Kesme denetleyicisinin her bir ucuna deiik kaynaklar balanmtr. Bu balantlarn

ouna 1980 ylnda ilk Pc ler zamannda karar verilmitir. Bugn halen ayn mimari devam ettirilmektedir.

IRQ0 : Ana kesme denetleyicisinin 0 numaral ucuna Intelin 8254 zamanlayc devresi baldr. Intel 8254 PIT(Programmable Interval Tme) belli bir periodda darbe reten osilatr devresidir. Bilgisayar aldnda BIOS saniyede 18.2 darbe retecek ekilde bu zamanlaycy ayarlar. rnein Linux 2.6 da readin ncelii deitirlmesse default olarak 100 milisaniyelik bir quanta deeri kullanlmaktadr.
Anahtar Notlar Dos iletim sistemi 18.2 deerini deitirmemektedir. 18.2 deeri aslnda 8254 ilemcisine balanan kristal frekans ile ilgilidir. Kullanlan kristal frekans 1193182 Hertz dir. 18.2 deeri bu deerin 65535 e blnmesinden elde edilmitir. O halde default darbe frekans 18.20679 biindedir.

IRQ0 windows, Linux/Unix sistemlerinde treadler aras gei mekanizmas iin kullanlr. rnein Linux iletim sistemi boot edildiinde BIOS un oluturduu default 18.2 deerini 10 mili saniyeye ve yeni kernal larda da 1 mili saniyeye ekmektedir. Fakat her timer kesmesi olutuunda treadler aras gei yaplmamaktadr. Bu durumda rnein hzl bir Pc de son Linux versiyonlarnda timer 1 mili saniye ye kurulmakta ve kabaca her 100 timer kesmesinde treadler aras gei oluturulmaktadr. Yine tipik olarak Windows sistemleri 60 mili saniye civarnda bir quanta kullanmaktadr.

IRQ1 : IRQ1 hatt 8042 klavye denetleyicisine baldr. Bu konuyu anlamadan nce klavye alt sisteminin almas incelenecektir.

249

Klavyenin iinde kabaca yatay ve dey hatlarn kesim noktasna tular yerletirlmitir. Bu hatlarn klavye iersindeki klavye ilemcisine verilmitir. Bylece bir tua baslp ekildiinde, klavye iersindeki ilemci bu tuun ka numaralu tu olduunu anlayabilir. Klavye iindeki ilemci klasik olarak Intel 8048 yada trevi mikrodenetleyiciler ile gerekletirlmektedir. Fakat uyumlu pek ok klavye ilemcisi farkl firmalar tarafndan retilmitir.(rnein Holtek firmasnn HT82K68A Keyboard Encode ilemcisi tipik olarak klavye reticileri tarafndan kullanlmaktadr.). Klavye ilemcisinin ular dorudan connectore verilmitir. Klavye connectornn tipik ular unlardr.

1) KPD Clock 2)KPD Data 3) N/C 4) GND 5) +5V(VCC)

1) KPD Clock 2) GND 3) KPD Data 4) N/C 5) +5V(VCC) 6) N/C

Klavyeden bir tua bastmzda klavye ilemcisi bu tuun hangi tu olduunu belirler ve tuun numarasn belirten ismine klavye tarama kodu(keyboard scen code) denilen data/clock

250

ular ile seri bir biimde darya gnderir. Tipik olarak clock ucunun ykselen kenarnda data ucu rneklenir. Grnd gibi aktarm seri bir biimde data ucundan yaplmaktadr. Aktarm ayrntlar iin klavye ilemcilerinin darta sheetlerine baklmaldr. Klavye zerindeki yazlarn klavye alsmas ile hibir ilgisi yoktur. Her tuun bir numaras vardr, d dnyaya yalnz tarama kodu iletilir. Klavye ilemcisi yalnzca tua bastmzda deil elimizi ektiimizde de kod gndermektedir. Bastmzda gnderilen koda make kod, ektiimizde gnderilen koda break kod denilmektedir. Pc klavyeleri break kod olarak nce bir F0 byte sonra make kodun aynsn gndermektedir. rnein bastmz tu iin gnderilen 1 byte lk make kod hex 18 olsun. Elimizi tutan ektiimizde F018 biiminde 2 byte gnderilir. O halde biz bu klavyeyi yalnzca Pc lerde kullanmak zorunda deiliz, tamamen baka aygtlarda da kullanabiliriz. Klavye connectorunu Pc ye taktmzda bu ular dorudan klavye denetleyicisi diye bilinen(tipik olarak Intel 8042 gibi ilemciler) bir denetleyiciye baldr. Klavyeden gelen klavye tarama kodu klavye denetleyicisine ulatnda klavye denetleyicisi bu kodu sistem tarama kodu(systems scan code) denilen baka bir tarama koduna dntrr, kendi ierisindeki bir yazmata saklar ve IRQ1 hattn aktive eder. IRQ1 olutuunda klavye denetleyicisinin iinde 1 byte lk sistem tarama kodu bulunmaktadr. Bu deer 60h portu okunarak elde edilebilir. letim sistemlerinde IRQ1 kesme kodu klavye denetleyicisinden baslm yada ekilmi tuu alarak klavye tamponuna yerletirir. Klavye tarama kodu ile sistem tarama kodu arasndaki farkllklar unlardr: Make kodlar farkldr. Break kod 2 byte deil tek byte a indirgenmitir. Make kodun yksek anlaml biti 1 yaplarak break kod elde edilir. letim sistemi baslan ve ekilen tular alarak bir kuyrua yerletirir, programlar bu kuyruktan tular almaktadr. Shift gibi alt gibi, caps lock gibi tularn hibir zellii yoktur. rnein biz nce shift sonra a tuuna basm olalm ve elimi nce a sonra shift tuunda ekmi olalm. nce shift tuu iin make kod sonra A tuu iin make kod sonra A tuu iin break kod en son da shift iin break kod oluturulur. imdi elimizi nce shift tuuna sonra A ve B tularna basm olalm. Sonra elimizi bu tulardan ekmi olalm. Srasyla u kodlar iin kesmeler oluacaktr:

251

shift(make), A(make), B(make), A(break), B(break), shift(break). letim sistemi baslan tular kuyrua yerletirdikten sonra zel tular iin bayraklar tutar ve kullancnn hangi tulara bastn belirler. rnein bir programc programlama dilinde bir karakter okumak isterse, iletim sistemi shift(make) ve A(make) tularn tampondan atar ve shift bayran set eder, ve programcya (byk harf) A tuunun ascii karln verir. Sonra programc bir karakter daha okumak isterse ona (byk harf) B yi verir, nk hala shift bayra set edilmi durumdadr. Makine aldnda BIOS ta baslan tulardan bir kuyruk sistemi oluturmaktadr. BIOS un oluturduu bu kuyruk sistemi dos tarafndan da ayn biimde kullanlr. BIOS un ve dos un klavye ilemleri yle organize edilmektedir: 1) 15 karakterlik bir klavye tamponu tutulur. 2) Shift, control, alt gibi tulara basldnda tampona bir ey yazlmaz, yalnzca bayraklar set edilir. 3) Ascii tularna basldnda bayraklarn durumuna baklarak ilgili tular kuyrua yazlmaktadr. 4) Ctrl+alt+del, pause gibi zel tular IRQ1 kesme kod tarafndan o an deerlendirilmektedir. Klavye denetleyicisi ile kalvyenin iersindeki ilemci ile data balants tek tarafl deil ift tarafldr. Yani klavye denetleyiciside klavye iersindeki ilemciyi programlamaktadr. Klavyede elimizi bir tua bastmzda nce o tu iin bir make kod gnderilir, elimizi tutmaya devam ettiimizde ayn tu iin make kod gnderilmeye devam eder. Bu mekanizmaya typematik denilmektedir. Typematik klavye iersindeki ilemci tarafndan kontrol edilir, tua basld andan typematik e kadar geen sre ve typematik periodu ayarlanabilmektedir. Klavye zerindeki baz tulara ilikin klarn yaklmas klavye tarafndan yaplan zel bir ilem deildir. rnein biz caps tuuna basm olalm. Ik klavye devresi tarafndan yaklmaz. Klavye caps tuunun tarama kodunu klavye denetleyicisine gnderir. Sonra IRQ1 oluur, IRQ1 kesme kodu klavye ilemcisini programlayarak n yanmasn salar. Yni rnein biz IRQ1 i disable etsek caps lock tuuna bastmzda k yanmaz. IRQ2 : Birinci kesme denetleyicisinin 2 numaral ucu ikinci kesme denetleyicisine bal olduu iin byle bir u yoktur.

252

IRQ3 : Bu hatta 2 ve 4 numaral comport lara bal olan UART ilemcisi baldr. Pc ler normal olarak 4 seri porta kadar desteklenmektedir. UART(Universial Asynchronous Receiver Transmitter) eitli durumlarda IRQ oluturabilmektedir. IRQ4 : Bu hatta com1 ve com3 seri portlarna bal UART ilemcisi baldr. IRQ5 : Bu IRQ hatt genellikle ses kartlar tarafndan kullanlmaktadr. Genileme yuvasna taklan kartlarda IRQ oluturabilmektedir. rnein ses kartlar tipik byle kartlardr. 5 numaral bu u klasik olarak LPT2 paralel port ilemcisine baldr fakat artk bilgisayarlarda 2 paralel port bulunmad iin bu IRQ ses kartlar kullanabilmektedir. IRQ6 : Bu IRQ hattna Intel 8272 flopy denetleyicisi baldr. IRQ7 : Bu IRQ hattna LPT1 paralel port ilemcisi baldr. Paralel portlarda IRQ oluturabilmektedir. IRQ8 : kinci kesme denetleyicisinin 0 numaral ucuna Real Time Clock ilemcisi baldr. Pc ler ilk ktnda bir saat devresi iermiyordu. Dolaysyla bilgisayar kapattmzda tarife zaman bilgisi kayboluyordu. Daha sonra AT lerle birlikte bir saat ilemcisi anakarta eklenmitir. Bilgisayarmz kapattmzda board zerindeki bu saat ilemcisi almaya devam etmektedir. Bu ilemci board zerindeki kk pilden beslenmektedir. RTC ilemcisi ayn zamanda CMOS setup bilgilerinide tutmaktadr. Yani bilgisayar aarken F2 yada del tuu ile girdiimiz setup bu RTC ilemcisinin iindedir. Tipik olarak bilgisayar atmzda alma EPROM ierisindeki blgeden balar, buradaki kodbaz test ilemlerini yaptktan sonra klavyeden F2 yada del tuuna baslp baslmadna bakar. Bu tulara baslmsa RTC ierisindeki CMOS blgesine bavurur, bu blgeyi bir menu eliinde edit eder. BIOS ayn zamanda al srasnda bu CMOS bilgilerine bakarak evre birimlerinide ona gre programlamaktadr. rnein biz buradan bir hard disk i devre d brakabiliriz. Bu durumda BIOS IDE denetleyicisine bilgi gndererekaygt disable eder. Yani CMOS setup BIOS taki statik kodu biraz dinamik hale getirmek iin dnlmtr. (CMOS password bilgiside CMOS un ierisinde tutulmaktadr, dolaysyla bu pili takp karttmzda yada ksa devre yaptmzda password de disable olur.). IRQ9-10-11 : Bu hatlar genileme yuvasna taklan hatlar iin serbest braklmtr. IRQ12 : Bu IRQ hattna PS2 faresi baldr. Yani kk connector l farelerimiz bu IRQ hattn kullanmaktadr. IRQ13 : Bu IRQ hattna matematik ilemci baldr. Eskiden noktal saylar zerinde ilem yapan matematik ilemci ayr bir ilemci olarak boarda taklyordu. Fakat 80486DX modeli ile birlikte

253

matematik ilemcide ayn ilemci paketinin iine yerletirilmitir. Bugnk pentiumlarda yine matematik ilemci ile normal ilemci ayn entegrenin ierisinde birbirine bal bir biimdedir. Matematik ilemci bir problem olutuunda ana ilemciye IRQ yolu ile durumu bildirmektedir. IRQ14 : Bu IRQ hattna birincil(primary) IDE denetleyicisi baldr. rnein hard disk te bir sektrn okunmas bittikten sonra hard disk durumu IDE denetleyicisine bildiri, IDE denetleyiciside IRQ durumu oluturur. IRQ15 : Bu IRQ hattna ikincil IDE denetleyicisi baldr.

22.2

IRQ Kesme Kodlarnn Set Edilmesi

Bir IRQ olutuunda arlacak kod programc tarafndan belirlenebilir. Intel ilemcilier her kesme numaras iin bir adres ieren kesme vektrne sahiptir. Bu kesme vektrne adres yerletirebilmek iin Windows ve Unix/Linux gibi sistemlerde kernel dzeyinde programlama gerekir. Yardmc lemciler

22.3

Bir bilgisayar sisteminde bir yada birden fazla ana ilemci ve ok sayda yardmc ilemci vardr. Ana iemci ile yardmc ilemciler elektriksel olarak balant halindedir. CPU yani merkezi ilemci programcnn yazd komutlar altrr. Yardmc ilemciler CPU programlamaktadr. O halde biz programmzda yardmc ilemciye gnderilecek komutlar belirleriz., CPU bizim isteimiz dorultusunda onlar programlar. Yani sonuta yardmc ilemcileri yine biz programlam olmaktayz. Tipik bir yardmc ilemci 3 grup u topluluundan oluur: Giri ular, k ular ve Kontrol ular. lemcinin ular ikilik sistemde birer bit olarak kullanlmaktadr. rnein tipik olarak 5V civarnda bir gerilim lojik 1, 0V civarnda bir gerilim lojik 0 olarak deerlendirilir. O halde CPU yardmc ilemciye aslnda ikilik sistemde saylar gndermekte ve onlardan ikilik sistemde cevaplar almaktadr. Bu ikilik sistemdeki bilgiler elektriksel dzeyde gerekletirilmektedir.

254

Giri ular Tipik bir yardmc ilemci

rnein 4 bitlik iki say zerinde drt ilem uygulayan tipik bir ilemcin ular u ekilde olabilir:

a0 a1 a2 a3 b1 b2 b3 b4 t0 t1

4 ilem ilemcisi

c0 c1 c2 c3 c4

T0 0 0 1 1

T1 0 1 0 1

Anlam Toplam karma arpma Blme

255

Bir ilemciye komut gndermek demek ona ikilik sistemde saylar gndermek demektir. CPU btn ilemcilere baldr, fakat belirli bir ilemciyi seebilmesi iin port numaras denilen bir numaraya gereksinim duyar. Bylece komutu dierlerine deil yalnzca ona gnderebilir. Baz ilemcilerin tek bir port numaras vardr, baz ilemcilerin birden fazla port numaras bulunabilir. Intel ilemcilerinde yardmc ilemciye bilgi gndermek iin out makine kodu, yardmc ilemciden bilgi almak iin in makine kodu kullanlr. rnein; out 21, FF. Burada biz 21h portuna FF deeri gnderilmitir. rnein; in al, 21. Burada ise 21h portundan deer alnm ve al yazmana yerletirlmitir. Bir ilemcinin bir portun hangi saylar gnderdiimizde bunun ne olarak ele alnaca ve yorumlanaca ilemciye gre deimektedir. Her yardmc ilemcinin programlanmas ayr bir biimde o ilemci renilerek yaplr. Yardmc ilemcilere komut gnderme Windows ve Linux/Unix sistemlerinde ancak aygt srclerle mmkndr. Fakat komut gnderme iini yapan basit aygt srcler yazlm olarak bulunmaktadr. rnein Windows da inpout32 isimli aygt src 2 fonksiyon sunmakta, bu fonksiyonlarda in ve out komutlarn kernal moda uygulamaktadr. Linux sistemlerinde /dev dizinin altndaki port isimli aygt src zaten bu ii yapcak ekilde dzenlenmitir. rnein klavye denetleyicisi 60h ve 61h portlarn kullanmaktadr. Anmsanaca gibi son baslan yada ekilen tuun klavye tarama kodu dntrlerek sistem tarama kodu haline getirilmekteydi. Klavye denetleyicisi bu deeri 60h portuna yerlestirir, sistem programcs son baslan yada ekilen tuu anlamak iin 60h portundan okuma yapmaktadr. Gerektende IRQ1 kesme kodu nce 60h portunu okumakta, bu bilgiyi almakta ve baslan tua karar vermektedir. Yine klavyedeki zel tularn na yakmak iin typematik ayarlarn yapmak iin 61h portunu kullanmak gerekir.

256

22.4.

Paralel Port Kullanm

Paralel port bilgisayar yazc haberlesmei iin dnlm olan genel amal bir porttur. 25 adet pine sahiptir. Her pine bilgisayar yazc haberlemesi dikkate alnarak bir isim verilmitir. Aslnda paralel port bamsz amalarlada kullanlabilir. Pin isimleri yledir:

Pin No(DB25)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18-25

Signal name
nStrobe Data0 Data1 Data2 Data3 Data4 Data5 Data6 Data7 nAck Busy Paper-out Select Linefeed nError nInitialize nSelect-Printer Ground

Paralel portlar ilk ktklarndan bu yana evrim geirmitir. Bugnk paralel portlar gemiteki modlarda destekler durumdadr. lk paralel portlar standart mod ile bugn kullanlabilmektedir. Standart moda yalnzca 4 bit gnderip alma yaplabilir. Daha sonra

257

EPP(Enhanced Paralel Port) modu tasarlanm ve port biraz gelitirilmitir. Bu moda 8 bitlik transfer yaplabilmektedir. Nihayet paralel portlar biraz daha gelitirilerek ECP(Extended Capability Port) haline getirilmitir. Bugn bu 3 modda kullanlabilmektedir. Aralarnda nemli farkllklar yoktur ve burada standart mod aklanacaktr. USB portlarn gelimesi ile ve yaygnlamas ile pararlel portun cazibesi byk oranda kaybolmaktadr. Fakat basit kullanm nedeniyle yinede varln srdrmektedir. Paralel portun 3 port adresi vardr: Taban port adresi deiebilmekle birlikte ok byk olaslkla LPT1 iin 378h, LPT2 iin 278h dir.
Anahtar Notlar Bir ilemci birden fazla port kullanyorsa bu portlar ardldr ve ilk port numarasna taban port denilmektedir.

Paralel port paralel port ilemcisi tarafndan yrtlr ve bu ilemcinin 3 adet yazmac vardr. Bu yazmalar portlara balanmtr. Taban+0 numaral porta data yazmac, taban+1 numaral porta durum yazmac, taban+2 numaral porta komut yazmac baldr. Bu yazmalar 8 bit uzunluundadr. Paralel portun data yazmac paralel portun 2 ile 9 numaral pinlerini temsil etmektedir. Bu yazma standart moda okunabilir yada yazlabilir. Ancak standart moda paralel portun 2-9 numaral pinleriyanlzca out amal kullanlabilmektedir. Bu nedenle biz bu yazmac okuduumuzda ilgili pinlerin durumunu deil son yazdmz deeri okuruz. Programc taban port numarasn kullanarak out ilemi yaptnda deerler bu yazmaca yaplr, paralel port ilemcisi 1 olan bitleri 5V a 0 olan bitleri 0V a eker. O halde paralel porttan bir ledi yakp sndrmek iin asadaki gibi bir kod yazlabilir.
while (!kbbit()) { Out32(0x378, 1); Sleep(1000); Out32(0x378, 0); Sleep(1000); }

7 9

6 8

5 7

4 6

3 5

2 4

1 3

0 2

258

Paralel portun taban+1 numaral portuna durum yazmac baldr. Durum yazmac da bir grup pin ile iligilendirilmitir. Fakat bu pinler yazma amal deil okuma amaldr.

7 ~11

6 10

5 12

4 13
Durum Yazmac

3 15

2 x

1 x

0 1

Biz bu yazmac okursak dardan o pinlere uygulanan iaretleri elde ederiz. Bu yazma read only dir ve yazmaya izin yoktur. 7. bit(yani 11. pin terstir(toggle)). Yani 11. pin dardan sfra ekildiinde biz onu bir diye, bire ekildiinde sfr diye okuruz. 1 ve 2 numaral bitler kullanlmamaktadr. Grld gibi standart moda pararlel port 8 bit out yaparken yalnzca 5 bit in yapabilmektedir. Bylece eski paralel portlar 4 bit-4bit haberleme yapyorlard. Komut yazmac paralel portu programlamakta kullanlr, ayn zamanda bu yazma yine baz out ular ile ilikilendirilmitir.

7 x

6 x

5 x

4 x
Komut Yazmac

3 ~17

2 16

1 ~14

0 ~1

22.5. Paralel Portta Veri Transferi

Eskiden a haberlemesi yaygn deil iken ve Ethernet kartlar kullanlmyor iken bilgisayardan bilgisayara veri transferi ok zordu.(90 yllarn ortalarna kadar). O gnlerde paralel portlar iki bilgisayar arasnda dosya aktarm iinde kullanlyordu. smine lablink denilen zel bir kablo, bir portun out ularn dierinin in ularna balyarak elde ediyordu. Sonra zel yazlmlar 1byte lk bilgiyi 4 bitlik 2 paraya ayrp, bu kabloadan gnderip alabiliyordu.

1 259

15

13

12

10

11

10

11 6

12

13

2 15

16 16

17 17

25

25

260

22.6.

Seri Haberleme

Seri haberleme temel olarak zaman aralklaryla bilginin bit-bit kar tarafa aktarlmas ile meydana gelir. Teorik olarak yalnzca 2 hat ile seri bilgi akratm yaplabilir. Gnderici taraf byte bitlerine ayrr, 1 olan bit iin hatt rnein 5V a, 0 olan bit iin 0V a(bu seviyeler deiebilir) eker. Kar tarafta ayn hzda hatta bakar. Bylece byte aktarm yaplr. Ancak 2 hat ile ayn anda yalnzca bir taraf dierine bilgi gnderir. Fakat ayn anda her iki tarafta birbirine bilgi gnderip alcak ise en az 3 hat gerekir.

Seri haberleme gnderip alma durumuna gre 3e ayrlr.

1) Simplex Haberleme : Yalnzca bir taraf bilgi gnderir, ters ynde gnderim olmaz. Bunun iin 2 adet hat yeterlidir. 2) Half-Dublex Haberleme : Burada 2 taraf ta birbirine bilgi gnderip alabilir, fakat bunular ayn anda yapamaz. Bunun iinde 2 adet hat yeterlidir. 3) Full-Dublex Haberleme : ki tarafta ayn anda birbirlerine bilgi gnderip alabilir. Bu haberleme iin en az 3 hat gerekmektedir.

Seri haberlemenin en nemli problemi iki tarafn ayn hzda gnderip alma yapmasdr. Bugnk elektronik devreler bunu salyabilmektedir. Dier nemli bir problem alc tarfn hatta baktnda o anda bilgilerin gnderilip gnderilmediini belirlemesi zorunluluudur. Seri haberleme kendi iersinde asenkron ve senkron olmak zere iki ye ayrlr. Asenkron haberleme doada en ok karlalan durumdur. Burada byte n bitleri eit hzda gnderilip alnr, fakat byte lar arasnda rastgele bekleme sreleri sz konusudur. Halbuki senkron haberlemede hem bytler n bitleri hemde byte lar ayn hzda gnderilip alnr. Asenkron seri haberlemede klasik yntem start bit stop bit yntemidir. Bilgi gnderilmiyorken hat lojik 1 seviyesinde bekletilir, gnderici tarafbilgiyi gndermeden nce hatt 1 birim sfra eker. Bylece alc taraf bilginin gnderilmeye balandn anlar. Artk iki tarafta belirlenen hzda bilgileri gnderip alrlar. Nihayet ilem bitince hat yeniden eski 1 durumuna ekilir. Bunada stop bit denilir.

261

stop bit

Start bit

0
Frame

Pc lerde seri haberleme iin UART (Universal Asynchronous Receiver and Transmitter) denilen yardmc ilemci kullanlmaktadr. UART Intel firmasnn 8250, National firmasnn 16550 ilemcileridir. UART ilemcisi belirli bir frekansta programlanabilmektedir. Programc UART ilemcisine bilgiyi byte olatak verir, ilemci onu bitlerine ayrp kar tarafa belirlenen hzda gnderir. UART ayn zamanda full-dublex olarak alma ileminide yapabilmektedir. ki UART ilemcisi birbirine balanabilir. UART iemcisinin en nemli 3 ucu TxD(Transmit-data), RxD(Receive-data, GND(Ground) dr. UART ilemcisi seri porta bal olarak kullanlr. Biz UART a 1 bitlik bir bilgi verdiimizde, UART bunu bitlerine ayrarak TxD ularndan bit-bit kodlar. Bilgisayar taraf 9PIN MALE connector biimindedir. UART ve seri port bilgisayar modem haberlemesi iin dnlmtr ve pinlere isimleri buna gre verilmitir. UART ilemcisinin ucu dorudan deil rs232 dntrc ucu ile seri porta verilmitir. Normalde UART ilemcisinin ular TTL dzeyindedir.(Tipik +5V sfr). Halbuki seri portun ular rs232 sinyal seviyelerine gre ayarlanmtr. Bu sistem tipik olarak +-15V civarndadr. UART ilemcisinin ular ile seri port un ular ayndr. En nemli 3 u yukarda da belirtildii gibi RxD, TxD ve GND ulardr. Seri port ilemleri eitli dzeylerde yaplabilir. En aa dzeyde UART ilemcisinin portlarna bilgi gnderilip alnarak ilemler gerekletirlebilir. Fakat bu ilemleri yapan bakalar tarafndan yazlm yada C ktphanesine eklenmi, eklenti niteliindeki fonksiyonlarda kullanlabilir. Windows ve Unix/Linux sistemlerinde UART n haberleme portlarna dorudan

262

erimemiz engellenmitir. Bu iletim sistemlerinde seri port ilemlerini gerekletiren zel sistem fonksiyonlar vardr.

RxD TxD GND

RxD TxD GND

UART ilemcisi 7 haberleme portu kullanr. Pc lerde Com1 iin taban port adresi 3F8H, Com2 iin 2F8H dir. UART ierisinde eitli yazmalar vardr. Bu yazmalar eitli haberleme portlarna baldr. ki UART n haberleebilmesi iin ncelikle bunlarn ayn deerlerle set edilmesi gerekir. Set etme srasnda u ilemler yaplr: UART n gnderme ve alma hz belirlenir. Data bitlerinin says belirlenir. Start bitten sonra data bitlerinin says 5, 6, 7 yada 8 olabilir. Yani 8 olmas zorunlu deildir.

263

Stop bitler 1 yada 2 olabilir. Bazen haberlemeyi yavalatmak iin ve hattan kaynaklanan problemleri tolere etmek iin 2 stop bit kullanma yoluna gidilmektedir. Fakat son yllarda byle bir gereksinim kalmamtr.

UART bilgi gnderir yada alrken parity ayar ve kontrolu yapabilmektedir.

Yukardaki ayarlarn her iki bilgisayarda da ayn biimde yaplmas gerekmektedir. Aksi halde hemen frame hatas oluur.

22.7.

Hatalarn Belirlenmesi zerine Yntemler

Bir bilgiyi iletirken yada saptarken bilgi ile birlikte baz anahtar deerlerde iletilir yada saklanrsa, daha sonra bu deerlere baklarak bilginin bozulup bozulmad anlalabilir. Bunun iin eitli yntemler kullanlmaktadr.

1) Parity Yntemi : Bu yntem zellikle seri haberlemede yaygn kullanlmaktadr. rnein UART ilemcileri parity hesab yapmaktadr. Parity ynteminde her byte iin yada bit grubu iin ayrca birde parity biti gnderilir. Parity tek (odd) yada, ift (even) biiminde olabilir. Tek parity demek data ierisindeki 1 olan bitlerin saysn teke tamamlamak iin gnderilen bittir. ift parity ise ifte tamamlamak iin gnderilen parity dir. rnein ;

10101110

tek parity = 0, ift parity = 1

data

Parity yntemi bozulmalara ok duyarl bir yntem deildir.

2) Checksum Yntemi : Bu yntem dosyalarda yani dosyalarn bozulmasn belirlemek iin tercih edilen bir yntemdir. Checksum basit bir yntemdir fakat gc snrldr. Byte, word, dword versiyonlar vardr. Bu yntemde dosyann tm bytelar kmilatif olarak taanlar atlacak biimde toplanr. Daha sonra tekrar ayn hesap yapldnda nceki deer ile ayn deer bulunursa bilgi bozulmamtr, bulunmazsa bilgi bozulmutur. Bazen checksum

264

deeri negatif checksum biiminde de hesaplanr. Negatif checksum ismi zerinde elde edilen checksum n negatif deeridir. Eer checksum bilgiside dosyann ierisinde bir yerde bulunacak ise bu durumda dosyann checksum hesaplandnda sfr (0) elde edilir. Bozulma kontrol iin CRC( Cyclic Redundancy Check) kullanlr. CRC yntemini hesaplamas daha zordur fakat deiimlere kar duyarl ok daha fazladr. rnein checksum ynteminde dosya 2 byte yer deitirmise checksum deeri deimez. CRC yntemi modemlerde, disklerde, ve sktrma programlarnda yaygn kullanlan yntemdir.

22.8. assert Makrosunun Kullanm ve Projelerin Delay ve Release Versiyonlar

Programdaki yanl almaya yol aan gizli hatalara bcek denilmektedir. Yaplan aratrmalar, programcnn yapt hatalarn 5% ile % 8 arasnn nihayi rne yansdn

gstermektedir. Ayrca bceklerin rn satldktan sonra dzeltilmesi ok maliyetli bir ilem olarak bilinmektedir. Bcek oluumunun en bata programc tarafndan engellenmesi gerekir. Programc kodunu yazarken ayn zamanda da bir bcek oluuyormu diye kontrol etmesi gerekir. Bu ilem assert makrosu ile yaplr. assert makrosu assert.h ile bildirilmitir ve kullanm yledir : assert(ifade). Pek ok derleyicide assert makrosu aadaki koda benzer ekilde yaplr.
#ifndef NDEBUG #define assert(exp) if (!(exp)) { fprintf(strderr, "Assertion failed : %s-%d\n", --FILE--, --LINE--); abort(); } #else #define assert(exp) #endif

Grld gibi ndebug sembolik sabiti define edilmemise default olarak debug mod sz konusudur. Bu durumda assert makrolar yerine kontrol kodlar alr. Eer ndebug sembolik sabiti define edilmise tm assert makrolar yerine boluk atanr. Programc assert makrolar kodun eitli yerlerine yerletirerek anormal durumlarn olumasn gzler. Eer assert makrosuna taklnrsa bir ipucu elde edilmi olunur. Bu ipucu deerlendirilerek bcein bulunduu yere gelinir.

265

int main(int argc, char *argv[]) { char *str; str = strchr("Ankara", 'x'); myputs(str); return 0; }

void myputs(const char *str) { assert (str != NULL); while (*str != NULL) { putchar(*str); ++str; } putchar ('\n'); }

Burada fonksiyon null adresle arlmas normal bir durum deildir. te assert makrosu bunu yakalar ve bize hatann yerini bulmamz iin bir ipucu verir. rnein
void CalcSomething(int val) { assert(val >= 0); ... }

Burada val deerinin parametresinin sfrdan byk olmas gerekir. Normal olan budur. Programc gerekli her yere assert makrolarn yerletirerek kontrol salar. Fakat daha sonra kodunda hibir bcek olmadndan emin olduunda assert makrolarnn yol at gereksiz kontrollerden kurtulmak isteyecektir. Bunun iin tek yapmas gereken ey ndebug makrosunu define etmektir. Bir projenin 2 versiyonu vardr. Bunlar debug ve release dir. Debug versiyon assert makrolarn koda eklendii, gereksiz kontrollerin yapld versiyondur. Programc kodunu debug versiyonda gelitirir, satmadan nce release derlemesi yapar. Release derlemesi tm assert makrolarn koddan kartmaktadr. Pek ok IDE de de projenin debug ve release versiyonlar menu seenekleri ile ayarlkanmaktadr. Visual studio da default durum dubug versiyondur. Bu versiyonda ndebug sembolik sabiti define edilmemitir ve ayrca ktphanelerin debug versiyonlar devreye sokulur. Ktphanelerin debug versiyonlarnda yine assert ler uygulanmtr.

266

Projenin release versiyonunda ise ndebug define edilmitir ve ktphanenin release versiyonlar devreye sokulur.

22.9.

Deiken Syda Parametre Alan Fonksiyonlar

C de prototipte yada tanmlama srasnda atomu fonksiyonun istenildii kadar argman ile arlabileceini belirtir. rnein;

void Func (int a, );

Burada fonksiyon en az bir parametre almak zorundadr. iin sfr tane yada daha fazla argman girilebilir. Standartlara gre parametresi parametre listesinin sonunda bulunmak zorundadr ve ayrca nn solunda en az bir parametre bulunmak zorundadr. rnein printf fonksiyonun tanm yledir; int printf(const char *str, );

Intel ilemcilerinde parametre aktarm stack yolu ile ve sadan sola yaplmaktadr. Yani ilk parametre stack te dk adreste bulunur, dier paramatrelere bu paramatrenin yerini biliyorsak eriebiliriz. Parametrelerin stack e atl sras ve stack organizasyonu, mimariden mimariye deiebildii iin stack ten paramatre ekme ilemi makrolara yaptrlmaktadr. Bu makrolar stdarg.h iersinde bulunmaktadr. va_list tr genellikle bir adres trdr. nce bu trden bir nesne tanmlanmaldr. Daha sonra va_start makrosu ile bu va_list ve ilk paramatre ileme sokulur. rnein;
#include #include #include #include #include <stdio.h> <stdlib.h> <string.h> <assert.h> <stdarg.h>

void Func(int a, ...) { va_list arg; va_start(arg, a); val = va_arg(arg, int) ... }

267

int main(int argc, char *argv[]) { Func(10, 20, 30, 40, 50, 60, 70, 0); return 0; }

Burada arg aslnda bir gstericidir. va_start makrosuda ilk parametreden sonraki paramatrenin adresini alarak buna yazmaktadr. va_arg makrosu va_list trnden bir nesneyi ve bir tr bilgisini parametre olarak alr, stackte sradaki argman eker. Son olarak va_end makrosu arlmaktadr. Bu makronun yapt bir ey genellikle yoktur. Aadaki fonksiyon 0 bulana kadar argmanlar stackten ekip toplamaktadr;
int Add(int a, ...) { va_list arg; int total = 0, val; va_start(arg, a); total += a; while ((val = va_arg(arg, int)) != 0) total += val; va_end(arg); return total; } int main(int argc, char *argv[]) { printf("%d\n", Add(10, 20, 30, 40, 0)); return 0; }

Tabi bu rnekte biz dier tm parametrelerin int trden olduunu varsaydk. Aslnda programc bir biimde bu trleri anlamak zorundadr. Zaten fonksiyon 1.parametresi bunun anlalmas iin bir ipucu vermektedir. rnein; printf(a = %d b = %lf\n, a, b); Burada printf %d ve %lf formatlarna bakarak ilk paramatrenin int dierinin double trden olduunu anlar. C derleyicisi parametresine kar gelen int trnden kk argmanlar int trne, float trn ise double trne dntrerek stack e atar.

268

269

You might also like