CSD İşletim Sistemi Çekirdeğinin Sanal Dosya Sistemine İlişkin Temel Veri Yapıları Kaan Aslan 1 Haziran 2004 1. Giriş CSD sanal dosya sistemi büyük ölçüde Linux sistemlerinin sanal dosya sistemine benzemektedir. Dosya sistemi grubu çeşitli UNIX türevlerinin sanal dosya mimarilerini incelemiş ve Linux sistemlerine yakın durmayı tercih etmiştir. Gelinen nokta göz önüne alındığında sanal dosya sisteminin tasarım bakımından Linux sistemlerine benzemesi yadırganmamalı ve tedirginlikle karşılanmamalıdır. Bilindiği gibi Linux sistemleri de ilk biçiminden bu yana diğer UNIX sistemlerinden oldukça büyük alıntılar yapmış, belli bir aşamadan sonra bazı özgün yaklaşımlar geliştirebilmiştir. CSD Dosya Sistemi Grubu da geliştirmenin sonraki evrelerinde özgün yenilikler yapma isteğindedir. 2. Dosya Sistemine İlişkin Temel Veri Yapıları CSD dosya sisteminin desteklediği tüm dosya sistemleri FILE_SYSTEM_TYPE yapılarından oluşan bir bağlı listede tutulmaktadır. Bağlı listeye elemanlar sistemin başlatılması sırasında eklenmektedir. CSD dosya sisteminde en temel işlem diğer sistemlerde olduğu gibi mount işlemidir. Mount işlemi sırasında mount edilen dosya sistemine ilişkin bilgiler çeşitli veri yapılarında biraraya getirilmektedir. Mount işlemi SYS_LINUX_mount sistem fonksiyonu tarafından yapılmaktadır: int SYS_LINUX_mount(PSTR pszDevName, PSTR pszMountDir, PSTR pszFSName, DWORD dwFlags, PVOID pData); SYS_LINUX_mount doMount readSuperBlock addSuperBlock addMountedFS … Mount işlemi sırasında mount edilen dosya sistemi addMountedFS fonksiyonu tarafından MOUNTED_FILE_SYSTEM türünden bir bağlı listeye, süper blok bilgileri de addSuperBlock fonksiyonu tarafından SUPER_BLOCK türünden bağlı listeye yazılmaktadır. 1 Kaan Aslan Makale Arşivi – www.kaanaslan.net Bir dosya sistemi birden fazla yere mount edilebilir. Yukarıdaki şekilden de görüldüğü gibi SUPER_BLOCK yapısının dlistMounts elemanı ilgili süper bloğun nerelere mount edildiğini belirlemek için kullanılan bir bağlı listedir. Benzer biçimde bir dosya sistemine ilişkin birden fazla volume söz konusu olabilir. FILE_SYSTEM_TYPE yapısının dlistFSSB elemanı o dosyasistemine ilişkin SUPER_BLOCK nesnelerini tutan bağlı listedir. MOUNTED_FILE_SYSTEM listesinin ilk elemanı gs_mountedFS tarafından, SUPER_BLOCK listesinin ilk elemanı gs_superBlocks tarafından, FILE_SYSTEM_TYPE yapısının ilk elemanı da gs_fsType tarafından tutulmaktadır. SYS_LINUX_mount fonksiyonunun parametresi aygıt dosyasının yol ifadesidir. Fonksiyon önce yol ifadesinden hareketle aygıt dosyasının i-node bilgilerini elde eder. Erişim için gereken aygıt numarası i-node bilgilerinin içerisindedir. Bu işlemden sonra eğer aygıtın süper bloğu SUPER_BLOCK listesinde yoksa yeni bir SUPER_BLOCK nesnesi oluşturulmakta, eğer varsa eski SUPER_BLOCK nesnesi kullanılmaktadır. Aygıt dosyasından elde edilen aygıt numaraları pek çok veri yapısına da aktarılmaktadır. SUPER_BLOCK mount edilen fiziksel birime ilişkin parametrik bilgilerin tutulduğu bir veri yapısıdır. Örneğin aygıtın fiziksel adresi, aygıtın blok sayısı, blokların sektör uzunluğu gibi temel tüm parametrik bilgiler SUPER_BLOCK yapısında tutulmaktadır. Disk üzerinde gerçek okuma, yazma işlemlerinin hareket noktası SUPER_BLOCK yapısıdır. SUPER_BLOCK nesnesi FAT ve VFAT dosya sistemlerinde boot sektör BPB blgilerinden, UNIX/LINUX dosya sistemlerinde ise diskteki süper blok bilgilerinden oluşturulmaktadır. 2 Kaan Aslan Makale Arşivi – www.kaanaslan.net 3. Dilimli Tahsisat Sistemi Dilimli tahsisat sistemi (slab allocator) ilk kez 1994 yılında Solaris 2.4 ile birlikte uygulamaya geçirilmiştir. Linux sistemleri de 2.2 uyarlamasıyla birlikte dilimli tahsisat sistemini kullanmaya başlamıştır. CSD İşletim Sisteminin çekirdek yapısı içerisinde dilimli tahsisat sistemi yoğun olarak kullanılmaktadır. Dilimli tahsisat sistemi küçük nesnelerin tahsis edilmesi işlemlerinde yavaş tahisat fonksiyonlarını az çağırmak için oluşturulmuş bir cache sistemidir. Bu sisteme göre bir nesne dilimli tahsisat fonksiyonu ile tahsis edilmeye çalışıldığında dilimli tahsisat fonksiyonu bir grup nesne kadar alanı (yani bir dilimlik alanı) tahsis eder. Sonraki tahsisatlar için hızlı bir biçimde daha önce tahsis edilmiş olan dilimlerden yer verilir. Dilimli tahsisat fonksiyonları şunlardır: HCACHE CreateCache( PCSTR pszName, DWORD dwObjects, DWORD dwObjectSize ); PVOID AllocObject( HCACHE hCache ); void FreeObject( HCACHE hCache, PVOID pBlock ); CreateCache fonksiyonu kullanılacak dilim sisteminin ismini, başlangıçta tahsis edilecek nesne sayısını ve bir nesnenin byte uzunluğunu parametre olarak alır ve tahsisat işleminde kullanılacak handle değeri ile geri döner. Fonksiyon ikinci parametresinden hareketle başlangıçta kaç dilimin gerektiğini hesaplar ve bu dilimleri tahsis eder. AllocObject dilimden nesne veren fonksiyondur. Tahsis edilen alan FreeObject fonksiyonu ile serbest bırakılır. FreeObject fonksiyonu tüm dilim boşaltılmışsa dilimi işletim sistemine geri verir. CSD dilimli tahsisat sisteminde nesne uzunluğu ne olursa olsun bir dilim SLAB_SIZE (512) kadar nesne içermektedir. Örneğin: HACAHE hDirEntryCache; PDIR_ENTR pEntry; … hDirEntryCache = CreateCache("DirEntryCache", 5000, sizeof(DIR_ENTRY)); ASSERT(hDirEntryCache != NULL); … pEntry = (PDIR_ENTRY) AllocObject(hDirEntryCache); ASSERT(pEntry != NULL); Bu durumda CreateCache başlangıçta 10 dilim tahsis edecektir (5000 / 512 yukarı doğru yuvarlanmıştır.) Dilimli tahsisat sisteminde dilimler işletim sisteminin çekirdek heap alanından tahsisat yapan AllocMem sistem fonksiyonu ile tahsis edilmektedir. 3 Kaan Aslan Makale Arşivi – www.kaanaslan.net 4. Aşağı Seviyeli Disk Cache Sistemi Disk cache sistemi diskten son okunan blokların RAM’de tutulmasıyla disk erişimini azaltmayı hedefleyen bir cache sistemdir. Bu sisteme UNIX/LINUX sistemlerinde İnglizce buffer cache denilmektedir. Disk cache sisteminin büyüklüğüne sistemdeki RAM miktarına bakılarak dinamik bir biçimde karar verilir. Disk cache sisteminin -iyi uygulandığı taktirde- disk erişimini %70’lerin üzerinde azalttığı (cache hit ratio) bilinmektedir. Bu nedenle disk cache sistemi dosya sisteminin performansını belirlemede kritik öneme sahiptir.Linux disk cache sistemi Maurice J. Bach’ın ünlü Design of the UNIX Operating System kitabında açıklanan modelden alınmıştır. CSD İşletim Sisteminde de bu model kullanılmaktadır. Disk cache sistemi bağlı listeli bir hash tablosu olarak düzenlenmiştir. Hash tablosu BUFFER_HEAD bağlı listelerininin başlangıç adreslerinin tutulduğu bir dizi biçimindedir. DLIST_HEADER gs_hashTable[HASH_TABLE_SIZE]; Cache’teki her blok için bir BUFFER_HEAD nesnesi vardır. Bloğun tüm bilgileri bu nesnede tutulur: typedef struct tagBUFFER_HEAD { KDEV kdev; DWORD dwBlock; DWORD dwBlockSize; DWORD dwStatus; DWORD dwLRUIndex; DWORD dwSector; BYTE *pBlock; DLIST_NODE dlink; DLIST_NODE dlinkFree; } BUFFER_HEAD, *PBUFFER_HEAD; Görüldüğü gibi yapının içerisinde söz konusu bloğun uzuluğu, hangi aygıtın hangi bloğu olduğu gibi önemli bilgiler bulunmaktadır. Yapının pBlock gösterici elemanı bloğun yerini, dwBlockSize elemanı ise uzunluğunu tutar. BUFFER_HEAD nesnelerinin tuttukları bloklar farklı büyüklükte olabilmektedir. Fakat blok uzunluğu işlemcinin desteklediği sayfa uzunluğundan (örneğin Intel işlemcilerinde 4K) büyük olamaz. 4 Kaan Aslan Makale Arşivi – www.kaanaslan.net Cache sisteminin şekilsel gösterimi aşağıdaki gibidir: BUFFER_HEAD nesnelerinden oluşan hash tablosu bir bağlı liste dizisi biçimindedir. Bloğun cache içerisinde aranması için aygıt numarası ve blok numarası kullanılarak bir dizi indeksi elde edilir. Dizinin bu indeksli elemanı üzerinde doğrusal arama yapılır. Bloklar getBlock fonksiyonu tarafından cache’te aranır: PRIVATE PBUFFER_HEAD getBlock( KDEV kdev, DWORD dwBlock, DWORD dwBlockSize ); 5 Kaan Aslan Makale Arşivi – www.kaanaslan.net Fonksiyon: 1) Önce istenen blok cache’te var mı diye bakar. İstenen blok cache’te varsa onun BUFFER_HEAD adresiyle geri döner. 2) Eğer istenen blok cache’te yoksa yeni bir BUFFER_HEAD oluşturur. Onu cache’e yerleştirir ve cache’e yerleştirmiş olduğu BUFFER_HEAD nesnesinin adresiyle geri döner. getBlock okuma işleminin kendisini yapmaz. getBlock fonksiyonunun çağırma şeması şöyledir: getBlock getBufferCacheHash updateLRU addItemLists deleteItemFreeList putBufferCache getBufferCacheHash addItemLRU setBufferClean fillFreeList addItemFreeList initBufferHead getBlock fonksiyonunun anlaşılmasında iki önemli nokta vardır: 1) Cache’e yerleştirilecek BUFFER_HEAD nesnesinin tahsis edilmesi 2) BUFFER_HEAD nesnesinin kullandığı bloğun tahsis edilmesi Tahsisat işlemlerinin hızlı yapılabilmesi için bloğu tahsis edilmiş olan fakat diğer bilgileri geçersiz olan BUFFER_HEAD nesneleri özel bağlı listelerde saklanır. Bu bağlı listelere boş blok listeleri (free block lists) denilmektedir. Her blok büyüklüğü için toplam NR_FREE_LIST(4) kadar boş blok listesi vardır. 6 Kaan Aslan Makale Arşivi – www.kaanaslan.net Boş blok listelerindeki BUFFER_HEAD nesneleri ve onların blokları tahsis edilmiştir. Fakat BUFFER_HEAD nesnesinin ve onun tuttuğu bloğun içeriği boştur.Bir boş blok listesi elemanını oluşturabilmek için hem bir BUFFER_HEAD nesnesine hem de tampon (buffer) olarak kullanılacak bloğa gereksinim vardır. Boş bağlı listede eleman kalmadığında ona eleman doldurmak için fillFreeList fonksiyonu çağrılmaktadır. fillFreeList fonksiyonu o bağlı listeye Sayfa uzunluğu / Block uzunluğu kadar eleman ekler. Bu fonksiyon getBlock içerisinden çağrılır. fillFreeList fonksiyonunun çağırma şeması şöyledir: fillFreeList AllocPage createBuffers getUnusedBufferHead AllocObject addItemFreeList fillFreeList boş bağlı listeye eleman ekleyebilmek için BUFFER_HEAD nesnesi elde etmeye çalışır. BUFFER_HEAD nesneleri normal olarak dilimli tahsisat sisteminden alınmaktadır. Ancak dilimli tahsisat sistemine daha az başvurmak için kullanılmayan BUFFER_HEAD nesneleri kullanılmayan nesne listesi (unused list) denilen bir bağlı listede tutulur. fillFreeList fonksiyonu BUFFER_HEAD nesnesini önce getUnusedBufferHead fonksiyonu ile buradan almaya çalışır. Kullanılmayan nesne listesinde hiç BUFFER_HEAD nesnesi kalmamışsa nesne gerçekten AllocObject dilimli tahsisat fonksiyonuyla tahsis edilir. Her blok büyüklüğü için ayrı bir boş bağlı listenin kullanıldığını görüyorsunuz. Böylece bir blok gerektiğinde onun aranması daha hızlı yapılabilmektedir. fillFreeList fonksiyonu bloklar için gerekli olan tampon RAM alanlarını doğrudan AllocPage fonksiyonunu çağırarak sayfa düzeyinde tahsis eder. 7 Kaan Aslan Makale Arşivi – www.kaanaslan.net Sistemin blok okuması yapan ana fonksiyonu ReadBlock fonksiyonudur. ReadBlock önce getBlock fonksiyonunu çağırarak cache’e bakar. Eğer cache’te blok bulunamazsa gerçek disk okuması için ReadWriteBlock fonksiyonunu kullanır. ReadWriteBlock fonksiyonu blok aygıt sürücüsünün temel bir fonksiyonudur. Burada ele alınmayacaktır. ReadBlock fonksiyonunun çağırma şeması şöyledir: ReadBlock getBlock ReadWriteBlock Disk cache sistemi hem okuma hem de yazma amaçlı kullanılmaktadır. Yani yazma işlemi sırasında da eğer blok cache’te ise yazma cache’e yapılmaktadır. Cache’teki blokların tazelenmesi arka planda çalışan çekirdeğe ilişkin bir thread tarafından yapılacaktır. Disk cache sisteminde kullanılan son veri yapısı LRU listesidir. Bu liste cache’teki blokların en az işlem görenlerini tespit etmek amacıyla kullanılır. Cache’teki bir blok üzerinde işlem yapıldığında bu bloğa ilişkin BUFFER_HEAD nesnesi LRU listesinin en önüne alınır. Böylece listenin sonunda her zaman az kullanılanlar kalır. Disk cache sisteminden eleman çıkartılacağı zaman en az kullanılan bloklar cache’ten atılmaktadır. Aşağı seviyeli disk cache sisteminde kullanılan veri yapıları isimleriyle şunlardır: 1. BUFFER_HEAD bağlı listelerinin başlangıç adreslerlerini tutan hash tablosu: PRIVATE DLIST_HEADER gs_hashTable[BUFCACHE_HASH_TABLE_SIZE]; 2. BUFFER_HEAD nesnelerinin tahsis edilmesinde kullanılan dilimli tahsisat sistemi: PRIVATE HCACHE gs_hBufHeadCache; 3. Bloğu tahsis edilmiş BUFFER_HEAD nesnelerinden oluşan boş bağlı listeler: PRIVATE DLIST_HEADER gs_dlistFree[BUFCACHE_NR_FREE_LIST]; 4. Kullanılmayan BUFFER_HEAD nesnelerinin saklı olduğu kullanılmayan nesne listesi: PRIVATE DEFINE_DLIST(gs_dlistUnused); 5. Cache’teki ve kullanılmayan nesne listesindeki eleman sayılarını tutan değişkenler: PRIVATE int gs_nInUseBufHeads; PRIVATE int gs_nUnusedBufHeads; Aşağı seviyeli disk cache sistemindeki alt sistemlerin amaçları da aşağıda özetlenmiştir: Genel Disk Cache Sistemi: Diskte erişilen son blokları RAM’de bir cache içerisinde saklayarak disk erişimini azaltır. Böylece sistemin hızlı çalışmasını sağlar. İşletim sisteminin hızı bakımından kritik öneme sahip bir sistemdir. 8 Kaan Aslan Makale Arşivi – www.kaanaslan.net Dilimli Tahsisat Sistemi: İşletim sisteminin tahsisat fonksiyonları yavaştır. Bu nedenle küçük nesneler için sistemin tahsisat fonksiyonlarını ikide bir çağırmak etkin bir yöntem değildir. Bunun yerine işletim sisteminin tahsisat fonksiyonları ile büyük dilimler tahsis edip sonra o dilimlerin içerisinden hızlı bir biçimde nesneleri verme yöntemi tercih edilir. Amaç işletim sisteminin yavaş çalışan tahsisat fonksiyonlarını daha az çağırmaktır. Hash Tablosu: Erişilmeye çalışılan bir bloğun disk cache sistemi içerisinde olup olmadığının hızlı bir biçimde tespit edilmesi için kullanılır. Eğer blok cache’te varsa doğrudan alınır. Blok cache’te yoksa aygıt okumasyla blok aygıttan alınarak hash tablosuna yerleştirilir. Boş Blok Listeleri: Cache’ten çıkartılan bloklar hemen serbest bırakılmaz. Boş blok listelerine alınarak orada bekletilir. Böylece yeni bir disk bloğu için yeniden RAM alanı tahsis edilmemiş olur. Boş blok listelerinde bulunan bir RAM bloğu yeni disk bloğu için kullanılır. (Tabii cache’ten çıkartılan her blok boş blok listesinde biriktirilmez bunun bir sayısı vardır. Yani boş blok listesinde maksimum sayı kadar blok zaten varsa yeni bloklar listeye yazılmadan doğrudan sisteme iade edilir.) Kullanılmayan Nesne Listesi: Bu liste BUFFER_HEAD nesneleri için cache olarak kullanılır.Yani kullanılmayan BUFFER_HEAD nesneleri bu listeye alınır. Böylece dilimli tahsisat sisteminden yapılan tahsisatlar azaltılmış olur. Bu listedeki nesnelerin blokları tahsis edilmemiştir. 5. Yol İfadelerinin Çözümlenmesi ve Dizin Girişlerine İlişkin Cache Sistemi Dosya işlemlerinin programcı bakımından başlangıç noktası dosyanın hangi dizinde ve hangi isimde olduğunu gösteren yol ifadesi (path name)’dir. Dosya üzerinde işlem yapan pek çok sistem fonksiyonu (open, stat, mkdir, chdir, …) dosyayı tespit edebilmek için dosyanın yol ifadesini parametre olarak almaktadır. Yol ifadesini parametre olarak alan sistem fonksiyonları ilk iş olarak bu yol ifadesinden hareketle dosyanın temel bilgilerine ulaşmaya çalışırlar. Dosyanın temel bilgileri POSIX sistemlerinde i-node yapısıyla temsil edilmektedir. Verilen bir yol ifadesinden hareketle yol ifadesinin sonunda belirtilen dosyanın i-node bilgilerine erişilmesi sürecine yol ifadesinin çözümlenmesi (pathname resolution) denir. (Yol ifadesi terimi hem dosyalar için hem de dizinler için kullanılan bir kavramdır. Dizinler ve dosyalar arasında bunların ele alınma biçimleri bakımından bir fark bulunmamaktadır.) Yol ifadelerinin çözümlenmesi özyinelemeli (recursive) bir işlemdir. Çözümleme sırasında yol ifadesini oluşturan her bir yol bileşeni üzerinden teker teker geçilmek zorundadır. Çünkü her yol bileşenine ilişkin i-node bilgisi önceki bileşen ile belirtilen dizin içerisindedir. Örneğin, /home/osdev/test.c gibi bir yol ifadesinin çözümlenmesi sırasında önce kök dizinin i-node bilgilerinden home dizininin inode bilgileri, home dizininin i-node bilgilerinden osdev dizininin i-node bilgileri, osdev dizininin i-node bilgilerinden de nihayet test.c dosyasının i-node bilgileri elde edilir. CSD dosya sisteminde yol bileşenlerine dizin girişi (directory entry) de denilmektedir. Dizin girişi bilgileri DIR_ENTRY yapısıyla temsil edilmektedir. 9 Kaan Aslan Makale Arşivi – www.kaanaslan.net typedef struct tagDIR_ENTRY *PDIR_ENTRY; typedef struct tagDIR_ENTRY { DWORD dwCount; DWORD dwFlags; PINODE pInode; PDIR_ENTRY pParentEntry; DLIST_NODE dlinkHash; DLIST_NODE dlinkLRU; DLIST_NODE dlinkAlias; DLIST_NODE dlinkSibling; DLIST_HEADER dlistSubEntry; PSUPER_BLOCK pSB; PDIR_ENTRY_OPERATIONS pOps; ENTRY_NAME entryName; char shortEntryName[DENTRY_SHORT_NAME_SIZE]; } DIR_ENTRY; Bir dosyaya ilişkin dizin girişi bilgileri ve i-node bilgileri aslında disk üzerinde tutulan bilgilerdir. Yol ifadelerinin çözümlenmesi sırasında yol ifadelerini oluşturan dizin girişi ve i-node bilgileri diskten belleğe alınmak zorundadır. Yani yol ifadesinin çözümlenmesi işlemi aslında yol ifadesinin sonunda bulunan dosyaya ilişkin i-node bilgilerinin diskten belleğe çekilmesi işlemidir. Yol ifadelerinin çözümlenmesi daha etkin bir hale nasıl getirilebilir? Şüphesiz ilk düşünülecek yöntem bir cache sistemi kurmaktır. Böylece, bir dosyanın bilgilerine erişilirken geçilen yollara ilişkin tüm bileşenlerin dizin girişi bilgileri ve i-node bilgileri bir cache sisteminde tutulursa, aynı dosyalara erişildiği durumda işlemin hızlanacağı açıktır. Bu nedenle modern işletim sistemlerinde hem dizin girişleri hem de i-node elemaları için ayrı cache sistemleri kullanılmaktadır. CSD işletim sisteminde de (tıpkı Linux sistemlerinde olduğu gibi) dizin girişleri ve i-node bilgileri bu nesnelere özgü cache sistemlerinde saklanır. CSD dosya sisteminin dizin girişlerinin cache sisteminde şu veri yapıları kullanılmaktadır: 1. DIR_ENTRY türünden bağlı listelerin başlangıç adreslerinin tutulduğu bir hash tablosu: PRIVATE DLIST_HEADER gs_dirEntryHashTable[DENTRY_HASH_TABLE_SIZE]; 2. En az kullanılan ve kullanılmayan DIR_ENTRY nesnelerinin tespit edilmesini sağlayan bir LRU bağlı listesi: PRIVATE DEFINE_DLIST(gs_dlistLRU); 3. Bir i-node’a ilişkin link bilgilerini tutan bir eş giriş bağlı listesi. Bu listenin ilk elemanı i-node nesnesi içerisindedir: DLIST_HEADER dlistDirEntry; /* INODE yapısının elemanıdır */ 10 Kaan Aslan Makale Arşivi – www.kaanaslan.net 4. Cache’teki ve kullanılmayan nesne listesindeki eleman sayınısı tutan değişkenler: PRIVATE int gs_nInUseEntries; PRIVATE int gs_nUnusedEntries; DIR_ENTRY nesnesinin kaç kişi tarafından kullanıldığını gösteren bir dwCount elemanı vardır. Sayacı sıfıra düşen DIR_ENTRY nesnesi hash tablosundan çıkarılmaz; yalnızca LRU listesinin sonuna alınır. LRU listesinde sayacı sıfıra düşmüş olan (yani kullanılmayan) kaç tane DIR_ENTRY nesnesi olduğu gs_nUnusedEntries değişkeninde tutulmaktadır. Kullanılan DIR_ENTRY nesneleri bağlı listede öne alınır. Böylece en çok kullanılanlar önde en az kullanılanlar ve hiç kullanılmayanlar arkada kalır. Bir i-node elemanına ilişkin birden fazla DIR_ENTRY nesnesi bulunabilir. Bunlar da başlangıcı i-node nesnesinde fakat linkleri DIR_ENTRY içerisinde olan eş giriş listelerinde saklanırlar. Dizin girişlerine ilişkin cache sistemi i-node cache sisteminin kontrol merkezidir. Inode cache sistemine elemanlar DIR_ENTRY işlemleriyle alınırlar. Yani ne zaman bir yol ifadesi kullanılsa bu yol ifadesindeki dizin girişleri dizin girişi cache sistemine, inode elemanları ise i-node cache sistemine alınmaktadır Her dizin girişi için i-node cache sistemi içerisinde bir i-node nesnesi vardır. CSD dosya sisteminde yol ifadelerinin çözümlenmesi LookupDirEntry fonksiyonu tarafından yapılmaktadır: PDIR_ENTRY LookupDirEntry( PCSTR pPathName, PDIR_ENTRY pBaseEntry, DWORD dwLookupFlags ); Fonksiyon çözümlenecek yol ifadesini (pPathName), arama işleminin başlatılacağı dizini (pBaseEntry) ve arama planını belirten bayrakları parametre olarak alır. Başarılıysa ilgili girişin DIR_ENTRY adresiyle, başarısızsa NULL adresiyle geri döner. Fonksiyon dizin girişini önce cache’te arar. Eğer cache’te bulamazsa aygıttan okuyarak onu cache’e yerleştirir. Birkaç durum söz konusudur: 1. Eğer pPathName mutlak yol ifadesi ve pBaseEntry de NULL ise pBaseEntry process’in kök dizinine çekilir. Böylece arama işlemi kök dizininden itibaren yapılır. 2. Eğer pPathName mutlak yol ifadesi ve pBaseEntry de NULL ise pBaseEntry ile belirtilen girişin sayacı bir artırılır ve pBaseEntry process’in root dizinine çekilir. Yani yukarıdaki durumda olduğu gibi arama yine kök dizininden itibaren yapılacaktır. 3. pPathName göreli yol ifadesi ve pBaseEntry de NULL ise pBaseEntry process’in çalışma dizinine çekilir. Böylece arama işlemi çalışma dizininden itibaren yapılır. 4. pPathName göreli yol ifadesi ve pBaseEntry de NULL değilse pBaseEntry olduğu gibi bırakılır. Yani arama işlemi pBaseEntry ile belirtilen dizinden itibaren yapılır. Fonksiyonun çağırma şeması şöyledir: 11 Kaan Aslan Makale Arşivi – www.kaanaslan.net LookupDirEntry checkPermission (permission) lookupReservedEntries (lookup_dentry) GetDirEntryCache (cached_lookup) GetDevDirEntry (real_lookup) allocDirEntry (d_alloc) checkPermission her yol bileşeninin erişim iznini denetler. lookupReservedEntries yol bileşeninin . ve .. gibi ayrılmış (reserved) isimler olup olmadığına bakar. GetDirEntryCache bileşeni cache’te aramaktadır. Bu fonksiyon ya bileşeni cache’te bulur ya da bulamaz. Bileşen cache’te bulunamadıysa aygıttan çekilecektir. Bunun için GetDevDirEntry fonksiyonu kullanılır. GetDevDirEntry bir DIR_ENTRY nesnesi tahsis eder ve aygıttan okunan bilgileri DIR_ENTRY cache içerisinde saklar. GetDevDirEntry fonksiyonu aygıttan yol bileşeni için DIR_ENTRY bilgilerini alarak dizin girişi cache sistemine yerleştirir. Bu işlem sırasında aynı zamanda DIR_ENTRY nesnesine ilişkin i-node bilgileri de i-node cache sistemine çekilir. DIR_ENTRY GetDevDirEntry( PDIR_ENTRY pParentEntry, PCENTRY_NAME pEntryName ); Fonksiyon üst dizinin DIR_ENTRY adresini ve elde edilecek dizin girişinin ismini alır. GetDevDirEntry fonksiyonunun çağırma şeması şöyledir: GetCacheDirEntry allocDirEntry pParentInode->pOps->pfLookup putDirEntryCache PutInodeCache allocDirEntry yeni bir DIR_ENTRY nesnesini dilimli tahsisat sistemini kullanarak yaratır ve nesnenin bazı elemanlarını doldurur. Aygıttan DIR_ENTRY ve INODE nesnelerinin okunması tamamen INODE yapısına ilişkin pfLookup sanal fonksiyonu tarafından yapılmaktadır. pfLookup fonksiyonunun parametrik yapısı şöyledir: PDIR_ENTRY (*pfLookup)(PCINODE, PCDIR_ENTRY); Fonksiyon üst dizinin INODE nesne adresini ve bu dizinde aranacak olan bileşenin DIR_DENTRY nesne adresini parametre olarak alır. pfLookup sanal fonksiyonu elde ettiği DIR_DENTRY nesnesini PutDirEntryCache ile dizin girişlerine ilişkin cache sistemi içerisine, PutInodeCache ile de i-node cache içerisine yerleştirir. 12 Kaan Aslan Makale Arşivi – www.kaanaslan.net