10 Kasım 2009 Salı

Warning: Your body is infected by A(H1N1) virus

Söylenenler sahiden doğruymuş; bu grip denen melet hemde h1n1'li si ilaçlı 7 gün ilaçsız 1 haftada geçiyor. Önceki hafta Cuma günü beni yatağa mıhlayıp bugün itibari ile doğrulmama izin verdiği için saygıdeğer virüsümüze sonsuz şükranlarımı iletiyorum. Doğrusunu söylemek gerekirse diğer grip sendromlarının çok üstünde bir efor harcattı bünyeme. Doktor tarafından verilen ilaçlardan tutunda annemin bitkisel ilaç karışımlarına kadar onlarca şey denemem sadece bol bol uyumama neden oldu ve hala beynimdeki ve ellerimde ki uyuşukluk geçmiş değil bu yüzden imla hataları ve saçmalamalar yüzünden peşinen özür diliyorum :)

Hastalık sürecinde canımı en çok sıkan ama alışkanlıktan olsa gerek pek umursatmayan ülkemiz insanlarının ve onları bu denli bir paranoyaya sokan devlet organları ve medyanın tutumu oldu. 2 gün üst üste , gece yarıları dahil farklı saat dilimlerinde 7 kez 5 farklı hastaneye (2'si devlet 3'ü özel) girme girişimim derbi maç öncesi stat önünden farksız olan kalabalık yüzünden başarısızlıkla sonuçlandı. İnsanlar çıldırmış gibi hastahanelere akın etmişler. Bir kez hapşıran da gelmiş , gözü sulanan da. Benim gibi 41 derece ateşliler ise ya o hengamede beklemeyi tercih edecek ya da evine gidip makus kaderine razı olup yorganı üstüne çekecek.

Soranlar olabilir ! Nereden biliyorsun o virüsü taşıdığını ? diye. Tabi ki bilmiyorum ama karşılaşma fırsatı bulduğum ve 1dk lık bir görüşme şansı yakaladığım acil dokturu ile aramda geçen diyalog:

Dr House - "hımm " dereceye bakıyor "40 derece .... kaç gündür hastasın"
Ben - "bugün 4.gün ve ateşim 38.5 ile 41 arasında"
Dr House - "bulantı, ishal filan oldumu?"
Ben - "evet sanırım 18 kez istiğfra ettim ve karın kaslarım işlemez halde"
Dr House - "delikanlı işte sende kapmışsın domuzun gribini ama neyse varmı evde ilacın?"
Ben - "Evde??? İlaç ???"
DR House - "tmm " bişiler karalıyor "bunları al istrahat et"

Bende bu gribin birilerinin cebini doldurabilmek için türetilmiş bir varyant olduğunu düşünenlerdenim ve onların asla kazanmasını istemem ancak hayatınızdan vereceğiniz bir 5 gününüz yoksa gidip Sam amcanın iğnesini vurulmakta bir şık olarak önünüze çıkıyor.

Hepinize sağlıklı ve mutlu günler.

3 Kasım 2009 Salı

Günlükten Çıkanlar - 2

2005 Yılının ajandasınıda buldum , sadece 8 sayfa not karalamışım ve birbirinden kopuk bilgilerden oluşuyor lakin meraklıları için güzel nimet :

- Device Driver'lar SYSTEM olark anılan özel bir context'te çalışırlar. Bunu taskmanager'da görünen SYSTEM kullanıcısı olarakta görebiliriz.

- Her Aygıt sürücüsü (Device Driver) bir Device Name tag'ı ile tanımlanır. Her sürücü kullanacağı aygıt için bir isim oluşturmalıdır.

- Sürücüler DriverEntry rutininde aygıt için DeviceObject adı verilen aygıtı tanımlayısı sistem taraflı bir nesne ve SymbolicLink adı da verilen ve aygıt adının usermode tarafında da görülebilmesini sağlyan ortak nesne yaratır. Ayrıca bazı driver'a ve aygıta özel başlangıç işlemleride yapar.

- Driver'lar fiziksel bir aygıtı kontrol etmek zorunda değildirler. Bunun yerine sadece sürücü kodu içerisinde verilen görevleride yapabilirler. Ancak unutulmaması gereken en önemli husus bu kodların ring0 denilen en imtiyazlı seviyede çalıştıklarıdır.

- Driver'lara yapılan tüm istekler birer I/O Request Packet (IRP) biçiminde yollanır. Driver, tüm sürücü istekleri için önceden DriverEntry rutininde tanımlanmış olan fonskiyon pointer'larını SYSTEM context'inde bekler.

- Tüm işlemlerin virtual address (sanal adresleri) aynı olabilir ancak fiziksel sayfaları farklı adresleri işaret eder.

