Bagaimana bahasa berkembang sendiri? [Tutup]

208

Saya belajar C ++ dan saya baru mulai belajar tentang beberapa kemampuan Qt untuk mengkode program GUI. Saya bertanya pada diri sendiri pertanyaan berikut:

Bagaimana C ++, yang sebelumnya tidak memiliki sintaks yang mampu meminta OS untuk jendela atau cara untuk berkomunikasi melalui jaringan (dengan API yang saya juga tidak mengerti, saya akui) tiba-tiba mendapatkan kemampuan seperti itu melalui perpustakaan yang ditulis dalam C ++ sendiri? Semua itu tampak melingkar bagiku. Instruksi C ++ apa yang bisa Anda buat di perpustakaan itu?

Saya menyadari pertanyaan ini mungkin tampak sepele bagi pengembang perangkat lunak yang berpengalaman tetapi saya telah meneliti selama berjam-jam tanpa menemukan respons langsung. Sudah sampai pada titik di mana saya tidak bisa mengikuti tutorial tentang Qt karena keberadaan perpustakaan tidak bisa dimengerti oleh saya.

Med Larbi Sentissi
sumber
27
Bagaimana std :: cout menggambar apa pun di monitor? Atau apakah itu duduk di atas kompiler yang mengerti perangkat keras Anda?
doctorlove
14
Pertanyaan yang bagus Pada akhirnya sulit untuk menjawab sampai Anda mempelajari perangkat keras.
user541686
17
Qt bukan perluasan bahasa (yang membutuhkan kompiler sadar-Qt). Ini hanyalah perpustakaan yang ditambahkan ke gudang senjata Anda. Akhirnya, pada level terendah semua perpustakaan berkomunikasi dengan OS melalui panggilan sistem, yang tidak tergantung pada bahasa, tetapi sangat tergantung pada OS dan arsitektur CPU.
DevSolar
8
afaik, C ++ memiliki inline assembly, yang dapat melakukan hampir semua hal
Display Name
9
@DevSolar: Sebenarnya Qt tidak memperluas bahasa dengan mekanisme slot sinyal sendiri, refleksi dan banyak fitur dinamis lainnya. Dan hal-hal itu memerlukan kompiler (kompiler meta-objek) untuk dikompilasi ke kode C ++.
Siyuan Ren

Jawaban:

194

Komputer seperti bawang, ia memiliki banyak lapisan, dari inti perangkat keras murni hingga lapisan aplikasi terluar. Setiap lapisan memperlihatkan bagian dirinya ke lapisan luar berikutnya, sehingga lapisan luar dapat menggunakan beberapa fungsi lapisan dalam.

Dalam kasus misalnya Windows sistem operasi memperlihatkan apa yang disebut WIN32 API untuk aplikasi yang berjalan pada Windows. Pustaka Qt menggunakan API itu untuk menyediakan aplikasi yang menggunakan Qt ke APInya sendiri. Anda menggunakan Qt, Qt menggunakan WIN32, WIN32 menggunakan tingkat yang lebih rendah dari sistem operasi Windows, dan seterusnya sampai sinyal listrik di perangkat keras.

Beberapa programmer Bung
sumber
56
Catatan: di Qtsini menyediakan abstraksi dari lapisan di bawahnya, karena di Linux Qtmemanggil API Linux dan bukan WIN32 API.
Matthieu M.
5
Saya mungkin akan sedikit lebih pada contoh Qt, yang baru saja muncul, seperti itu dengan mudah memperluas kemampuan c ++. Ketika kenyataannya, mereka melakukan banyak upaya, untuk membuat API umum, untuk (masih bisa diperdebatkan) banyak "inti bawang" yang berbeda. Mereka adalah yang menyediakan portabilitas selain backend non-portabel non-portabel.
Luk32
81
Komputer itu seperti bawang: memotongnya membuat Anda menangis, tetapi setelah itu rasanya agak enak.
alecov
3
@ChristopherPfohl Ya, harus menggunakannya karena saya tidak tahu bagaimana komputer akan seperti sekotak coklat. :)
Beberapa programmer dude
1
@Citasitas guru mungkin berkata user32.dll, atau mungkin gdi32.dll.
user253751
59

Anda benar bahwa secara umum, perpustakaan tidak dapat membuat apa pun yang mungkin belum terjadi.

Tetapi pustaka tidak harus ditulis dalam C ++ agar dapat digunakan oleh program C ++. Bahkan jika mereka ditulis dalam C ++, mereka mungkin secara internal menggunakan perpustakaan lain yang tidak ditulis dalam C ++. Jadi fakta bahwa C ++ tidak menyediakan cara untuk melakukannya tidak mencegahnya ditambahkan, asalkan ada beberapa cara untuk melakukannya di luar C ++.

