Bir dil kendini nasıl genişletir? [kapalı]


208

C ++ öğreniyorum ve Qt'nin GUI programlarını kodlama yeteneklerinden bazılarını öğrenmeye başladım . Kendime şu soruyu sordum:

Daha önce işletim sistemi için bir pencere veya ağlar üzerinden iletişim kurmak için bir yol istemeyen hiçbir sözdizimine sahip olmayan C ++ (tamamen anlayamadığım API'larla, itiraf ediyorum) , C ++ 'da yazılmış kütüphaneler aracılığıyla bu tür yetenekleri aniden nasıl alır? Her şey benim için çok dairesel görünüyor. Bu kütüphanelerde hangi C ++ talimatlarını bulmanız mümkün?

Bu sorunun deneyimli bir yazılım geliştiricisi için önemsiz göründüğünün farkındayım, ancak doğrudan bir yanıt bulmadan saatlerdir araştırıyorum. Qt ile ilgili öğreticiyi takip edemediğim noktaya geldi, çünkü kütüphanelerin varlığı benim için anlaşılmaz.


27
Std :: cout monitörde nasıl bir şey çizer? Yoksa donanımınızı anlayan bir derleyicinin üzerine mi oturuyor?
doctorlove

14
Harika bir soru. Sonuçta, donanım çalışana kadar cevap vermek zor.
user541686

17
Qt, dilin genişletilmesi değildir (bu, Qt farkında bir derleyici gerektirir). Sadece cephaneliğinize eklenen bir kütüphane . Sonunda, en düşük düzeyde tüm kütüphaneler işletim sistemiyle dilden bağımsız olan, ancak işletim sistemine ve CPU mimarisine çok bağlı sistem çağrıları aracılığıyla iletişim kurar.
DevSolar

8
afaik, C ++ hemen hemen her şeyi yapabilen satır içi montajı var
Görünen Ad

9
@DevSolar: Aslında Qt dili kendi sinyal yuvası mekanizması, yansıması ve diğer birçok dinamik özellik ile genişletiyor. Ve bu şeyler C ++ koduna derlemek için bir derleyici (meta-nesne derleyicisi) gerektirir.
Siyuan Ren

Yanıtlar:


194

Bir bilgisayar soğan gibi, birçok sahiptir birçok dış uygulama katmanı saf donanımın iç çekirdekten katmanları. Her katman kendi kısımlarını bir sonraki dış katmana maruz bırakır, böylece dış katman bazı iç katman fonksiyonelliğini kullanabilir.

Örneğin Windows durumunda, işletim sistemi Windows üzerinde çalışan uygulamalar için WIN32 API'sini ortaya koyar. Qt kütüphanesi, kendi API'sına Qt kullanan uygulamalar sağlamak için bu API'yi kullanır. Qt kullanırsınız, Qt WIN32 kullanır, WIN32 Windows işletim sisteminin daha düşük düzeylerini kullanır ve donanımdaki elektrik sinyalleri gelene kadar devam eder.


56
Not: Qtburada altındaki katmanın bir özetini sağlar , çünkü Linux'ta QtWIN32 API'sini değil Linux API'sini çağırır.
Matthieu

5
Muhtemelen c ++ yeteneklerini genişletiyor gibi, Qt örneğinde biraz daha ayrıntılı olarak görüyorum. Gerçek olduğu zaman, ortak bir API yapmak için, çok farklı "soğan çekirdeklerine" (tartışmalı olarak) çok çaba harcadılar. Taşınabilir olmayan standart dışı arka uçların üzerinde taşınabilirlik sağlayanlardır.
luk32

81
Bir bilgisayar bir soğan gibidir: onu kesmek sizi ağlatır, ancak daha sonra biraz lezzetli olur.
alecov

3
@ChristopherPfohl Evet, bir bilgisayarın bir kutu çikolata gibi nasıl olacağını anlayamadığım için kullanmak zorunda kaldım. :)
Bazı programcı ahbap

1
@Celeritas muhtemelen öğretmen dedi user32.dllya da muhtemelen gdi32.dll.
user253751

59

Genel olarak, kütüphanelerin zaten mümkün olmayan hiçbir şeyi mümkün kılamayacağı konusunda haklısınız.

Ancak kütüphanelerin bir C ++ programı tarafından kullanılabilmesi için C ++ ile yazılması gerekmez. C ++ ile yazılmış olsalar bile, dahili olarak C ++ ile yazılmayan diğer kütüphaneleri kullanabilirler. C ++ kadar uzun olmadığı için, bu ilave engellemek değil yapmak için herhangi bir yol sunmadı gerçeği Yani bazı C ++ dışında bunu yapmanın yolu.