- Farklı process'lerin her iki modda aynı hafıza alanını kullanabilmesi için named memory mapped file oluşturması gerekmektedir.

- ObReferenceObjectByHandle komutu belirtilen handle'in istenen erişim izinlerine uygun olup olmadığına bakar. Eğer handle'a istenilen kriterlerde erişim izni verilirse programcıya STATUS__SUCCESS durumu döner.

- 32bit işlemciler bir hafıza adresine erişirken 16bit'lik bir Segment Selector ve 32bit'lik segmentle birlikte kullanılacak offset değeri kullanır.

- Segmentlere erişim ile alakalı gerekli blgiler işlemciye segment table yoluyla aktarılır.Segment Selector, segment table içindeki bir index'tir.

- Herhangi bir anda yalnızca 2 adet segment tablosu aktif olabilir. Bunlar GDT v LDT'dir.

- Segment Selector'de ki bir bit kullanılarak CPU hangi Segment tablosunu kullanacağına karar verir.

- Segment Descriptor'lar, hafızanın bir bölgesini işaret eden bilgiyi ve o bölgeye erişebilmek için gereken erişim haklarına ait bilgiyi tutar. Segment Descriptorlar , Segment Tablosunun içerisinde array şeklinde yer alırlar. Bir Segment Descriptor kısaca bir segmentin başlangıç adresi ile boyutunu tutar ve imtiyaz seviyesini belirten DPL olarakta bilinen 2 bit'i kullanır.

- İşlemci bir segment'e erişim izni vermeden önce DPL ve RPL'i karşılaştırır. RPL selector'de yer alan 2 bitlik bir imtiyaz belirteçidir.

- Address Translation işlemindeki ilk adım, segmetin taban adresi ile offset'in toplanmasıdır. Bu işlemin sonucunda eğer paging mekanizması aktif değil ise doğrudan çıkan sonuç fiziksel adresi gösterir. Paging aktif ise bu adrese logical veya lineer adres adı verilir ve fiziksel adresi bulabilmek için eldeki veri tekrar Paging Address Translation adı verilen bir başka mekanizmaya devr edilir.

- Memory Management şeması Paging olarak anılır. Çünkü Hafıza, Pages olarak bilinen sabit boyutlu birimler halinde tanımlanır. Intel işlemciler üzerinde bir sayfa 4kb olarak varsayılır.

- 32bit Adresleme ile fiziksel hafıza ancak 4GB adreslenebilir. Bunun anlamı 1 milyon sayfayı adresleyebilirsiniz demektir.

- Bir PageDirectoryEntry'si eğer LSB(Least Significant bit) bit'i 1 ise geçerli olarak değerlendirilir.

- WindowsNT her process için ayrı bir PageTable tutar ve bunun sanal adres aralığıda 0xC0000000 dan 0xC03fffff'dir.

- Page Table Directory (1024)1K adet Page Table'in adresini tutar. PDT Lineer adresin son 10bit'inde (22-32 bitleri) yer alır ve bu tabloda ki bir girişe işaret eder.

- Page Table , adresleri PDT'de bulunan ve kendi tablolarında 1024 adet PageTableEntry(PTE) tutan PageTableFrame(PTF)'ye işaret eden tablolardır. Lineer adresin 12 ve 22 bit'leri arasında yer alır.

- Address space olarak bilinen kavram PageDirectory'den başka bişi değildir. Page Directory'nin gösterdiği table'lar üst yarısı bütün process'ler için aynıdır.

- MMCreateProcessAddressSpace fonksiyonu hafızanın 3 aşağıdaki işler için ayırır:
Birinci sayfayı PageDirectory için, ikinci sayfayı HyperSpace Page table girişlerini tutmak için ve 3.Sayfayıda Process ilk defa oluşturulduğunda working set olarak anılan , processin .code , .data , stack gibi nesnelerini tutmaya yarayan hafıza öbeğinin adresini tutar.

- Memory-Mapped, dosyaları, NT section nesneleri ile çalışabilmek için kullanır.

- Bir Process'in çalışma anında fiziksel hafızaya alınamayan kısımları işaretlenir. Process ne zaman hafızada bulunmayan bir datasına ulaşmaya çalışırsa , önceden işaretlenmiş alanlar ikincil depolama aygıtından (senaryomuzda bu hdd'dir) ana hafızaya getirilir.