Pada level yang cukup rendah, beberapa fungsi yang dipanggil oleh C ++ (atau oleh C) akan ditulis dalam assembly, dan assembly berisi instruksi yang diperlukan untuk melakukan apapun yang tidak mungkin (atau tidak mudah) di C ++, misalnya untuk memanggil fungsi sistem. Pada titik itu, panggilan sistem dapat melakukan apa pun yang mampu dilakukan komputer Anda, hanya karena tidak ada yang menghentikannya.


sumber
Apakah maksud Anda perpustakaan yang ditulis dalam bahasa lain sudah dikompilasi menggunakan kompiler lain? Dan kemudian harus ada semacam file antarmuka yang menghubungkan setiap panggilan fungsi yang disediakan untuk C ++ oleh perpustakaan ke versi perpustakaan yang telah dikompilasi? Dengan demikian memungkinkan kompiler C ++ untuk mengetahui apa yang harus diterjemahkan ke dalam panggilan?
Med Larbi Sentissi
2
@MedLarbiSentissi 1) Belum tentu kompiler lain. Mungkin saja (dan ini sering terjadi) bahwa satu kompiler tunggal mampu mengkompilasi banyak bahasa, termasuk rakitan, dan bahkan mungkin mampu mengkompilasi C ++ dengan inline assembly. 2) Bergantung pada sistem dan kompiler tertentu, membuat fungsi-fungsi yang dapat dipanggil dari C ++ memang dapat dilakukan dengan semacam file antarmuka, tetapi file antarmuka semacam itu mungkin sudah merupakan header C (atau bahkan C ++) yang langsung dapat digunakan dari C ++.
1
@MedLarbiSentissi: Banyak pustaka windows dikompilasi menjadi file dll yang berisi antarmuka mereka sendiri, serta kode. Anda dapat mengintip ke dalam dll dan melihat daftar fungsi yang digunakannya. Mereka sering juga datang dengan file header C. Ketika Anda membuat exe Anda, itu berisi daftar dll yang perlu dijalankan. Ketika OS mencoba memuat exe Anda, ia akan secara otomatis juga memuat dll tersebut sebelum memulai eksekusi.
Mooing Duck
8
Jawaban ini tampaknya menunjukkan bahwa "keajaiban" terletak sepenuhnya dalam bahasa lain yang dipanggil, tetapi sebenarnya sebagian besar kode yang membentuk sebagian besar sistem operasi modern adalah C (dengan hanya bagian yang sangat terikat pada perangkat keras atau kinerja-kritis yang ditulis dalam rakitan) - dan sangat mungkin untuk menggunakan C ++ sebagai gantinya. Intinya adalah, tidak ada "sihir", bahasa diciptakan untuk membangun abstraksi yang sangat kuat, dan begitu Anda dapat berinteraksi dengan perangkat keras kemungkinannya hampir tak terbatas.
Matteo Italia
1
@ DVD Saya pikir seluruh konflik dalam diskusi ini adalah bahwa Anda (dan lainnya) mendefinisikan C sebagai fitur yang ditentukan untuknya. Bahkan, kompiler menambahkan lebih banyak dari yang ditentukan, membuat pertanyaan tentang apa yang agak tidak sepele untuk dijawab. Bagi saya hal khusus tentang bahasa (dengan demikian hal itu adalah) adalah cara meta untuk mengekspresikan aliran program dan kemungkinan untuk menyusun. Elemen-elemen yang terstruktur tidak penting untuk itu, karena hanya ASM-code yang lebih bagus yang dapat ditambahkan oleh kompiler sesuai keinginan
LionC
43

C dan C ++ memiliki 2 properti yang memungkinkan semua ekstensibilitas yang dibicarakan oleh OP ini.

  1. C dan C ++ dapat mengakses memori
  2. C dan C ++ dapat memanggil kode assembly untuk instruksi yang tidak menggunakan bahasa C atau C ++.

Dalam kernel atau dalam platform mode dasar yang tidak dilindungi, periferal seperti port serial atau disk drive dipetakan ke dalam peta memori dengan cara yang sama seperti RAM. Memori adalah serangkaian sakelar dan membalik sakelar periferal (seperti port serial atau driver disk) membuat periferal Anda melakukan hal-hal yang bermanfaat.