Oldukça düşük bir seviyede, C ++ (veya C) tarafından çağrılan bazı işlevler derlemede yazılır ve derleme, C ++ içinde mümkün olmayan (veya kolay olmayan) şeyleri yapmak için gerekli talimatları içerir, örneğin aramak için bir sistem işlevi. Bu noktada, bu sistem çağrısı bilgisayarınızın yapabileceği her şeyi yapabilir , çünkü onu durduracak hiçbir şey yoktur.


Diğer dillerde yazılmış kütüphanelerin zaten başka derleyiciler kullanılarak derlendiği anlamına mı geliyor? Ve sonra kütüphanenin C ++ 'a sağladığı her fonksiyon çağrısını kütüphanenin önceden derlenmiş bir versiyonuna bağlayan bir çeşit arayüz dosyası olmalı? Böylece C ++ derleyicisi bu çağrıları ne çevirmek bilmek izin?
Med Larbi Sentissi

2
@MedLarbiSentissi 1) Başka derleyiciler olmayabilir. Tek bir derleyicinin montaj da dahil olmak üzere birden fazla dili derleyebilmesi ve hatta C ++ 'ı satır içi derlemeyle derleyebilmesi mümkündür (ve genellikle böyle olur). 2) Belirli sistem ve derleyiciye bağlı olarak, bu işlevleri C ++ 'dan çağrılabilir yapmak gerçekten de bir çeşit arabirim dosyası ile yapılabilir, ancak bu tür bir arabirim dosyası zaten C ++' dan doğrudan kullanılabilen bir C (hatta C ++) başlığı olabilir.

1
@MedLarbiSentissi: Birçok windows kütüphaneleri, kendi arayüzlerini ve kodunu içeren dll dosyalarına derlenir. Bir dll'ye göz atabilir ve kullanmanıza izin veren işlevlerin bir listesini görebilirsiniz. Genellikle bir C başlık dosyası ile birlikte gelirler. Exe oluşturduğunuzda, çalıştırmak için gereken dll listesini içerir. OS exe'nizi yüklemeye çalıştığında, yürütmeye başlamadan önce otomatik olarak bu dll'leri de yükleyecektir.
Mooing Duck

8
Bu cevap, "sihir" in tamamen diğer dillerde çağrıldığını gösteriyor gibi görünüyor, ancak aslında en modern işletim sistemlerini oluşturan kodun çoğu C'dir (yalnızca montajda yazılmış çok donanım bağlantılı veya performans açısından kritik parçalar ile) - ve bunun yerine C ++ kullanmak kesinlikle mümkündür . Mesele şu ki, "sihir" yoktur, diller bu kadar güçlü soyutlamalar oluşturmak için yaratılmıştır ve donanım ile etkileşime girdiğinizde olasılıklar neredeyse sınırsızdır.
Matteo Italia

1
@hvd Bence bu tartışmadaki tüm çelişki, siz (ve diğerleri) için C'yi belirtilen özellikler olarak tanımlamanızdır. Aslında, derleyiciler belirtilenden çok daha fazlasını ekleyerek C'nin neyi cevaplaması önemsizdir sorusunu ortaya çıkarır. Benim için bir dille ilgili özel olan şey (bu yüzden olduğu şey), program akışını ifade etmenin meta yolu ve yapılandırma olanaklarıdır. Yapılandırılan öğeler bunun için önemli değildir, çünkü derleyiciler tarafından istedikleri gibi eklenebilecek daha güzel ASM kodu
LionC

43

C ve C ++, OP'nin bahsettiği tüm bu genişletilebilirliğe izin veren 2 özelliğe sahiptir.

  1. C ve C ++ belleğe erişebilir
  2. C ve C ++, C veya C ++ dilinde olmayan talimatlar için montaj kodunu çağırabilir.

Çekirdekte veya temel korumasız mod platformunda, seri bağlantı noktası veya disk sürücüsü gibi çevre birimleri RAM ile aynı şekilde bellek haritasına eşlenir. Bellek bir dizi anahtardır ve çevre biriminin (seri bağlantı noktası veya disk sürücüsü gibi) anahtarlarını çevirmek çevre birimlerinizi faydalı şeyler yapmak için alır.

Korumalı mod işletim sisteminde, çekirdeğe kullanıcı alanından erişmek istediğinde (dosya sistemine yazarken veya ekranda bir piksel çizerken) sistem çağrısı yapması gerekir. C'nin bir sistem çağrısı yapmak için bir talimatı yoktur, ancak C doğru sistem çağrısını tetikleyebilen birleştirici kodunu çağırabilir. Bu, kişinin C kodunun çekirdekle konuşmasını sağlar.