- Eğer İşletim sistemi fiziksel hafızayı(RAM) tüketirse kendine yer açailmek için bazı dataları atmak durumunda kalır. Ancak bu boşaltım işlemi geri dönüşümsüz bir silinme şeklinde değil swapping yapılarak tekrar hdd'ye atılır ve dilendiği zaman oradan geri alınabilir. Bu dataların atılma işlemine karar verme mekanizması "Replacement Policy" olarak bilinir. Bu mekaizmada WindowsNT FIFO(İlk giren ilk çıkar) yönetimini kullanarak yerine getirir. Bu policy'ye göre bir yer sıkıntısı olduğunda bellekte ki en eski veri atılmış olacaktır.

- Eğer bir Page fiziksel Ram'in üzerinde map edilmemişse WindowsNT bu sayfayı "invalid" olarak işaretler. Bu sayfaya herhangi bir erişim gerçekleşirse bir "page fault" gerçekleşir ve bu hatayı yakalayan "page fault handler" hdd'den ilgili datayı az önce yukarıdaki bahsettiğimiz şekilde getirir.

- Eğer Page bir dll veya executable code içeriyor ise saygfa da o ilgili dll veya exe dosyadan alınır. Şayet sayfa bir data içeriyor ise sayfayı swap dosyasından alacaktır. Yani kod içeren bölgeler datalardan önceliklidir. Eğer sayfa Memory-Mapped paylaşımlı dosya alanından alınacak ise sayfa uygun dosyadan alınır.

- Windows NT fiziksel hafızadaki boş alanı sürekli tahrip eder, böylece bir page fault meydana geldiğinde hdd'den çıkarılacak sayfa için yer ayırabilecektir. Bu takip bilgileri, Page Frame Database (PFD) olarak anılan Kernel data yapısında tutulur.

- PFD hafızadaki sayfaları FIFO tabanlı bir listede tutar ve yer sıkıntısı olduğu durumlarda atılacak sayfaya karar verir. Ancak bir sayfayı atmadan önce WindowsNT bu sayfanın "dirty" kirli olmadığından emin olmalıdır. Dirty biti sayfanın yazılmış olduğunu ve hafızadan atılmak icap eden durumlarda bu sayfanın ilgili swapping işlemine uygun olduğunu gösterir. Ayrıca PFD paylaşılan sayfalar içine bir referans sayacı tutar ve yalnız bu sayaç ilgili sayfa için sıfır olduğunda atılır. Genelde PFD her fiziksel sayfanın durumuna bakar. PFD her fiziksel sayfa için 24byte 'lık bir array'dir. PFD arrayinin boyutu bir kernel değişkeninde depolanan fiziksel sayfanın sayısına eşittir. Bu değeri tutan değişken "MmNumberOfPhysicalPages"'dir. PFD'nin adresini yine bir kernel değişkeni olan MmPfnDatabase tutar. Bir fiziksel sayfa farklı durumlarda olabilir. Örneğin in-use, free ,free ama dirty gibi. PFD girişi bir doubly linkd list'e ve fiziksel sayfanın durumuna bağlıdır. Örneğin boş sayfaları tanımlayacak PFD girişleri free page listesine bağlıdır.

- Virtual Address Descriptor: Windows NT her boş fiziksel sayfanın listesi ile birlikte ayrıca her Process için ayrılmış olan virtual address boşluğunuda izlemeye ihtiyaç duyar. Bir Process ,bir hafıza bloğu ayırmak istediği zaman ki bu işlem örneğin bir dll i hafızaya almakta olabilir bu esnada WindowsNT Virtual Address boşluğundaki boş bloklar için bir kontrol yapar ve ondan sonra gereken yeri ayırır, ve Virtual Address map'i bu doğrultuda günceller ve hali ile bu işlem bilgilerini alabileceği en doğru yer Page Table'dir.

- IO Manager , gerekli şartlar oluşup bir IRP oluşturulduğunda IRP yapısının AssociatedIRP.SystemBuffer alanına usermode'da yer alan buffer'indaki bilgiyi geçer.

2 Kasım 2009 Pazartesi

Biraz sinerji katalım

Takip edenler bilir, yaklaşık bir aydır eski nostaljim olan kernelmode dünyasına geri döndüm. Kendisi ile 2 sene önce hazin bir ayrılık yaşamış ve highlvl yollarını aşındırır olmuştum. Sağolsun Emre Tınaztepe ve Kutalmis dostlarım sayesinde tekrar gerçeten severek uğraştığım işe geri döndüm. Bu sebeple yıllar önce şirketteki a4 ve toner kapasitesinin tükenmesine neden olduğum kernelmode dökümanlarımı tekrar gün yüzüne çıkardım ve hararetle okumaya başladım.

Dökümanları karıştırıken günlük gibi tuttuğum ve iyice sararmaya yüz tutmuş olan not defterime denk geldim. Okudukça iyiki yazmışım bunları dedim ve sizlerle paylaşmak için hemen bloguma giriş yaptım. Umarım sizlerinde işine yarar:

== 2004 ==
- User-Mode kodları Objectlere handle'ları kullanarak erişir ancak Kernel-Mode kodları Object'lere doğrudan erişirken pointer'ları kullanır.

- Object'lerde bulunan ReferenceCount hem user-mode dan handle lar vasıtası ile yapılan erişimlerde hem de kernel-mode'dan yapılan erişimlerde 1 artar.

- Bir process zaten çok küçük zaman aralıklarında çalıştığından (quantum slice) hafıza bölgelerinede bitişik olsalar dahi çok küçük erişim boyutlarında erişir.

- İşletim Sistemi, bir processin sadece o an hafızada çalıştığı kümelerini (bknz:working set) saklamaya ihtiyaç duyar

- Her device controller local bir buffer'a sahiptir. CPU bu local bufferdan, ana hafızaya veya ana hafızdan local buffera data taşır

- I/O: Aygıttın kendi device controllerinde bulunan local buffer'a yapılan işlemdir.
Device controller daha sonra bu i/o işleminin bittiğini Cpu'ya interrupt kullanarak bildirir.

- Trap bir kullanıcı hatası veya başka bir problemden dolayı meydana gelen yazılımsal bir interrupt'tır

- I/O Manager, bir IRP oluşturduğunda _IRP yapısının AssociatedIrp.SystemBuffer buffer alanına kullanıcı taraflı buffer alanındaki bilgiyi geçer.

- IofCompleteRequest çağrısı ile bir irp için gerekli işlemlerin tümünün yapıldığı varsayılır. Bu komut sonrasında I/O Manager driver taraflı buffer alanını user taraflı buffer alanına kopyalar.

- IRQL Notları

1.Bir fonksiyona girdiğinizde mutlaka IRQL'ni kontrol edin
2.Her hangi bir fonksiyonu çağırmadan önce IRQL'ı için DDK'ya göz atın
3.Eğer bir thread en düşük IRQL seviyesinde çalışıyorsa onu daha fazla alt seviyeye indiremezsiniz, ancak yükseltebilirsiniz.
4.DISPATCH_LEVEL da PAGE_FAULT yaşamazsınız
5.Paging I/O APC level'da yapılır
6.Kullanıcı her zaman PASSIVE_LEVEL da çalışır
7.Kernel'de PASSIVE_LEVEL da çalışabilir.
8.PASSIVE_LEVEL da iş yükü dağıtımına izin verilir
9.DPC'ler DISPATCH_LEVEL da çalışırlar ve preempt edilemez(etkisizleştirilemez) (ama interrupt edilebilirler tabiki) ve dispatcher olduklarından DISPATCH_LEVEL'da çalışırlar.
10.IRQL'ları manipüle etmek için KeLowerIrql() ve KeRaiseIrql fonksiyonları kullanılır.

- IRP Notları

1.IRP'ler bir uygulamanın veya driver'in davranışları üzerinden IoManager tarafından üretilirler. IRP'in üst kısmı (header) sabit bilgilerden oluşur, alt kısım ise stack location adı verilen bilgi yığınından oluşur.
2.Uygulama driver'a yalnızca kontrolü IRP'lar vasıtası ile devredebilir, ve bilgiler paylaşılan bir hafıza tarafından değiş tokuş edilir.
3.IoManager driver'lar için bir IRP kuyruğu tutmaz, sadece ne zaman alınacaklarını ve gönderileceklerine bakar. IRP'leri kuyruklamaktan driver kendisi sorumludur.
4.IRP sürücü IoCompleteRequest isteği çağrıldığında işlemini sonlandırır.
5.Irp->IoStatus.Information transfer edilen data boyutunu içerir ve bu bilgi usermode tarafındaki DeviceIOController'in en son paramtresi olan bytesreturned'e aktarilir.
6.IoManager geri donen bilgiyi SystemBuffer'dan OutputBuffer'a kopyalar.
7.IoCompleteRequest fonksiyonu IoManager'a bildirilen en son IRP çağrısıdır ve bu IRP'in artık işinin sona erdiğini bildirir. Bu çağrı bir kez yapıldıktan sonra artık o IRP'e erişilemez.
8. Driver'dan Driver'a IRP'ler vasıtası ile haberleşilebilir. Driver'lar aynı adres boşluğunda çalıştıklarından her biri bir diğeri ile paylaşımlı hafıza alanları sayesinde iletişim kurabilir.
9.IRP, sürücü katmanları arasında dolaşabilir. Bu IRP'in bilgilerine IoGetCurrentIrpStackLocation çağrısı ile ulaşılabilir.

İşe yarar temelinizi oluşturacak şeyler buldukça paylaşmaya devam edeceğim... ,

Şimdilik sağlıcakla.