Dalam sistem operasi mode terproteksi, ketika seseorang ingin mengakses kernel dari userspace (katakanlah ketika menulis ke sistem file atau menggambar piksel pada layar) seseorang perlu membuat panggilan sistem. C tidak memiliki instruksi untuk melakukan panggilan sistem tetapi C dapat memanggil kode assembler yang dapat memicu panggilan sistem yang benar, Inilah yang memungkinkan kode C seseorang berbicara dengan kernel.

Untuk membuat pemrograman platform tertentu lebih mudah, panggilan sistem dibungkus dengan fungsi yang lebih kompleks yang dapat melakukan beberapa fungsi yang berguna dalam program sendiri. Seseorang bebas untuk memanggil sistem panggilan secara langsung (menggunakan assembler) tetapi mungkin lebih mudah untuk hanya menggunakan salah satu fungsi pembungkus yang disediakan oleh platform.

Ada tingkat API lain yang jauh lebih berguna daripada panggilan sistem. Ambil contoh malloc. Ini tidak hanya akan memanggil sistem untuk mendapatkan blok memori besar tetapi juga akan mengelola memori ini dengan melakukan semua pembukuan pada apa yang terjadi.

Win32 API membungkus beberapa fungsionalitas grafik dengan satu set widget platform umum. Qt mengambil ini sedikit lebih jauh dengan membungkus Win32 (atau X Windows) API dengan cara lintas platform.

Meskipun pada dasarnya kompiler C mengubah kode C menjadi kode mesin dan karena komputer dirancang untuk menggunakan kode mesin, Anda harus mengharapkan C untuk dapat menyelesaikan bagian singa atau apa yang dapat dilakukan komputer. Semua yang dilakukan perpustakaan pembungkus adalah melakukan angkat berat untuk Anda sehingga Anda tidak perlu melakukannya.

doron
sumber
Peringatan tentang # 2: C dan C ++ hanya bisa memanggil fungsi yang sesuai dengan "konvensi panggilan" yang dipahami dan diharapkan oleh kompiler. (Kode assembly dapat menggunakan konvensi apa pun yang disukainya, atau bahkan tidak sama sekali - sehingga kode tersebut mungkin tidak dapat dipanggil secara langsung.) Untungnya, setiap kompiler yang menghargai diri sendiri menyediakan cara bawaan untuk menggunakan konvensi umum platform. (Kompiler Windows C, misalnya, memungkinkan Anda memiliki / menggunakan fungsi yang menggunakan konvensi "cdecl", "stdcall", atau "fastcall"). Tetapi kode assembly harus menggunakan konvensi yang diketahui oleh kompiler, atau C dan C ++ dapat ' t menyebutnya secara langsung.
cHao
2
Juga: I / O yang dipetakan dengan memori adalah umum, tetapi tidak keseluruhan cerita. PC, misalnya, biasanya menangani port serial, drive disk, dll menggunakan "I / O port" x86, mekanisme yang sama sekali berbeda. (Penyangga video biasanya dipetakan di memori, tetapi mode video dll biasanya dikontrol melalui port I / O.)
cHao
@ cHao: Tentu saja pendekatan klasik menggunakan INP dan OUTP semakin disingkirkan demi DMA; generasi PCI tampaknya melakukan lebih banyak dengan register fungsi khusus yang dipetakan di memori, sekarang ada cara untuk memetakan perangkat secara otomatis ke daerah yang tidak tumpang tindih dan menemukannya dari driver, dan lebih sedikit dengan port I / O.
Ben Voigt
periferal modern akan menggunakan DMA untuk transfer data massal tetapi Anda masih akan memprogram pengontrol DMA dengan memori yang dapat dialamatkan
doron
@doron: Umm, Anda memprogram pengontrol DMA melalui ruang alamat I / O (bukan ruang memori) pada PC, setidaknya jika Anda waras. CPU x86 modern suka mengatur ulang akses memori untuk meningkatkan kinerja. Dengan MMIO, itu bisa menjadi bencana ... jadi Anda harus berhati-hati untuk membuat alamat-alamat itu tidakacheache dan menaruh instruksi cerita bersambung di semua tempat yang tepat. OTOH, x86 itu sendiri memastikan bahwa membaca dan menulis ke ruang I / O dilakukan dalam urutan program. Itulah sebabnya banyak hal penting masih dilakukan melalui ruang I / O (yang umumnya tidak dapat diakses melalui pointer), dan mungkin akan selalu demikian.
cHao
23

Bahasa (seperti C ++ 11 ) adalah spesifikasi , di atas kertas, biasanya ditulis dalam bahasa Inggris. Lihat di dalam draft C ++ 11 terbaru (atau beli spec final mahal dari vendor ISO Anda).