Belirli bir platformun programlanmasını kolaylaştırmak için, sistem çağrıları kendi programında bazı yararlı işlevleri yerine getirebilecek daha karmaşık fonksiyonlara sarılır. Birisi sistem çağrılarını doğrudan aramakta serbesttir (montajcı kullanarak), ancak platformun sağladığı sargı işlevlerinden birini kullanmak muhtemelen daha kolaydır.

Bir sistem çağrısından çok daha kullanışlı olan başka bir API düzeyi vardır. Örneğin malloc'u ele alalım. Bu sadece sistemi büyük bellek blokları elde etmek için çağırmakla kalmayacak, aynı zamanda gerçekleşen tüm kitapları tutarak bu belleği yönetecektir.

Win32 API'leri bazı grafik işlevlerini ortak bir platform widget seti ile sarar. Qt, Win32 (veya X Windows) API'sını çapraz platformda sararak bunu biraz daha ileri götürür.

Temel olarak bir C derleyicisi C kodunu makine koduna çevirir ve bilgisayar makine kodunu kullanacak şekilde tasarlandığından, C'nin aslan paylaşımını veya bir bilgisayarın neler yapabileceğini başarmasını beklemelisiniz. Sarıcı kütüphanelerinin yaptığı tek şey, sizin için ağır kaldırma yapmaktır.


Dikkat # 2: C ve C ++ sadece derleyicinin anladığı ve beklediği bir "çağrı kuralına" bağlı işlevleri çağırabilir. (Montaj kodu, istediği herhangi bir kuralı kullanabilir, hatta hiçbirini kullanamaz - bu nedenle kod doğrudan çağrılabilir olmayabilir.) Neyse ki, kendine saygılı her derleyici, platformun ortak kurallarını kullanmak için yerleşik bir yol sağlar. (Örneğin, Windows C derleyicileri, "cdecl", "stdcall" veya "fastcall" kurallarını kullanan işlevlere sahip olmanızı / bunları kullanmanıza izin verir.) Ancak derleme kodu, derleyicinin bildiği bir kural kullanmalı veya C ve C ++ ' t Doğrudan ara.
cHao

2
Ayrıca: bellek eşlemeli G / Ç yaygındır, ancak hikayenin tamamı değildir. Örneğin bilgisayarlar, x86'nın tamamen farklı bir mekanizma olan "I / O portları" kullanarak seri portlara, disk sürücülerine vb. (Video arabelleği genellikle bellek eşlemelidir, ancak video modları vb. Genellikle G / Ç bağlantı noktaları aracılığıyla kontrol edilir.)
cHao

@cHao: Elbette INP ve OUTP kullanan klasik yaklaşım DMA lehine dışlanıyor; PCI üretimi, bellek eşlemeli özel işlev kayıtlarıyla daha fazlasını yapıyor gibi görünüyor, artık cihazları otomatik olarak çakışmayan bölgelere eşlemenin ve sürücülerden keşfetmenin bir yolu var ve G / Ç bağlantı noktalarında daha az.
Ben Voigt

Modern çevre birimleri, toplu veri aktarımı için DMA kullanacak, ancak yine de DMA denetleyicisini adreslenebilir bellekle programlayacaksınız
doron

@doron: Umm, DMA denetleyicisini, en azından aklı başındaysanız, bir PC'deki G / Ç adres alanı (bellek alanı değil) aracılığıyla programlıyorsunuz. Modern x86 işlemciler, performansı artırmak için bellek erişimlerini yeniden sıralamayı sever. MMIO ile, bu felaket olabilir ... bu yüzden bu adresleri önbelleğe almamaya ve tüm doğru yerlere serileştirme talimatlarını koymaya dikkat etmelisiniz . OTOH, x86, G / Ç alanına okuma ve yazma işlemlerinin program sırasında yapılmasını sağlar. Bu yüzden önemli şeylerin çoğu hala G / Ç alanı (genellikle bir işaretçi ile erişilemez) aracılığıyla yapılır ve muhtemelen her zaman olacaktır.
cHao

23

(Gibi diller 11 C ++ ) olan özellikler kağıt üzerinde, genellikle İngilizce yazılmış. En son C ++ 11 taslağının içine bakın (veya masraflı nihai spesifikasyonu ISO satıcınızdan satın alın ).

Genellikle bazı dil uygulamalarına sahip bir bilgisayar kullanırsınız (Prensip olarak herhangi bir bilgisayar olmadan bir C ++ programı çalıştırabilirsiniz, örneğin, bir grup insan kölesi yorumlayarak; etik olmayan ve verimsiz olurdu)

