Kayıt: Feb 14, 2003 Mesajlar: 94 Nereden: İstanbul
Tarih: Fri Sep 16, 2005 8:26 pm Mesaj konusu: dll kullanımı ile ilgili 2 soru
Selamlar;
Konunun başlığını detaylandıramadım,çünkü sormak istediğim şeyler bir parça birbirlerinden kopuk durumdalar.
1-Şimdi kendi yarattığımız bir class'ı export eden bir .dll yazıp,bunu bir .exe dosyasına bağlıyoruz.MSDN'den okuduğuma göre biz .exe dosyasını çalıştırdığımız anda sistem .dll'in içindeki class'ı,onun üye fonksiyonlarını ,değişkenlerini ve dll'deki diğer global fonksiyonları bizim .exe dosyamızın bellek alanına yazıyor (.lib dosyası ile dll'in en başta otomatik olarak yüklendiğini farz ediyorum,implicit linking hesabı). Fakat öte yandan,.dll içerisindeki bir DllCreateClassObject(CObj** ppObj) tarzı fonksiyonla yine .dll içerisinde, dinamik olarak bir CObj yarattığımız zaman, exe içerisinde bunu
Kod:
delete pObj;
diye silmeye kalktığımızda program patlıyor.Bu nedenle pObj->Release() ile objeye kendini
Kod:
delete this;
şeklinde, dll içerisinde sildiriyoruz.
Benim anlamadığım; dll exe'nin bellek alanına yükleniyorsa dll'in dinamik yarattığı objeleri exe'nin silebilmesi gerekmez mi?Sonuçta exe'nin de dll'in de kullandıkları bellek alanı aynı? Eğer kendilerine ait farklı bellek alanları varsa,o zaman biz nasıl oluyor da exe üzerinden dll'in yarattığı ve onun bellek alanında bulunan objenin pointeri ile sorunsuz bir şekilde üye fonksiyonları çağırabiliyoruz?
Kafam karıştı açıkçası.
2-Bu sorum ise dll'in __declspec( dllexport ) ile export ettiği ve exe'nin
__declspec( dllimport ) ile import ettiği fonksiyonlarla ilgili.
şeklinde tanımlanmış global bir fonksiyonu kod içerisinde herhangi bir yerde
Kod:
.
.
int a;
KareAl(&a,15);
.
.
diye çağırdığımız zaman,CPU bu fonksiyonun compiler tarafından decorated edilmiş adı ile ilişkilendirilmiş,exe içindeki bellek adresine atlıyor,daha önceki fonksiyona ait lokal değişkenler CPU registerlerinden stack'a yazılıyor;parametreler (&a,15 gibi) ,yeni lokal değişkenler falan duruma göre registerlere alınıyor,yeni fonksiyonun kodu çalışmaya başlıyor.Yeni fonksiyon sonlanınca giriş işlemlerinin tersi yapılıyor,bir önceki fonksiyona dönülüyor.
Peki dll tarafından export edilen bir fonksiyonu exe içinden çağırdığımız zaman ekstra birşey yapılıyor mu?Eğer hakikaten dll, exe ile aynı bellek alanına yükleniyorsa,teorik olarak normal bir fonksiyon çağrımı ile aynı şekilde olması lazım gibi geliyor bana.
(Eğer dll'den import edilen fonksiyonlar için ekstra işlemler varsa,bayağı yavaşlaması lazım uygulamanın.Örneğin gl.h içerisinde bir sürü, opengl32.dll kütüphanesinden import edilen fonksiyonun prototipi var ve bunlar glVertex3f,glDrawElements gibi çok sık kullanılan fonksiyonlar.Yani dll fonksiyonları için ayrı işlemler yapılması gerekliyse GL programları sürünebilirdi--çok düz bir mantıkla düşünürsek)
Kısaca normal uygulama içindeki bir fonksiyonu çağırmakla,dll'den import edilen fonksiyonu çağırmak arasında bir fark oluyor mu?
Biraz spesifik mevzular olduğu için bunlarla ilgili pek uygun kaynak bulamadım internette,yardımcı olabilirseniz sevinirim.İyi çalışmalar.
The_Cuisinart bir önceki açtığın formunda yazmıştım. Ama okumadın heralde gittin msdn'ye hemen, illa gevurcamı yazıcaz.
senin exe'nin .idata bölümünde kullanmak istediğin fonsiyonların adları yazar. Windows senin exeyi çalıştırıken dll'deki istediğin fonksiyonları
hafızaya yükler ve "Adresini" senin exenin .idata bölümüne gerekli olan yere yazar sende dll fonsiyonunu çağırırsın
tıpkı bunun gibi:
asm
call [498878..] bu sayı senin exenin üzerinde bulunan boş bir yerdir oraya windows dll fonsiyonun hafızasındaki yerini atar sende çağırır kullanırsın.
dll fonsiyonu senin programın içinde normal fonsiyonla aynı biçimde kullanılır.
Kayıt: Feb 14, 2003 Mesajlar: 94 Nereden: İstanbul
Tarih: Sat Sep 17, 2005 11:07 am Mesaj konusu:
Alıntı:
The_Cuisinart bir önceki açtığın formunda yazmıştım. Ama okumadın heralde gittin msdn'ye hemen, illa gevurcamı yazıcaz.
Devreci, abi sakin, bak ben ne kadar sakinim, le le le sakine hatta . Işık ve sevgiyle
Herhalde COM başlığından bahsediyorsun? Abi orada mevzu farklıydı ya.
Neyse cevabın teşekkürler.Son birşey daha sorucam.Şimdi dll fonksiyonu 475894... diye bir adrese yazılıyor ve call[ 475894...]
diye fonksiyon çağrılıyor.Burada 475894... dll fonksiyonunun direk başlangıç yeri mi oluyor? Normal exe fonksiyonunu call Kare diye çağırdığımızda sonuçta oradaki "Kare" de bir adresin yerine geçmiyor mu?
Kısaca call[ 475894...] ve call Kare deyince cpu fonksiyonların başına atlayıp kodu çalıştırmaya başlıyor,normal exe fonksiyonun tek farkı adresi "Kare" adı altında bilmemiz mi?
evet hocam o sayının gösterdiği hafızanın içine windows dll fonksiyonunun adresinin başlangıç yerini yazar. Bu nedenle her zaman aynı sayı çıkmaz.
kare fonksiyonunun yeride exe içinde bellidir.
Com da ise o sayı içindeki sayının içinde sırasıyla fonksiyonların yerleri yazılıdır. Bizim için tek farkı fonksiyonu adı ile değil numarası ile çağırmamız.
Kayıt: Nov 02, 2002 Mesajlar: 215 Nereden: Istanbool
Tarih: Sun Sep 18, 2005 8:49 pm Mesaj konusu:
hodo...
o kadar basit degil. dll icinde 'new'ledigin birseyi dll icinde 'delete' etmek durumunda kaliyorsun. Sebebi de suna benzer birsey (%100 dogru olmayabilir ama %99 dogru) : windows dll'in kullandigi memory'i birden fazla .exe'ye mapleyebilir.. sonucta 10 tane process o dll'i kullaniyorsa, hepsi de dll'in kendilerine ait birer kopyasi oldugunu zannedecektir, ama aslinda yoktur, dll'in fiziki ram'de sadece tek kopyasi vardir, di mi.. dll'in kendine gore bir address space'si olmasi gerekir yani.. yani tam boyle degil de buna benzer birsey...
simdi bu kopyanin icinde bir 'new' komutu calisigini dusun.. dondurdugu adress hani process'in memory space'sinde olacak? :))
Bunun overhead'ina gelince de, zaten windows'da hersey kendi address space'inde calisiyor, yani programin kullandigi adreslerin hicbiri gercek fiziksel adresler degil.... normal bir program bir func cagirirken ne kadar penalty yiyorsan aynisini yersin...yani tam aynisini degil sanirim bir-iki instruction fark var. frame basina 100,000 milyon kere glVertex3F cagirmazsan olculebilir bir fark olusmaz.
Devreci: COM'un bunlarla alakasi yok. COM'da function pointer'lar dynamic olabilir, object'lere runtime'da baglanabilir, COM ile DLL arasinda zerre benzerlik yok. COM'da zart diye function pointerine jumplamazsin. O function pointeri o DLL'in icinde olmayabilir, hatta o PC'nin icinde de olmayabilir, networkdeki baska bir makinada da olabilir, DCOM olabilir o adres..
zaten function pointer dersen com'un essence'sini pas gecmis olursun.. orada hersey interface, o interface'lere ulasmani saglayan sey de com interface manager, coCreateInstance dedigin zaman o interface'i support eden obceyi sen yaratmiyorsun, dll'deki bir offset'e jum etmiyorsun, o adresi sana COM veriyo., dedigim gibi o adres network'deki baska bir makinada da olabilir ve ona ulasmak icin, salliyorum, encryption'a, kerberos authentication'a ihtiyacin olabilir..Sen de ne sorarlarsa mov eax, 13; int 10h; diye cevap veriyorsun. When all you have is an hammer, everything begins to look like a nail.
ah ulan sensei olacakti da cevap yazacakti bu soruya.
Kayıt: Nov 02, 2002 Mesajlar: 215 Nereden: Istanbool
Tarih: Sun Sep 18, 2005 10:37 pm Mesaj konusu:
Ziiirnn...
bir ii sey daha.
bir com dll'i memory'e yuklendigi zaman illa onu yukleyen process ile ayni address space'de olacak diye birsey yoktur. eger com objecini inproc olarak cocreate etmezsen, o obje senin processin disinda baska bir process'e yuklenir.
aslinda soyle desek daha bir rahat anlasilabilir belki.
bir dll'in icine bir c++ class'i koydun ve export ettin ya..
onun yerine soyle yap.. bir .cpp ve bir .h'dan olusan bir dll dusun.
.cpp icine class'in tanimini ve implementasyonunu yaz.
class XBitmap olsun mesela bu.
sonra .h icinde sadece XBitmap'in PUBLIC methodlarindan olusan bi class yaz - XBitmapInterface.
butun XBitmapInterface metodlari virtual yap ve XBitmap'i XBitmapInterface'den derive et.
.h icinde
lucyfer sen hala c++ dan örnek veriyorsun. cpu da cointa.. intsance..
vs bu gibi naneler yok. Eğer bu kadar iyi biliyosun bu işleri bu COm'u
makine nasıl işliyor anlat bi. Mesela DCOM dan bir fonsiyonu çalıştırıken
cpu neler yapıyo aydınlat bizi .
@devreci: sevgili devreci, cpu'ları ve asm'yi sevmeni ilgiyle takip ediyorum. kolay gelsin ama alakalı alakasız her konuyu cpu'ya taşımanın da bi alemi yok. eh, com da dll de exe de çalıştırılabilen (executable) dosyalar. onu biliyoruz hepimiz. yapısal olarak alakaları yok, işlevsel olarak illa ki aynı işleve sahipler bi şekilde. cpu ne alaka ya.
Kayıt: Feb 14, 2003 Mesajlar: 94 Nereden: İstanbul
Tarih: Mon Sep 19, 2005 2:54 pm Mesaj konusu:
Lucifer, cevaplar için sağol.COM nedir, ne değildir ince ince anlıyorum; MSDN'de "FROM CPP TO COM" diye bayağı güzel bir döküman var,adamın biri sağolsun üşenmemiş,oturmuş, dll içindeki basit bir C++ sınıfını adım adım bir COM objesine dönüştüren bir döküman yazmış.Bastım 44 sayfa tuttu,koçyiğit bir abiymiş demekki.Gerçi döküman tam 10 yıllık ama olsun.İnceliyorum şu aralar.
Dll fonksiyonlarının overhead mevzusuna gelince,üşenmedim ne olup bitiyor diye basit bir konsol programına kendi yaptığım bir dll'i ekledim.Dll içinde void A() diye global bir fonksiyon var,exe'nin void B() diye bir global fonksiyonu var.
diye çağrılıyor.Dediğim gibi asm'den anlamam fakat B() fonksiyonu exe'nin kod sectionu içinde neredeyse, o (0041....) sayısı orayı gösteriyor,compiler B() gördüğü her yerde cpu'nun direk o adrese atlaması için gerekli olan kodu yazıyor sanırım. A() ise aslen function pointer mantığı ile çalışıyor,__imp_AHedeHodo,yani (0045....) adresinde aslında dll fonkisyonunun "kendisi" değil,"adresi" var.(0045....) adresindeki adrese gidip fonksiyonu çalıştırıyor cpu.Bir nevi indirection galiba.Direct,indirect addressing diye iki farklı olay bunlar yine galiba ama en iyisi burda durayım ben,çok low level mevzular, maymun olmam tehlikesi var.
Son olarak dll'de memory alloc konusuna gelirsek;
Olayı başlarda yanlış yorumladım,zira benim deneme için yaptığım dll 3-5 gudik matematik işlemi yapan methodlara sahip bir class export ediyordu,bunu yükleyip kullanan sadece benim client programım vardı doğal olarak.Ama kernel32.dll falan gibi cevval sistem ve runtime dll'lerini haliyle her process ayrı ayrı kullanmak zorunda.Yalnız tam bu noktada bazı kavram karmaşaları yaşıyorum, şimdi "dll'in bellekte bir örneği var,windows bunu processlere map eder."Buradaki mapping işleminden kasıt sisteminin processlere dll fonksiyonlarının pointerlarını vermesi değil mi? Böylece birsürü prosesin bellekteki tek bir fonkisyona birsürü pointeri olacak.
Bir de address space kavramı,her prosesin fiziksel bellekte kendine ait adres alanları var diyoruz.Fakat "Kullandığı adresler gerçek fiziksel adresler değil" ne anlama geliyor ? Ha bir de,bir prosesin içindeki pointer'ın başka bir prosesin adres alanındaki bir fonksiyona falan işaret etmesi illegal bir mevzu değil miydi,sanki ben öyle hatırlıyorum ilk C++ öğrendiğim zamanlardan.
Kayıt: Nov 02, 2002 Mesajlar: 215 Nereden: Istanbool
Tarih: Mon Sep 19, 2005 3:39 pm Mesaj konusu:
The_Cuisinart demiş ki:
MSDN'de "FROM CPP TO COM" diye bayağı güzel bir döküman var,adamın biri sağolsun üşenmemiş,oturmuş, dll içindeki basit bir C++ sınıfını adım adım bir COM objesine dönüştüren bir döküman yazmış.Bastım 44 sayfa tuttu,koçyiğit bir abiymiş demekki.Gerçi döküman tam 10 yıllık ama olsun.İnceliyorum şu aralar.
ben de benzeri bir yaklasimla anlatan bir kitaptan ogrenmistim. adam once 'hadi bir c++ classi yazip dll'den export edelim' sonra 'bu class'i oyle yazalim ki dll'i kullananlarin cpp include etmesi gerekmesin' sonra 'bu dll/lib her c++ compileri tarafindan kullanilabilsin' sonra 'her dilden kullanilabilsin' sonra 'scriptle bile erisilebilsin(activex)' diye gidiyordu
Alıntı:
Fakat "Kullandığı adresler gerçek fiziksel adresler değil" ne anlama geliyor ?
her process'in 2 gb'lik bir adress space'i var... yani windowsta calisan her process kendine ait 2 gb'lik memory goruyor. bir process'in kullandigi 0x00040000 adresi ile baska process'in kullandigi 0x00040000 adresi fiziki ram'de ayni yere denk gelmiyor yani. bu nasil yapiliyor dersen, virtual memory bu zaten, cpu uzerinde iki adet special registerimiz var (es:di), bu register'ler memory'de virtual memory map'e point ediyor... aslinda fiziksel ram 4 kb'lik segmentlere bolunmus durumda, ama bir trick ile her process continuous bir 2 gb'lik block'a sahip oldugunu zannediyor...
igrenc anlattim, aksam eve gibince duzgunce yazayim.
Kayıt: Feb 14, 2003 Mesajlar: 94 Nereden: İstanbul
Tarih: Mon Sep 19, 2005 9:36 pm Mesaj konusu:
Lucifer,hocam nasıl oluyor bu yahu,dediklerinden hiçbir şey anlamadım.
Benim bildiğim bir virtual memory mevzusu vardı,o da RAM'da yer kalmayınca windows'un harddisk üzerinde RAM'ı taklit eden bir dosya oluşturmasıydı.
Yani şimdi biz
int x;
diye bir integer'in &x diye adresini aldığımızda çıkan o afilli 0x0045A1 bilmemne sayısı bize onun fiziksel adresini vermiyor mu?????
Yıkıldı tüm gençlik hayallerim,canevimden vuruldum.
Kayıt: Nov 02, 2002 Mesajlar: 215 Nereden: Istanbool
Tarih: Tue Sep 20, 2005 10:45 am Mesaj konusu:
The_Cuisinart demiş ki:
Benim bildiğim bir virtual memory mevzusu vardı,o da RAM'da yer kalmayınca windows'un harddisk üzerinde RAM'ı taklit eden bir dosya oluşturmasıydı.
Yani şimdi biz
int x;
diye bir integer'in &x diye adresini aldığımızda çıkan o afilli 0x0045A1 bilmemne sayısı bize onun fiziksel adresini vermiyor mu?????
evet, ayni fiziksel adresi vermiyor.
welcome to the real world
hemen soyle dusunelim: makinada 128 mb ram var, ve bizim program 256 mb memory kullaniyor. Windows sana ram saglayabilmek icin swap aciyor... elimizdeki afili 0x0045A1 adresi artik degil ram'de gercek fiziksel bir adres gostermeyi, ram'i bile gostermiyor, hard disk uzerinde bir sektor'e point ediyor yani onlarin hepsi sanal adres. o adreslerin gercek fiziki adreslere map'lenmesi icin de ram'de bir yerlerde virtual memory table diye birsey tutuluyor, o tabloda her process'e ait memory bilgileri var... mesela A process'inin 0x0045A1 adresi RAM 3. chip 5 sira 32. transistorde, B process'inin 0x0045A1 adresi RAM 1. chip 3. sira hede, C process'inin 0x0045A1 adresi swap01/page32/'de gibi..
eger C process'i calistirilirken 0x0045A1 adresini access etmek isterse, swap01/page32/'deki bilgi ram'de bos bir yere aktarilitor, virtual memory table update ediliyor (C process'inin 0x0045A1 adresi RAM 2. chip hede'de diye) ve bizim C process'i arka planda olup biten olaylarin farkina bile varmadan o adresteki datayi okuyor.
buna benzer birsey.
her adresse access ettiginde tablo'dan lookup yapmamak icin de, cpu'nun uzerinde bir takim adanmis (dedicated) register'ler var bu lookup icin, onu kullaniyorlar.
Kayıt: Feb 14, 2003 Mesajlar: 94 Nereden: İstanbul
Tarih: Tue Sep 20, 2005 6:54 pm Mesaj konusu:
Lucifer,abi iyi hoş diyorsun da şimdi ben bir Ctrl+Alt+Del yaptığım zaman 44 ayrı çalışan process görüyorum(Hakikaten).Bunlardan mesela Ahmet adlı program 1000 integer kullansa bunun 1000 ayrı adresi olucak,Mehmet adlı program 3500 tane float kullansa onların 3500 ayrı adresi olacak,Hasan 500 tane kendi tanımladığı bir classtan kullansa onların 500 ayrı adresi olacak.Kalan 41 tanesi de ayrı.Şimdi virtual address table'ın bunca değişkenin,datanın virtual adresine karşılık fiziksel adres tutması sırf bu üç program için 1000+3500+500=5000 tane bölüme karşılık geliyor,diğer 41 processi de ekle yani bu table başlı başına devasa bir yapı haline gelmez mi?????
Hız mevzusuna hiç girmiyorum,elbet virtual-physical dönüştürme yapması için alengirli bir sürü ayrı chiptir,devredir vardır elbet.
Ha bir de 44 process yüklü olduğu halde benim 512 mb RAM'ın yarısı boş.Yani doğası gereği böyle yüzlerce megabyte bellek isteyen bir sürü program vardır elbet, ama belleğin tamamen dolup diske yazdığına çok şahit olmadım bilgisayarın.(Zaten swap yapınca disk langır langır ötüyor,hız inanılmaz derecede düşüyor.)Yani ciddi bir şekilde RAM yetersizliği çekildiği bir zamanda bu virtual memory sistemine geçilmesi daha mantıklı olmaz mıydı?RAM'ın yarısı boşken sistemin virtual-physical çevrimi biraz fuzuli gibi geliyor?
Kayıt: Nov 02, 2002 Mesajlar: 215 Nereden: Istanbool
Tarih: Wed Sep 21, 2005 12:54 pm Mesaj konusu:
Ahmet 1000 tane integer kullanirsa bunlarin cogu stack'de olacak zaten. program da onlara stack+12'deki int'i float'a cast et, bir arttir, stack + 15'deki float'a yaz gibi kullanacak. yani, makina dili adreslemenin cogu zaten relative (izafi). if (..) then (...) endif diye bir kalipta, eger if'in icindeki TRUE degilse endif'e jumplar ya... o jumpladigi yer zaten gercek bir adres degildir, (jump 15_byte_ileri) gibi birsey...
bir de adressler virtual demek, her byte adresi tek tek tablolarda tutuluyor degil, fiziki ram 4 kb'lik bloklara bolunmus durumda, bu bloklarin adresleri tutuluyor.
soyle aslinda
44 process'in hepsinin kendi virtual address table'i var. buna processin kendisi de ulasamaz, islemci seviyesinde kullanilan birsey bu.
misal process 21, 0x4c7c6fb82934 diye bir adresten data okuyacak.
windows bir process'e switch ettigi zaman cpu'nun 'es' ve 'di' register'larina process'in virtual address table'sinin indeksini yazar. process 21 icin bu adres 0x0011223344 fiziki adresi olsun.
process 21 aktif ve 0x4c7c6fb82934 adresinui okuyacak.
her adresin ilk bilmemkac biti, o adresi kullanan process'in virtual adress tablosuna bir indextir.
process 21 ve 0x4c7c6fb82934 adresi icin bu deger 0x4c7c olsun.
her offsette 4 kb'lin continuous fiziksel bir adres datasi bulunur.
cpu es:di'den 0x0011223344 degerini okuyarak tablonun ofsetini bulur..
buna 0x4c7c ekleyerek 0x0011223344 + 0x4c7c diye bir fiziki address bulur.
bu fiziki adresin 0x4c7c6fb82934 - 0x4c7c00000000'inci offseti, process'in ulasmak istedigi fiziki adrestir.
butun bunlarin yapilmasi 0 (zero) clock cycle surer. pipeline icinde bu is icin ozel atanmis transistorler var cunku.
Bu forumda yeni konular açamazsınız Bu forumdaki mesajlara cevap veremezsiniz Bu forumdaki mesajlarınızı değiştiremezsiniz Bu forumdaki mesajlarınızı silemezsiniz Bu forumdaki anketlerde oy kullanamazsınız