Anda biasanya menggunakan komputer dengan beberapa implementasi bahasa (pada prinsipnya Anda dapat menjalankan program C ++ tanpa komputer apa pun, misalnya menggunakan sekelompok budak manusia yang menerjemahkannya; itu tidak etis dan tidak efisien)

Umum implementasi C ++ Anda berfungsi di atas beberapa sistem operasi dan berkomunikasi dengannya (menggunakan beberapa kode implementasi spesifik , sering di beberapa pustaka sistem). Umumnya komunikasi itu dilakukan melalui panggilan sistem . Cari misalnya ke syscalls (2) untuk daftar panggilan sistem yang tersedia di kernel Linux .

Dari sudut pandang aplikasi, syscall adalah instruksi mesin dasar seperti SYSENTERpada x86-64 dengan beberapa konvensi ( ABI )

Di desktop Linux saya, pustaka Qt berada di atas pustaka klien X11 yang berkomunikasi dengan server X11 Xorg melalui protokol X Windows .

Di Linux, gunakan lddpada executable Anda untuk melihat daftar dependensi (panjang) pada perpustakaan. Gunakan pmappada proses Anda berjalan untuk melihat mana yang "dimuat" saat runtime. BTW, di Linux, aplikasi Anda mungkin hanya menggunakan perangkat lunak gratis, Anda dapat mempelajari kode sumbernya (dari Qt, ke Xlib, libc, ... kernel) untuk lebih memahami apa yang terjadi

Basile Starynkevitch
sumber
2
Sebagai referensi, ANSI menjual spesifikasi C ++ 11 dengan harga yang sedikit lebih murah yaitu US $ 60. (Dulu setengahnya, tetapi inflasi.: P) Ini dilabeli sebagai INCIT / ISO / IEC 14882, tapi setidaknya spesifikasi dasar yang sama yang ditawarkan ISO. Tidak yakin tentang errata / TRs.
cHao
19

Saya pikir konsep yang Anda lewatkan adalah panggilan sistem . Setiap sistem operasi menyediakan sejumlah besar sumber daya dan fungsionalitas yang dapat Anda manfaatkan untuk melakukan hal-hal terkait sistem operasi tingkat rendah. Bahkan ketika Anda memanggil fungsi perpustakaan biasa, itu mungkin membuat panggilan sistem di belakang layar.

Panggilan sistem adalah cara tingkat rendah memanfaatkan kekuatan sistem operasi, tetapi bisa rumit dan rumit untuk digunakan, jadi sering "dibungkus" dalam API sehingga Anda tidak harus menghadapinya secara langsung. Namun di baliknya, hampir semua hal yang Anda lakukan yang melibatkan sumber daya terkait O / S akan menggunakan panggilan sistem, termasuk pencetakan, jaringan dan soket, dll.

Dalam kasus windows, Microsoft Windows memiliki GUI yang sebenarnya ditulis ke dalam kernel, sehingga ada panggilan sistem untuk membuat windows, melukis gambar, dll. Dalam sistem operasi lain, GUI mungkin bukan bagian dari kernel, dalam hal ini Sejauh yang saya tahu tidak akan ada panggilan sistem untuk hal-hal yang berhubungan dengan GUI, dan Anda hanya bisa bekerja pada level yang lebih rendah dengan grafis level rendah apa pun dan panggilan terkait input yang tersedia.

Dave Cousineau
sumber
3
Hal penting yang hilang adalah bahwa panggilan sistem itu sama sekali tidak ajaib. Mereka dilayani oleh kernel yang biasanya ditulis dalam C (++). Selain itu, syscalls bahkan tidak diperlukan. Dalam OS yang belum sempurna tanpa perlindungan memori, windows dapat ditarik dengan meletakkan piksel langsung ke dalam framebuffer perangkat keras.
el.pescado
15

Pertanyaan bagus. Setiap pengembang C atau C ++ baru memikirkan hal ini. Saya mengasumsikan mesin x86 standar untuk sisa posting ini. Jika Anda menggunakan kompiler Microsoft C ++, buka notepad Anda dan ketik ini (beri nama file Test.c)

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

Dan sekarang kompilasi file ini (menggunakan prompt perintah pengembang) cl Test.c / FaTest.asm

Sekarang buka Test.asm di notepad Anda. Apa yang Anda lihat adalah kode yang diterjemahkan - C / C ++ diterjemahkan ke assembler. Apakah Anda mendapatkan petunjuknya?

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

Program C / C ++ dirancang untuk berjalan pada logam. Yang berarti mereka memiliki akses ke perangkat keras tingkat rendah yang membuatnya lebih mudah untuk mengeksploitasi kemampuan perangkat keras. Katakanlah, saya akan menulis getar C library () pada mesin x86.