C ++ uygulama geneliniz bazı işletim sistemlerinin üzerinde çalışır ve onunla iletişim kurar ( bazı sistem kitaplıklarında uygulamaya özel bazı kodlar kullanarak ). Genellikle iletişim sistem çağrıları yoluyla yapılır . Örneğin , Linux çekirdeğinde mevcut sistem çağrılarının bir listesi için sistem çağrılarına (2) bakın .

Uygulama açısından, bir sistem çağrısı, SYSENTERbazı sözleşmelerle ( ABI ) x86-64 gibi temel bir makine talimatıdır

Linux masaüstümde Qt kütüphaneleri, X11 ve Xorg sunucuları arasında X Windows protokolleri ile iletişim kuran X11 istemci kitaplıklarının üzerindedir .

Linux'ta, lddkütüphanelerdeki bağımlılıkların (uzun) listesini görmek için yürütülebilir dosyalarınızı kullanın. Kullanım pmapsizin çalıştıran süreci üzerinde olanlar çalışma zamanında "yüklü" olduğunu görmek için. BTW, Linux'ta, uygulamanız muhtemelen sadece özgür yazılım kullanıyor, neler olduğunu daha fazla anlamak için kaynak kodunu (Qt, Xlib, libc, ... çekirdek) inceleyebilirsiniz.


2
Referans olarak, ANSI C ++ 11 spesifikasyonunu 60 $ 'dan biraz daha az çirkin bir fiyata satıyor . (Eskiden yarısı vardı, ama enflasyon.: P) INCITS / ISO / IEC 14882 olarak etiketlendi, ancak ISO'nun sunduğu en azından aynı temel özellik. Hata / TR'den emin değilim.
cHao

19

Bence eksik olan kavram sistem çağrıları . Her işletim sistemi, düşük düzey işletim sistemiyle ilgili şeyler yapmak için kullanabileceğiniz çok büyük miktarda kaynak ve işlevsellik sağlar. Normal bir kütüphane işlevini çağırsanız bile, muhtemelen perde arkasında bir sistem çağrısı yapıyor demektir.

Sistem çağrıları, işletim sisteminin gücünü kullanmanın düşük düzeyli bir yoludur, ancak kullanımı karmaşık ve kullanışsız olabilir, bu nedenle API'lara genellikle "sarılır", böylece doğrudan onlarla uğraşmanıza gerek kalmaz. Ancak altında, O / S ile ilgili kaynakları içeren yaptığınız hemen hemen her şey, yazdırma, ağ ve soketler gibi sistem çağrılarını kullanacaktır.

Windows durumunda, Microsoft Windows GUI'sinin çekirdeğe yazıldığından, pencereler, resim grafikleri vb. Yapmak için sistem çağrıları vardır. Diğer işletim sistemlerinde GUI çekirdeğin bir parçası olmayabilir, bu durumda Bildiğim kadarıyla GUI ile ilgili şeyler için herhangi bir sistem çağrısı olmayacaktı ve yalnızca düşük seviyeli grafikler ve girişle ilgili çağrılar mevcut olduğunda daha da düşük bir seviyede çalışabilirsiniz.


3
Eksik olan önemli şey, bu sistem çağrılarının hiçbir şekilde sihir olmamasıdır. Genellikle C (++) ile yazılmış çekirdek tarafından servis edilir. Ayrıca, sistem çağrıları bile gerekli değildir. Bellek koruması olmayan ilkel işletim sistemlerinde, pikseller doğrudan donanım çerçeve arabelleğine yerleştirilerek pencereler çizilebilir.
el.pescado

15

İyi soru. Her yeni C veya C ++ geliştiricisi bunu göz önünde bulundurur. Bu yazının geri kalanı için standart bir x86 makinesi varsayıyorum. Microsoft C ++ derleyicisi kullanıyorsanız, not defterinizi açın ve bunu yazın (Test.c dosyasını adlandırın)

int main(int argc, char **argv)
{
   return 0
}

Ve şimdi bu dosyayı derleyin (geliştirici komut istemini kullanarak) cl Test.c /FaTest.asm

Şimdi Not Defteri'nde Test.asm açın. Gördüğünüz şey çevrilmiş koddur - C / C ++ derleyiciye çevrilir. İpucu var mı?

_main   PROC
    push    ebp
    mov ebp, esp
    xor eax, eax
    pop ebp
    ret 0
_main   ENDP

C / C ++ programları metal üzerinde çalışacak şekilde tasarlanmıştır. Bu, donanımın özelliklerinden yararlanmayı kolaylaştıran daha düşük seviyeli donanıma erişimleri anlamına gelir. Diyelim ki, bir x86 makinesine bir C kütüphane getch () yazacağım.

