CSD İşletim Sistemi Çekirdeğinin Sanal Dosya

advertisement
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
Download