Bergantung pada assembler, saya akan mengetik sesuatu dengan cara ini:

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

Saya menjalankannya dengan assembler dan menghasilkan .OBJ - Sebut saja getch.obj.

Saya kemudian menulis program C (saya tidak memasukkan apa pun)

extern char getch();

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

Sekarang beri nama file ini - GetChTest.c. Kompilasi file ini dengan meneruskan getch.obj. (Atau kompilasi satu per satu untuk .obj dan LINK GetChTest.Obj dan getch.Obj bersama-sama untuk menghasilkan GetChTest.exe).

Jalankan GetChTest.exe dan Anda akan menunggu input keyboard.

Pemrograman C / C ++ bukan hanya tentang bahasa. Untuk menjadi programmer C / C ++ yang baik, Anda harus memiliki pemahaman yang baik tentang jenis mesin yang dijalankannya. Anda akan perlu tahu bagaimana manajemen memori ditangani, bagaimana register disusun, dll., Anda mungkin tidak memerlukan semua informasi ini untuk pemrograman reguler - tetapi mereka akan sangat membantu Anda. Terlepas dari pengetahuan perangkat keras dasar, tentu membantu jika Anda memahami cara kerja kompiler (mis., Bagaimana menerjemahkannya) - yang dapat memungkinkan Anda untuk mengubah kode Anda seperlunya. Ini adalah paket yang menarik!

Kedua bahasa mendukung kata kunci __as yang artinya Anda juga dapat mencampur kode bahasa majelis Anda. Belajar C dan C ++ akan membuat Anda menjadi programmer yang lebih baik secara keseluruhan.

Tidak perlu selalu terhubung dengan Assembler. Saya telah menyebutkannya karena saya pikir itu akan membantu Anda memahami lebih baik. Sebagian besar, sebagian besar panggilan perpustakaan seperti itu menggunakan panggilan sistem / API yang disediakan oleh Sistem Operasi (OS pada gilirannya melakukan hal-hal interaksi perangkat keras).

Krishna Santosh Sampath
sumber
10

Bagaimana C ++ ... tiba-tiba mendapatkan kemampuan seperti itu melalui perpustakaan yang ditulis dalam C ++ sendiri?

Tidak ada yang ajaib dengan menggunakan perpustakaan lain. Perpustakaan adalah kumpulan fungsi sederhana yang dapat Anda hubungi.

Anggap diri Anda menulis fungsi seperti ini

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

Sekarang jika Anda memasukkan file itu, Anda dapat menulis addExclamation(myVeryOwnString); . Sekarang Anda mungkin bertanya, "bagaimana C ++ tiba-tiba mendapatkan kemampuan untuk menambahkan tanda seru ke string?" Jawabannya mudah: Anda menulis fungsi untuk melakukan itu lalu Anda menyebutnya.

Jadi untuk menjawab pertanyaan Anda tentang bagaimana C ++ bisa mendapatkan kemampuan untuk menggambar windows melalui pustaka yang ditulis dalam C ++, jawabannya adalah sama. Orang lain menulis fungsi untuk melakukan itu, dan kemudian menyusunnya dan memberikannya kepada Anda dalam bentuk perpustakaan.

Pertanyaan-pertanyaan lain menjawab bagaimana gambar jendela benar-benar bekerja, tetapi Anda terdengar bingung tentang bagaimana perpustakaan bekerja jadi saya ingin membahas bagian paling mendasar dari pertanyaan Anda.

Philip
sumber
8

Kuncinya adalah kemungkinan sistem operasi untuk mengekspos API dan deskripsi terperinci tentang bagaimana API ini digunakan.

Sistem operasi menawarkan satu set API dengan konvensi pemanggilan. Konvensi panggilan mendefinisikan cara parameter diberikan ke API dan bagaimana hasilnya dikembalikan dan bagaimana menjalankan panggilan yang sebenarnya.

Sistem operasi dan kompiler yang membuat kode untuk mereka bermain bersama dengan baik, jadi Anda biasanya tidak harus memikirkannya, cukup gunakan.

thst
sumber
7

Tidak perlu sintaks khusus untuk membuat windows. Yang diperlukan hanyalah bahwa OS menyediakan API untuk membuat windows. API semacam itu terdiri dari panggilan fungsi sederhana yang disediakan oleh C ++ untuk sintaksis.