Montajcıya bağlı olarak şu şekilde bir şeyler yazarım:

_getch proc 
   xor AH, AH
   int 16h
   ;AL contains the keycode (AX is already there - so just return)
ret

Bir derleyici ile çalıştırın ve bir .OBJ oluşturmak - Getch.obj adı.

Daha sonra bir C programı yazıyorum (hiçbir şey eklemiyorum)

extern char getch();

void main(int, char **)
{
  getch();
}

Şimdi bu dosyayı adlandırın - GetChTest.c. Getch.obj dosyasını ileterek bu dosyayı derleyin. (Veya GetChTest.exe dosyasını oluşturmak için .obj ve LINK GetChTest.Obj ve getch.Obj için ayrı ayrı derleyin).

GetChTest.exe'yi çalıştırın ve bunun klavye girişini beklediğini göreceksiniz.

C / C ++ programlama sadece dil ile ilgili değildir. İyi bir C / C ++ programcısı olmak için, çalıştığı makinenin türü hakkında iyi bir anlayışa sahip olmanız gerekir. Bellek yönetiminin nasıl işlendiğini, kayıtların nasıl yapılandırıldığını vb. Bilmeniz gerekir. Düzenli programlama için tüm bu bilgilere ihtiyacınız olmayabilir - ancak bunlar size son derece yardımcı olacaktır. Temel donanım bilgisinin yanı sıra, derleyicinin nasıl çalıştığını (yani, nasıl tercüme edildiğini) anlarsanız kesinlikle yardımcı olur - bu da kodunuzu gerektiği gibi değiştirmenizi sağlayabilir. İlginç bir paket!

Her iki dil de __asm ​​anahtar sözcüğünü destekler; bu, derleme dil kodunuzu da karıştırabileceğiniz anlamına gelir. C ve C ++ öğrenmek genel olarak daha iyi bir yuvarlak programcı yapar.

Her zaman Assembler ile bağlantı kurmak gerekli değildir. Bahsetmiştim, çünkü bunun daha iyi anlamanıza yardımcı olacağını düşündüm. Çoğunlukla, bu tür kütüphane çağrıları, İşletim Sistemi tarafından sağlanan sistem çağrılarını / API'larını kullanır (işletim sistemi de donanım etkileşimi işlerini yapar).


10

C ++ ... aniden C ++ 'da yazılmış kütüphaneler aracılığıyla bu tür yetenekleri nasıl elde eder?

Diğer kütüphaneleri kullanmanın büyülü bir yanı yok. Kütüphaneler, arayabileceğiniz basit büyük çantalardır.

Kendinize böyle bir işlev yazmayı düşünün

void addExclamation(std::string &str)
{
    str.push_back('!');
}

Şimdi bu dosyayı eklerseniz, addExclamation(myVeryOwnString); . Şimdi, "C ++ aniden bir dizeye ünlem işareti ekleme yeteneğini nasıl elde etti?" Cevap çok kolay: Bunu yapmak için bir fonksiyon yazdınız, sonra çağırdınız.

C ++ 'ın C ++ ile yazılmış kütüphaneler aracılığıyla pencereleri çizme yeteneklerini nasıl alabileceği hakkındaki sorunuzu yanıtlamak için, cevap aynıdır. Birisi bunu yapmak için işlev (ler) yazdı ve sonra bunları derledi ve size bir kütüphane şeklinde verdi.

Diğer sorular, pencere çiziminin gerçekten nasıl çalıştığını cevaplıyor, ancak kütüphanelerin nasıl çalıştığı konusunda şaşkın geliyorsunuz, bu yüzden sorunuzun en temel kısmını ele almak istedim.


8

Anahtar, işletim sisteminin bir API'yi gösterme olasılığı ve bu API'nın nasıl kullanılacağı hakkında ayrıntılı bir açıklamadır.

İşletim sistemi, arama kurallarına sahip bir dizi API sunar. Çağıran kural, bir parametrenin API'ye nasıl verildiğini ve sonuçların nasıl döndürüldüğünü ve gerçek çağrının nasıl yürütüleceğini tanımlar.

İşletim sistemleri ve onlar için kod oluşturan derleyiciler birlikte güzel oynarlar, bu yüzden genellikle düşünmek zorunda değilsiniz, sadece kullanın.


7

Pencereler oluşturmak için özel bir sözdizimine gerek yoktur. Gerekli olan tek şey, işletim sisteminin pencereleri oluşturmak için bir API sağlamasıdır. Böyle bir API, C ++ 'ın sözdizimi sağladığı basit işlev çağrılarından oluşur.