Lebih jauh, C dan C ++ disebut bahasa pemrograman sistem dan dapat mengakses pointer arbitrer (yang mungkin dipetakan ke beberapa perangkat oleh perangkat keras). Selain itu, ini juga cukup sederhana untuk memanggil fungsi-fungsi yang ditentukan dalam perakitan, yang memungkinkan berbagai operasi yang disediakan prosesor. Karena itu dimungkinkan untuk menulis OS itu sendiri menggunakan C atau C ++ dan sejumlah kecil perakitan.

Hal ini juga harus disebutkan bahwa Qt adalah contoh buruk, karena menggunakan apa yang disebut meta compiler untuk memperpanjang C ++' sintaks. Namun ini tidak terkait dengan kemampuannya untuk memanggil ke dalam API yang disediakan oleh OS untuk benar-benar menggambar atau membuat windows.

Joe
sumber
7

Pertama, ada sedikit kesalahpahaman, saya pikir

Bagaimana C ++, yang sebelumnya tidak memiliki sintaks yang mampu meminta OS untuk jendela atau cara untuk berkomunikasi melalui jaringan

Tidak ada sintaks untuk melakukan operasi OS. Ini pertanyaan tentang semantik .

tiba-tiba mendapatkan kemampuan seperti itu melalui perpustakaan yang ditulis dalam C ++ sendiri

Nah, sistem operasinya sebagian besar ditulis dalam C. Anda dapat menggunakan shared library (jadi, dll) untuk memanggil kode eksternal. Selain itu, kode sistem operasi dapat mendaftarkan rutin sistem pada syscalls * atau interupsi yang dapat Anda panggil menggunakan rakitan . Pustaka bersama yang sering membuat sistem memanggil Anda, jadi Anda terhindar menggunakan perakitan inline.

Inilah tutorial yang bagus tentang itu: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
Ini untuk Linux, tetapi prinsip-prinsipnya sama.

Bagaimana sistem operasi melakukan operasi pada kartu grafis, kartu jaringan dll? Ini adalah tema yang sangat luas, tetapi sebagian besar Anda perlu mengakses interupsi, port atau menulis beberapa data ke wilayah memori khusus. Karena operasi itu dilindungi, Anda harus memanggil mereka melalui sistem operasi.

Pelaut Danubia
sumber
7

Dalam upaya memberikan pandangan yang sedikit berbeda dengan jawaban lain, saya akan menjawab seperti ini.

(Penafian: Saya menyederhanakan sedikit hal, situasi yang saya berikan adalah murni hipotetis dan ditulis sebagai sarana untuk menunjukkan konsep daripada 100% benar untuk kehidupan).

Pikirkan hal-hal dari sudut pandang lain, bayangkan Anda baru saja menulis sebuah sistem operasi sederhana dengan kemampuan dasar threading, windowing dan manajemen memori. Anda ingin menerapkan pustaka C ++ untuk membiarkan pengguna memprogram dalam C ++ dan melakukan hal-hal seperti membuat windows, menggambar ke windows dll. Pertanyaannya adalah, bagaimana melakukan ini.

Pertama, karena C ++ mengkompilasi ke kode mesin, Anda perlu menentukan cara untuk menggunakan kode mesin untuk berinteraksi dengan C ++. Di sinilah fungsi masuk, fungsi menerima argumen dan memberikan nilai balik, sehingga memberikan cara standar untuk mentransfer data antara berbagai bagian kode. Mereka melakukan ini dengan menetapkan sesuatu yang dikenal sebagai konvensi pemanggilan .

Sebuah konvensi menelepon negara di mana dan bagaimana argumen harus ditempatkan di memori sehingga fungsi dapat menemukan mereka ketika dijalankan. Ketika suatu fungsi dipanggil, fungsi panggilan menempatkan argumen dalam memori dan kemudian meminta CPU untuk beralih ke fungsi lainnya, di mana ia melakukan apa yang dilakukannya sebelum melompat kembali ke tempat ia dipanggil. Ini berarti bahwa kode yang dipanggil dapat berupa apa saja dan itu tidak akan mengubah cara fungsi dipanggil. Namun dalam hal ini, kode di belakang fungsi akan relevan dengan sistem operasi dan akan beroperasi pada kondisi internal sistem operasi.

Jadi, berbulan-bulan kemudian dan Anda memiliki semua fungsi OS Anda beres. Pengguna Anda dapat memanggil fungsi untuk membuat windows dan menggambar di atasnya, mereka dapat membuat utas dan segala macam hal indah. Inilah masalahnya, fungsi OS Anda akan berbeda dengan fungsi Linux atau fungsi Windows. Jadi, Anda memutuskan untuk memberikan antarmuka standar kepada pengguna agar mereka dapat menulis kode portabel. Di sinilah QT masuk.