Ayrıca C ve C ++, sistem programlama dilleri olarak adlandırılır ve isteğe bağlı işaretleyicilere (donanım tarafından bazı cihazlarla eşleştirilebilir) erişebilir. Ayrıca, işlemcinin sağladığı tüm işlemlere izin veren montajda tanımlanan işlevleri çağırmak da oldukça basittir. Bu nedenle, C veya C ++ ve az miktarda montaj kullanarak bir işletim sistemi yazmak mümkündür.

Ayrıca, C ++ 'sözdizimini genişletmek için meta bir derleyici kullandığı için Qt'nin kötü bir örnek olduğu belirtilmelidir . Ancak bu, aslında pencereleri çizmek veya oluşturmak için işletim sistemi tarafından sağlanan API'leri arama yeteneği ile ilgili değildir.


7

İlk olarak, biraz yanlış anlaşılma var, sanırım

Daha önce işletim sisteminden bir pencere veya ağlar üzerinden iletişim kurma yolunu soramayacak bir sözdizimi olmayan C ++ nasıl

İşletim sistemi işlemleri için bir sözdizimi yoktur . Anlambilim meselesi .

aniden C ++ 'da yazılmış kütüphaneler aracılığıyla bu tür yetenekleri elde edin

Peki, işletim sistemi çoğunlukla C ile yazılır . Harici kodu çağırmak için paylaşılan kütüphaneleri (dll) kullanabilirsiniz. Ayrıca, işletim sistemi kodu sistem rutinlerini sistem çağrılarına * veya derlemeyi kullanarak arayabileceğiniz kesintilere kaydedebilir . Paylaşılan kütüphaneler genellikle bu sistemi sizin için çağırır, böylece satır içi montajı kullanmazsınız.

İşte bununla ilgili güzel öğretici: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
Linux için ama ilkeler aynı.

İşletim sistemi grafik kartlarında, ağ kartlarında vb. İşlemleri nasıl yapıyor? Bu çok geniş bir temadır, ancak çoğunlukla kesintilere, bağlantı noktalarına erişmeniz veya özel bellek bölgesine bazı veriler yazmanız gerekir. Bu işlemler korunduğundan, bunları işletim sistemi aracılığıyla yine de aramanız gerekir.


7

Diğer cevaplara biraz farklı bir bakış açısı sağlamak amacıyla, ben böyle cevaplayacağım.

(Feragatname: Bazı şeyleri biraz basitleştiriyorum, verdiğim durum tamamen varsayımsal ve hayata% 100 gerçek olmaktan ziyade kavramları göstermenin bir aracı olarak yazılıyor).

Diğer perspektiften düşünün, temel iş parçacığı, pencereleme ve bellek yönetimi özelliklerine sahip basit bir işletim sistemi yazdığınızı hayal edin. Kullanıcıların C ++ programlamak ve pencere yapmak, pencere çizmek vb gibi şeyler yapmak için bir C ++ kitaplığı uygulamak istiyorsunuz. Soru, bunu nasıl yapılır.

İlk olarak, C ++ makine kodunu derlediğinden, C ++ ile arayüz oluşturmak için makine kodunu kullanmanın bir yolunu tanımlamanız gerekir. Burada fonksiyonlar devreye giriyor, fonksiyonlar argümanları kabul ediyor ve dönüş değerleri veriyor, böylece farklı kod bölümleri arasında veri aktarımı için standart bir yol sağlıyorlar. Bunu, bir şey olarak bilinen bir şey kurarak yaparlar. çağıran bir sözleşme .

bir çağıran kongre durumları ve yürütüldüğünde aldığında bir işlev onları bulabilmesi argümanlar bellekte yerleştirilmelidir nasıl. Bir işlev çağrıldığında, çağıran işlev bağımsız değişkenleri belleğe yerleştirir ve CPU'dan diğer işleve atlamasını ister ve burada geri çağrıldığı yere geri dönmeden önce ne yaptığını yapar. Bu, çağrılan kodun kesinlikle herhangi bir şey olabileceği ve işlevin çağrılma biçimini değiştirmeyeceği anlamına gelir. Ancak bu durumda, işlevin arkasındaki kod işletim sistemiyle ilgili olacaktır ve işletim sisteminin dahili durumunda çalışacaktır.

Böylece, aylar sonra tüm işletim sistemi işlevlerinizi çözdünüz. Kullanıcınız pencereler oluşturmak ve üzerlerine çizim yapmak için işlevleri çağırabilir, iş parçacıkları ve her türlü harika şeyleri yapabilir. Sorun şu ki, işletim sisteminizin işlevleri Linux işlevlerinden veya Windows işlevlerinden farklı olacaktır. Bu nedenle, kullanıcıya taşınabilir kod yazabilmeleri için standart bir arayüz vermeniz gerektiğine karar verirsiniz. İşte QT devreye giriyor.