Seperti yang hampir pasti Anda ketahui, QT memiliki banyak kelas dan fungsi yang berguna untuk melakukan hal-hal yang dilakukan sistem operasi, tetapi dengan cara yang tampak independen dari sistem operasi yang mendasarinya. Cara kerjanya adalah bahwa QT menyediakan kelas dan fungsi yang seragam dalam penampilannya bagi pengguna, tetapi kode di belakang fungsi berbeda untuk setiap sistem operasi. Sebagai contoh, QApplication QT :: closeAllWindows () akan memanggil fungsi penutupan jendela khusus setiap sistem operasi tergantung pada versi yang digunakan. Di Windows kemungkinan besar akan memanggil CloseWindow (hwnd) sedangkan pada os menggunakan Sistem X Window, itu berpotensi akan memanggil XDestroyWindow (tampilan, jendela).

Seperti terbukti, sistem operasi memiliki banyak lapisan, yang semuanya harus berinteraksi melalui antarmuka banyak varietas. Ada banyak aspek yang belum saya sentuh, tetapi untuk menjelaskan semuanya, akan memakan waktu yang sangat lama. Jika Anda lebih tertarik dengan cara kerja sistem operasi dalam, saya sarankan memeriksa wiki dev OS .

Ingatlah bahwa alasan banyak sistem operasi memilih untuk mengekspos antarmuka ke C / C ++ adalah karena mereka mengkompilasi ke kode mesin, mereka mengizinkan instruksi perakitan untuk dicampur dengan kode mereka sendiri dan mereka memberikan tingkat kebebasan yang besar kepada programmer.

Sekali lagi, ada banyak hal yang terjadi di sini. Saya ingin terus menjelaskan bagaimana perpustakaan seperti file .so dan .dll tidak harus ditulis dalam C / C ++ dan dapat ditulis dalam bahasa assembly atau bahasa lain, tetapi saya merasa bahwa jika saya menambahkan lagi saya mungkin juga akan tulis seluruh artikel, dan sebanyak yang saya ingin lakukan, saya tidak punya situs untuk menyimpannya.

Pharap
sumber
6

Ketika Anda mencoba menggambar sesuatu di layar, kode Anda memanggil beberapa kode lain yang memanggil beberapa kode lain (dll.) Sampai akhirnya ada "system call", yang merupakan instruksi khusus yang dapat dijalankan CPU. Instruksi-instruksi ini dapat ditulis dalam rakitan atau dapat ditulis dalam C ++ jika kompiler mendukung "intrinsik" mereka (yang merupakan fungsi yang ditangani kompiler "secara khusus" dengan mengubahnya menjadi kode khusus yang dapat dimengerti CPU). Tugas mereka adalah memberi tahu sistem operasi untuk melakukan sesuatu.

Ketika panggilan sistem terjadi, suatu fungsi dipanggil yang memanggil fungsi lain (dll.) Sampai akhirnya driver layar disuruh menggambar sesuatu di layar. Pada saat itu, driver tampilan melihat wilayah tertentu dalam memori fisik yang sebenarnya bukan memori, melainkan rentang alamat yang dapat ditulis seolah-olah itu adalah memori. Namun, sebaliknya, menulis ke kisaran alamat itu menyebabkan perangkat keras grafis menyadap penulisan memori, dan menggambar sesuatu di layar.
Menulis ke wilayah memori ini adalah sesuatu yang bisa. dikodekan dalam C ++, karena di sisi perangkat lunak itu hanya akses memori biasa. Hanya saja perangkat keras menanganinya secara berbeda. Itulah
penjelasan mendasar tentang cara kerjanya.

pengguna541686
sumber
4
Afaik panggilan sistem sebenarnya bukan instruksi cpu, dan tidak ada hubungannya dengan intrinsik. Ini lebih merupakan fungsi dari kernel sistem operasi, yang berkomunikasi dengan perangkat.
MatthiasB
3
@ MatthiasB: Ya, Anda salah, karena syscall(dan sepupunya sysenter) memang merupakan instruksi CPU.
user541686
2
Ini hanyalah petunjuk untuk meningkatkan jawaban Anda, karena tidak jelas bagi saya sendiri. Jangan melihatnya sebagai serangan pribadi atau apa pun.
MatthiasB
1
@MatthiasB: Saya tidak tersinggung. Saya katakan saya sudah tahu jawabannya tidak 100% akurat tapi saya pikir itu penyederhanaan yang cukup baik untuk menjawab OP - jadi, jika Anda benar-benar tahu cara menulis jawaban yang lebih baik maka silakan tulis sendiri jawab atau luangkan waktu untuk mengedit milikku. Saya benar-benar tidak punya apa-apa untuk ditambahkan yang menurut saya layak, jadi jika Anda ingin melihat sesuatu yang lebih baik di halaman ini, Anda harus berusaha sendiri.
user541686
3
Panggilan sistem dilakukan menggunakan interupsi perangkat lunak. Instruksi seperti sysenteradalah jalur panggilan yang dioptimalkan, karena pengalihan konteks yang digunakan oleh penangan interupsi tidak secepat yang diinginkan semua orang, tetapi pada dasarnya itu masih berupa peranti lunak yang dihasilkan interupsi sementara ditangani dengan cara vektor ke penangan yang dipasang oleh kernel OS. Bagian dari proses switching konteks yang dilakukan IS sysenteradalah mengubah bit mode dalam prosesor untuk mengatur dering 0 - akses penuh ke semua instruksi, register, dan memori dan area I / O yang istimewa.
Ben Voigt
4