Neredeyse kesin olarak bildiğiniz gibi, QT'nin işletim sistemlerinin yaptığı şeyleri yapmak için birçok temel sınıf ve işlevi vardır, ancak altta yatan işletim sisteminden bağımsız olarak görünür. Bunun çalışma şekli, QT'nin kullanıcıya göründüğü gibi tekdüze sınıflar ve işlevler sağlamasıdır, ancak işlevlerin arkasındaki kod her işletim sistemi için farklıdır. Örneğin, QT'nin QApplication :: closeAllWindows () yöntemi, kullanılan sürüme bağlı olarak her işletim sisteminin özel pencere kapatma işlevini çağırır. Windows'da büyük olasılıkla CloseWindow'u (hwnd), X Pencere Sistemini kullanan bir işletim sisteminde muhtemelen XDestroyWindow'u (ekran, pencere) çağırır.

Açıkça görüldüğü gibi, bir işletim sisteminin birçok katmanı vardır, bunların hepsi birçok çeşidin arayüzleri aracılığıyla etkileşime girmelidir. Dokunmadım bile pek çok yönü var, ama hepsini açıklamak çok uzun zaman alacaktı. İşletim sistemlerinin iç işleyişi ile ilgileniyorsanız, OS dev wiki'ye göz atmanızı öneririz .

Bununla birlikte, birçok işletim sisteminin arayüzleri C / C ++ 'a maruz bırakmayı seçmesinin sebebinin makine koduna derlenmeleri, montaj talimatlarının kendi kodlarıyla karıştırılmasına izin vermeleri ve programcıya büyük ölçüde özgürlük sağlamaları gerektiğini unutmayın.

Yine, burada çok şey oluyor. .So ve .dll dosyaları gibi kitaplıkların C / C ++ ile nasıl yazılması gerekmediğini ve derleme veya diğer dillerde yazılabileceğini açıklamak istiyorum, ancak daha fazla eklersem de bir makalenin tamamını yazın ve bunu yapmak istediğim kadarıyla üzerinde barındıracak bir sitem yok.


6

Ekranda bir şey çizmeye çalıştığınızda, kodunuz nihayet CPU'nun çalışabileceği özel bir talimat olan bir "sistem çağrısı" olana kadar başka bir kod (vb.) Çağıran başka bir kod parçasını çağırır. Bu yönergeler derlemede yazılabilir veya derleyici kendi içsellerini (derleyicinin "özel olarak" CPU'nun anlayabileceği özel koda dönüştürerek işlediği işlevler) destekliyorsa C ++ ile yazılabilir. Görevleri işletim sistemine bir şey yapmasını söylemektir.

Bir sistem çağrısı gerçekleştiğinde, ekran sürücüsüne ekranda bir şey çizmesi söylenene kadar başka bir işlevi (vb.) Çağıran bir işlev çağrılır. Bu noktada, görüntü sürücüsü içinde belirli bir bölgede bakar fiziksel bellek aslında değil bellek, ancak yazılabilir ziyade bir adres aralığı sanki hafıza idi. Ancak bunun yerine, bu adres aralığına yazmak grafik donanımının bellek yazımını engellemesine ve ekranda bir şeyler çizmesine neden olur .
Belleğin bu bölgeye yazma şeydir olabilir sadece normal bir bellek erişimi bulunuyor yazılım tarafında beri, C ++ kodlanmış. Sadece donanım onu ​​farklı şekilde ele alıyor.
Yani bu işe nasıl gerçekten temel bir açıklama.


4
Afaik bir sistem çağrısı gerçekten bir cpu talimatı değildir ve intrinsiklerle ilgisi yoktur. Daha çok, cihazlarla iletişim kuran işletim sistemi çekirdeğinin bir işlevi.
MatthiasB

3
@MatthiasB: Eh, yanılıyorsun, syscall(ve kuzeni sysenter) gerçekten bir CPU talimatı.
user541686

2
Bu, cevabımı geliştirmek için sadece bir ipucuydu, çünkü kendim için net değildi. Kişisel saldırı veya başka bir şey olarak görmeyin.
MatthiasB