Program C ++ Anda menggunakan pustaka Qt (juga diberi kode dalam C ++). Pustaka Qt akan menggunakan fungsi Windows CreateWindowEx (yang dikodekan dalam C di dalam kernel32.dll). Atau di Linux mungkin menggunakan Xlib (juga dikodekan dalam C), tetapi bisa juga mengirim byte mentah yang dalam protokol X berarti " Tolong buat jendela untuk saya ".

Terkait dengan tangkapan Anda -22 pertanyaan adalah catatan historis bahwa "kompiler C ++ pertama ditulis dalam C ++", meskipun sebenarnya itu adalah kompiler C dengan beberapa gagasan C ++, cukup sehingga dapat mengkompilasi versi pertama, yang kemudian dapat mengkompilasi sendiri .

Demikian pula, kompiler GCC menggunakan ekstensi GCC: ia pertama kali dikompilasi ke versi kemudian digunakan untuk mengkompilasi ulang dirinya. (Instruksi pembuatan GCC)

Malaikat
sumber
2

Bagaimana saya melihat pertanyaan ini sebenarnya adalah pertanyaan kompiler.

Lihatlah dengan cara ini, Anda menulis sepotong kode dalam Assembly (Anda dapat melakukannya dalam bahasa apa pun) yang menerjemahkan bahasa yang baru Anda tulis, Anda ingin memanggil Z ++ menjadi Assembly, untuk kesederhanaan, sebut saja itu kompilator (kompiler) .

Sekarang Anda memberikan kompiler ini beberapa fungsi dasar, sehingga Anda dapat menulis int, string, array dll sebenarnya Anda memberikannya kemampuan yang cukup sehingga Anda dapat menulis kompiler itu sendiri di Z ++. dan sekarang Anda memiliki kompiler untuk Z ++ yang ditulis dalam Z ++, cukup rapi.

Yang lebih keren lagi adalah sekarang Anda dapat menambahkan kemampuan ke kompiler itu menggunakan kemampuan yang sudah dimilikinya, sehingga memperluas bahasa Z ++ dengan fitur-fitur baru dengan menggunakan fitur-fitur sebelumnya.

Contoh, jika Anda menulis kode yang cukup untuk menggambar piksel dalam warna apa pun, maka Anda dapat mengembangkannya menggunakan Z ++ untuk menggambar apa pun yang Anda inginkan.

Thomas Andreè Wang
sumber
0

Perangkat keraslah yang memungkinkan ini terjadi. Anda dapat menganggap memori grafis sebagai susunan besar (terdiri dari setiap piksel pada layar). Untuk menggambar di layar Anda dapat menulis ke memori ini menggunakan C ++ atau bahasa apa pun yang memungkinkan akses langsung ke memori itu. Memori itu kebetulan dapat diakses oleh atau terletak di kartu grafis.

Pada sistem modern yang mengakses memori grafis secara langsung akan memerlukan penulisan driver karena berbagai pembatasan sehingga Anda menggunakan cara tidak langsung. Perpustakaan yang membuat jendela (benar-benar hanya gambar seperti gambar lainnya) dan kemudian menulis gambar itu ke memori grafis yang kemudian ditampilkan oleh GPU di layar. Tidak ada yang harus ditambahkan ke bahasa kecuali kemampuan untuk menulis ke lokasi memori tertentu, yang adalah untuk apa pointer.

john
sumber
Poin yang saya coba sampaikan adalah bahwa suatu bahasa tidak perlu "berkembang" dengan sendirinya dalam arti bahwa versi bahasa yang baru perlu ditulis ulang, dan itu tidak benar-benar melingkar karena untuk melakukan sesuatu yang menarik suatu program harus berinteraksi dengan perangkat keras.
john