1
@MatthiasB: Ben şahsen almıyorum. Zaten cevabın aslında% 100 doğru olmadığını bildiğimi söylüyorum ama OP'ye cevap vermek için yeterince iyi bir basitleştirme olduğunu düşünüyorum - bu yüzden, aslında daha iyi bir cevap yazmanın bir yolunu biliyorsanız, lütfen ya kendiniz yazın benimkini düzenlemek veya zaman ayırmak. Gerçekten buna değer olduğunu düşündüğüm bir şeyim yok, bu yüzden bu sayfada daha iyi bir şey görmek istiyorsanız, çaba harcamanız gerekecek.
user541686

3
Sistem çağrıları yazılım kesintileri kullanılarak yapılır. sysenterKesme işleyicileri tarafından kullanılan bağlamsal anahtarlama herkesin istediği kadar hızlı olmadığı için, bu gibi talimatlar optimize edilmiş çağrı yollarıdır, ancak temel olarak işletim sistemi çekirdeği tarafından yüklenen bir işleyiciye vektörleme ile işlenirken hala bir kesme üretilir. IS'nin gerçekleştirdiği bağlam değiştirme işleminin bir kısmı, sysentertüm ayrıcalıklı talimatlara, kayıtlara, bellek ve G / Ç alanlarına tam erişim - 0 halkasını ayarlamak için işlemcideki mod bitlerini değiştirmektir.
Ben Voigt

4

C ++ programınız Qt kitaplığını kullanıyor (C ++ ile de kodlanmış). Qt kitaplığı Windows CreateWindowEx işlevini (kernel32.dll içindeki C ile kodlanmıştır) kullanacaktır. Ya da Linux altında Xlib (C olarak kodlanmış) kullanıyor olabilir , ancak X protokolünde " Lütfen benim için bir pencere oluştur " anlamına gelen ham baytları da gönderebilir .

Senin İlişkin yakalama 22 daha sonra kendisini derlemek olabilecek şekilde, ilk sürümü derlemek olabilir bu nedenle birkaç C ++ kavramları, yeterli uzunlukta bir C derleyicisi oldu aslında rağmen “birinci C ++ derleyicisi C ++ yazılmış” olduğunu tarihsel not soruya ise .

Benzer şekilde, GCC derleyicisi GCC uzantılarını kullanır: önce bir versiyona derlenir ve daha sonra kendini yeniden derlemek için kullanılır. (GCC oluşturma talimatları)


2

Soruyu nasıl gördüğüm bu aslında bir derleyici sorusu.

Bu şekilde bakın, Z ++ olarak adlandırmak istediğiniz yeni yazılı dilinizi Assembly'ye çeviren Assembly'ye (herhangi bir dilde yapabilirsiniz) bir kod parçası yazıyorsunuz, basitlik için derleyici (bu bir derleyici) .

Şimdi bu derleyiciye bazı temel işlevler veriyorsunuz, böylece int, string, diziler vb. Yazabilirsiniz. Aslında derleyicinin kendisini Z ++ 'da yazabilmeniz için yeterli yetenekler veriyorsunuz. ve şimdi Z ++ için yazılmış bir derleyiciniz var, oldukça düzgün.

Daha da havalı olan, şimdi sahip olduğu yetenekleri kullanarak bu derleyiciye yetenekler ekleyebilmeniz, böylece önceki özellikleri kullanarak Z ++ dilini yeni özelliklerle genişletebilmenizdir.

Bir örnek, herhangi bir renkte bir piksel çizmek için yeterli kod yazarsanız, istediğiniz herhangi bir şeyi çizmek için Z ++ kullanarak genişletebilirsiniz.


0

Donanım bunun olmasını sağlayan şeydir. Grafik belleğini geniş bir dizi olarak düşünebilirsiniz (ekrandaki her pikselden oluşur). Ekrana çizmek için C ++ veya bu belleğe doğrudan erişim sağlayan herhangi bir dil kullanarak bu belleğe yazabilirsiniz. Bu belleğe sadece grafik kartıyla erişilebilir veya grafik kartında bulunur.

Modern sistemlerde, grafik belleğine doğrudan erişmek, çeşitli kısıtlamalar nedeniyle bir sürücü yazmayı gerektirir, böylece dolaylı araçlar kullanırsınız. Bir pencere (gerçekten sadece herhangi bir görüntü gibi bir görüntü) oluşturan ve ardından bu görüntüyü GPU'nun ekranda görüntülediği grafik belleğine yazan kütüphaneler. İşaretçilere yönelik olan belirli bellek konumlarına yazma yeteneği dışında dile hiçbir şey eklenmemelidir.


Belirtmeye çalıştığım nokta, dilin yeni bir versiyonunun yeniden yazılması gerektiği anlamında bir dilin kendisini "genişletmesi" gerekmediği ve ilginç bir şey yapmak için gerçekten dairesel olmadığıdır donanım ile arayüz gerekir.
john
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.