Mengapa sistem operasi melakukan hal-hal tingkat rendah dalam C dan C ++? Kenapa tidak C ++ saja?

20

Pada halaman Wikipedia untuk Windows , dinyatakan bahwa Windows ditulis dalam Assembly untuk bootloader dan pengalih tugas, dan C dan C ++ untuk rutinitas kernel.

IIRC, Anda dapat memanggil fungsi C ++ dari extern "C"blok d. Saya bisa menggunakan C untuk fungsi kernel sehingga aplikasi C murni dapat menggunakannya (suka printfdan semacamnya), tetapi jika mereka hanya bisa dibungkus dengan extern "C "blok, lalu mengapa kode dalam C?

Cole Johnson
sumber
10
Pernahkah Anda melihat berbagai "Mengapa menggunakan C ketika ada C ++?" pertanyaan di sini? Ini tidak selalu duplikat dari salah satu dari mereka, tetapi mereka yang terkait.
1
"Anda dapat memanggil fungsi C ++ dari blok" C "eksternal sebagai C ++" Maksud Anda, Anda dapat memanggil fungsi C ...?
Code-Guru
@ Code-Guru no, karena satu-satunya perbedaan antara fungsi C dan C ++ yang diekspor adalah dekorasi nama dan dalam C ++, penambahan thisvariabel
Cole Johnson
2
Lempar pengecualian di ISR ​​dan lihat apa yang terjadi
James
Namun pertanyaan C vs C ++ lainnya.
Machado

Jawaban:

31

Sebagian besar karena alasan historis. Beberapa bagian dari kernel windows awalnya ditulis dalam C, karena 1983, lebih dari tiga dekade lalu, ketika Windows 1.0 dilepaskan , C ++ hampir tidak dirilis. Sekarang perpustakaan-C ini akan tetap di sana "selamanya", karena Microsoft membuat kompatibilitas mundur sebagai titik penjualan dan menulis ulang versi yang kompatibel dengan bug dari C-parts di C ++ memerlukan banyak sekali usaha tanpa manfaat yang efektif.

back2dos
sumber
+1, saya kira itu adalah jawaban yang paling realistis (selain fakta bahwa mungkin ada beberapa devs kernel Windows yang tidak suka C ++ atau tidak percaya pada kompiler C ++ untuk hal-hal tingkat rendah). Lihat, misalnya, di sini stackoverflow.com/questions/520068/... , mengapa kernel Linux ditulis dalam C.
Doc Brown
@ back2dos - Walaupun kode C mereka tidak akan dibuang, itu tidak berarti akan digunakan atau tidak diperbarui. Saya jamin ada setidaknya satu metode yang melakukan sesuatu yang semula ditulis dan terkandung dalam pustaka C yang telah porting pustaka C ++ di Windows 8
Ramhound
8
Saya kesulitan meyakini bahwa ada kode Windows 1.0 dalam rilis Windows terbaru. Windows ME adalah rilis Windows terakhir yang tidak didasarkan pada basis kode Windows NT. Dan bahkan yang sebagian besar telah digantikan oleh kernel RT yang baru (yang, seperti yang saya mengerti, tidak banyak menjanjikan cara kompatibilitas mundur).
TMN
@TMN: argumen yang paling mungkin benar baik - saya cukup yakin di jalan dari Win 1.0 sekarang ada yang banyak perpustakaan yang ditulis dalam C yang masih bagian dari basis kode Win8 saat ini, dan tidak ada satu di MS melihat setiap manfaat untuk menulis ulang dalam C ++.
Doc Brown
1
Nyaris tidak ada kode yang berbicara dengan kernel Windows. Pada dasarnya, hanya driver yang melakukannya. Aplikasi biasanya berbicara dengan Win32 API, atau mungkin POSIX API.
MSalters
24

Seperti yang telah ditunjukkan oleh kebanyakan orang, alasannya sejauh ini historis, tetapi ada hal lain yang tidak disebutkan dan saya percaya itu adalah alasan orang masih menulis kode C untuk level rendah.

C adalah bahasa kecil dalam arti bahwa speknya (relatif) pendek. C ++ sangat besar dan itu meremehkan. Ini mungkin tidak terlalu menjadi masalah bagi programmer (walaupun saya pikir memang demikian), tetapi ini sangat penting jika Anda ingin melakukan verifikasi formal . Selain itu, ada alat yang sudah mapan untuk analisis kode C, yang dapat membantu mencegah bug, dll.

Dan ini sangat penting dalam perangkat lunak tertanam, di mana biaya bug yang digunakan sangat tinggi, relatif terhadap industri lainnya (bandingkan Web, di mana Anda dapat menerapkan tambalan segera ke semua pengguna). Belum lagi perangkat lunak yang sangat penting dan hal-hal medis.

Ada upaya untuk menggeser C dari posisi dominannya dalam pemrograman tingkat rendah dengan bahasa yang bahkan lebih baik, seperti BitC, tetapi sejauh ini mereka belum berhasil.

K.Steff
sumber
4
+1 Untuk menyebutkan perangkat lunak mission mission dalam C murni (mis. Perangkat lunak aeronautika). Namun, dalam perangkat lunak medis C ++ juga digunakan (pengujian ekstensif digunakan sebagai pengganti verifikasi formal, yang akan sangat sulit di C ++).
Giorgio
1
Juga, C memiliki himpunan bagian yang cukup sukses, MISRA-C. Ada persamaan untuk C ++, tetapi mereka bukan standar industri de facto (belum). Kecenderungan pemrograman keselamatan-kritis adalah bahwa perpustakaan dan kompiler juga akan dipaksa untuk menggunakan subset yang aman seperti MISRA. Untuk menulis ulang versi yang kompatibel dengan MISRA-C ++ dari seluruh pustaka standar C ++ kemungkinan besar akan menjadi mimpi buruk.
2
@Lundin MISRA pedoman bukan subset yang aman - Anda masih memiliki pointer mentah dan sebagian besar fitur lain yang membuat C tidak aman - mereka terutama berfokus pada tidak menggunakan atau mendokumentasikan perilaku spesifik implementasi.
Pete Kirkham
@PeteKirkham MISRA-C akan menangkap semua bug pointer paling klasik dan menerapkan analisis statis. Standar keamanan industri (IEC 61508 et al) tampaknya menyetujui MISRA-C sebagai subset aman dari C. Tidak ada banyak alternatif lain yang berguna untuk perangkat lunak mission-critical, kecuali jika Anda memilih SPARK Ada, bahasa yang sedikit diketahui, dengan alat terbatas mendukung.
2
Ini seharusnya dipilih sebagai jawaban terbaik karena itu benar. Orang lain yang menyarankan C hanya digunakan karena alasan historis itu sendiri histeris.
Rob
15
  1. C runtime jauh lebih kecil.
  2. Terjemahan C ++ ke dalam konstruksi tingkat lebih rendah kurang transparan daripada dalam C. (Lihat referensi dan tabel, untuk dua contoh cepat)
  3. C biasanya memiliki ABI yang stabil. C ++ biasanya tidak. Ini berarti bahwa minimal, antarmuka sistem panggilan harus bergaya C. Selain itu, jika Anda menginginkan modul dinamis apa pun, memiliki ABI yang konsisten sangat membantu.
Wnoise
sumber
+1 untuk (2) dan (3). Saya tidak yakin dengan (1).
Thomas Eding
7
@ Thomas Eding: C ++ runtime terdiri dari C runtime, ditambah fitur C ++ seperti pengecualian, RTTI, dan pengalokasi memori lainnya. YMMV, apakah yang diperhitungkan jauh lebih besar. (Dan kemudian ada perpustakaan standar ...)
menghilang
Ah, saya lupa tentang pengecualian dan kolam baru / hapus. RTTI Saya tidak pernah menggunakan: D
Thomas Eding
11

Alasannya tidak teknis. Sedikit perakitan tidak bisa dihindari, tetapi mereka tidak dipaksa untuk menggunakan C sesekali, yang mereka inginkan . Perusahaan saya menggunakan kernel miliknya sendiri, yang ditulis hampir seluruhnya dalam C ++, tetapi kami tidak perlu mendukung antarmuka C ke kernel seperti kebanyakan orang lain, karena kernel tertanam kami secara monolitik dikompilasi dengan aplikasi C ++ kami. Saat Anda memiliki antarmuka C, seringkali lebih mudah untuk menulis kode antarmuka dalam C, meskipun mungkin untuk menggunakannya extern "C"untuk menulisnya dalam C ++.

Bahkan kami memiliki segelintir file C, sebagian besar karena kode pihak ketiga. Kode tingkat rendah pihak ketiga hampir selalu disediakan dalam C, karena jauh lebih mudah untuk memasukkan kode C ke dalam aplikasi C ++ daripada sebaliknya.

Karl Bielefeldt
sumber
6

Pengembang kernel seringkali adalah tipe orang, yang merasa lebih bahagia, ketika langsung terbukti dari sumbernya, apa yang sebenarnya dilakukan oleh kode.

C ++ memiliki lebih banyak fitur, yang menyembunyikan apa yang kode lakukan lebih dari sekadar kode C menyembunyikannya: overload, metode virtual, templat, referensi, lemparan ... C ++ juga memiliki lebih banyak sintaks yang harus Anda kuasai untuk bahkan memahami C ++ kode menggunakannya.

Saya pikir kekuatan C ++ adalah alat yang sangat kuat untuk membuat perpustakaan dan kerangka kerja, yang kemudian membuat pengembangan aplikasi menjadi mudah. Sangat sering pengembang aplikasi C ++ akan benar-benar hilang dalam jeroan template yang dipenuhi perpustakaan, bahkan ketika ia sangat kompeten dalam membuat aplikasi menggunakan perpustakaan itu. Dan menulis hak pustaka C ++ adalah tugas pemrograman yang sangat menantang, dan hanya dilakukan untuk memberikan kerangka kerja yang bagus untuk kepentingan pengembang aplikasi. Pustaka C ++ tidak secara internal sederhana, mereka (atau dapat ...) hanya kuat namun sederhana dari sudut pandang pemrogram aplikasi.

Tetapi kernel API tidak bisa menjadi C ++ API, itu harus API agnostik bahasa, jadi sebagian besar hal-hal baik di C ++ tidak akan langsung dapat digunakan di antarmuka itu. Selain itu, kernel tidak benar-benar dibagi menjadi bagian "perpustakaan" dan "aplikasi" yang dikembangkan secara independen, dengan lebih banyak upaya secara logis pergi ke satu perpustakaan, untuk membuat pembuatan aplikasi yang mudah.

Selain itu, keamanan dan stabilitas lebih penting di dalam kernel, dan metode virtual jauh lebih dinamis dan karenanya lebih sulit untuk mengisolasi dan memverifikasi, daripada panggilan balik biasa atau mekanisme C-seperti lainnya.

Singkatnya, walaupun Anda tentu saja dapat menulis program C apa pun termasuk kernel sebagai C ++, sebagian besar kekuatan C ++ tidak digunakan dengan baik di kernel. Dan banyak yang berpendapat, bahwa alat pemrograman seharusnya mencegah Anda melakukan hal-hal yang seharusnya tidak Anda lakukan. C ++ tidak mau.

Hyde
sumber
+1. Sebagai pengembang kernel, "aturan praktis" saya adalah bahwa jika Anda tidak dapat memperkirakan "garis cache yang disentuh" ​​dengan mudah maka bahasa yang Anda gunakan lebih berbahaya daripada baik.
Brendan
Klarifikasi: Untuk kernel, Anda harus mengasumsikan bahwa CPU menghabiskan sebagian besar waktunya dalam ruang pengguna dan kode kernel digunakan secara sporadis (misalnya ketika ruang pengguna memanggil API kernel atau terjadi interupsi); yang berarti Anda harus menganggap "cache dingin". Untuk CPU modern (di mana RAM lambat relatif terhadap kecepatan CPU) cache dan TLB yang mahal, jadi (dikombinasikan dengan harapan "cache dingin") metrik "cache menyentuh" ​​menjadi indikator yang sangat penting untuk kinerja dan / atau skalabilitas.
Brendan
5

Bjarne Stroustrup, dalam sebuah wawancara pada Juli 1999 :

Tidak satu pun dari bahasa ini yang secara radikal berbeda atau secara dramatis lebih baik daripada bahasa kontemporer lainnya. Namun, mereka cukup baik dan penerima manfaat dari faktor keberuntungan dan sosial

David
sumber
2
Selamat datang david Ketika mengutip atau mengutip, adalah ide yang baik untuk memberikan referensi (ditambahkan!)
Andrew
3

C adalah bahasa tingkat sangat rendah, dengan desainnya. Satu langkah lagi dari assembler; mengetahui chipset yang Anda targetkan, Anda bisa, dengan sedikit pengetahuan, secara manual "mengkompilasi" C ke dalam ASM. Bahasa "dekat-ke-logam" semacam ini adalah kunci untuk optimasi tingkat tinggi (untuk kinerja, efisiensi memori, dll). Namun, karena sedekat ini dengan logam, Anda tidak mendapatkan banyak gratis dengan bahasa ini; itu adalah bahasa prosedural, non-berorientasi objek, dan dengan demikian untuk bekerja dengan konstruksi seperti itu melibatkan banyak kode boilerplate untuk membuat dan menggunakan konstruksi multi-nilai dalam memori.

C ++ adalah "C one better", menambahkan sejumlah fitur kemudahan penggunaan seperti alokasi memori dinamis, built-in struktur marshalling, perpustakaan besar kode yang telah ditentukan, dll, dengan mengorbankan beberapa kerugian efisiensi (masih jauh lebih baik dari lingkungan runtime yang dikelola). Untuk coder rata-rata, keuntungannya jauh lebih besar daripada kerugian di area basis kode yang tidak perlu kontrol anal-retribusi alokasi memori dll.

Kombinasi keduanya sangat tradisional; Anda menggunakan C untuk menulis area basis kode yang paling kritis terhadap kinerja, dan efisien-memori, yang kemudian dapat Anda gunakan dengan cara yang lebih abstrak melalui pemanggilan metode dari kode C ++, yang dapat lebih terorganisir dan dirancang dengan lebih elegan daripada pemain yang berkinerja tinggi , kode C dioptimalkan uber-oogly.

KeithS
sumber
2
Mengenai efisiensi, saya akan mengulangi sendiri: (1) Orang-orang C ++ akan mengatakan itu omong kosong. (2) Saya katakan saya tidak melihat alasan mengapa ini harus terjadi, dan ingin contoh nyata. Bukan contoh bagaimana mudahnya menulis kode yang kurang efisien, tetapi contoh bagaimana menjadi seefisien C membutuhkan keburukan yang tidak semestinya.
3
Definisikan "jelek"; Saya kode dalam C # untuk mencari nafkah, dan setiap kali saya melihat contoh kode C ++ di StackOverflow saya merasa ngeri pada seberapa banyak cruft dianggap normal dalam penggunaan bahasa sehari-hari. Ketika saya mengkodekan dalam C ++ jalan kembali ketika, saya sering melihat kode C dan merasa ngeri; jenis struktur pengemasan tangan, perhitungan pointer eksekusi untuk lompatan manual, ASM tertanam ... huek. Beberapa orang meratapi hilangnya pengetahuan tingkat rendah di antara programmer Java / .NET; Saya menganggapnya sebagai anugerah besar bagi produktivitas.
KeithS
1
Anda tidak menjawab pertanyaan saya;) Dengan "jelek" Maksud saya "jelek menurut standar C ++ gurus '". Dengan kata lain, contoh di mana seseorang tidak dapat menggunakan "C ++ modern" dan seefisien C.
2
Itu mungkin benar (saya jujur ​​tidak tahu). Untuk pengembangan kernel (dan beberapa bidang lainnya), kita tidak berbicara tentang programmer rata-rata.
3
Orang lupa bahwa C -> C ++ adalah sebuah kontinum. Terlalu sering, argumen ini membandingkan C ++ yang baik dan modern dengan C. Anda dapat mengambil program C dan mengkompilasinya dengan kompiler C ++ dalam waktu yang relatif singkat dan akan berjalan dengan cepat. Jika fitur C ++ modern "terlalu lambat", jangan gunakan. Itu bahkan dapat mencakup hal-hal seperti iostream. "Terlalu lambat" tidak pernah menjadi alasan yang baik untuk menggunakan C lebih dari C ++.
Gort the Robot
1

Bisa jadi dengan C Anda menghabiskan sebagian besar waktu Anda untuk memikirkan masalah yang ada dan bagaimana membuat kode solusinya. Dalam C ++ Anda akhirnya berpikir tentang C ++ dan segudang fitur, fungsi, dan sintaksis yang tidak jelas.

Juga di banyak toko C ++ kode Anda dipantau oleh "polisi mode" yang terpesona oleh serangkaian pola desain terbaru, atau, pernyataan terbaru yang tidak dapat dipahami dari dewa besar Stroustrup. Kode cantik menjadi lebih dihargai daripada kode kerja, menemukan penggunaan untuk set templat Boost terbaru lebih dikagumi daripada menemukan solusi kerja untuk bisnis.

Pengalaman saya adalah bahwa untuk semua fitur pintar dan kemurnian OO dari C ++, pengkodean dalam plain C membuat pekerjaan dilakukan lebih cepat dan lebih efektif.

James Anderson
sumber
0

Mungkin saja bagian-bagian C tidak mudah dibawa-bawa ke kompiler C ++ yang digunakan untuk bagian-bagian C ++. Mungkin kode C akrab dengan kompiler C dengan cara yang tidak sesuai dengan kompiler C ++.

Jika Anda memiliki kompiler C ++ berkualitas, hampir tidak ada alasan untuk mencampur C dan C ++ dalam sebuah proyek. Hampir.

Salah satu alasannya adalah bahwa proyek Anda membagikan kode C dengan proyek lain, kode tersebut tidak dikompilasi sebagai C ++, dan Anda tidak ingin mempertahankan garpu C ++ dari kode itu.

Kaz
sumber
-1

Saya pikir Anda memilikinya mundur - extern "C"blok memastikan bahwa konvensi pemanggilan C digunakan untuk semua fungsi di dalam blok. Jadi Anda dapat memanggil fungsi C murni dari C ++, bukan fungsi C ++ dari C. Terlepas dari itu, saya membayangkan bahwa alasan orang menggunakan C dan C ++ adalah karena banyak perpustakaan tingkat rendah ditulis menggunakan C, dan lebih mudah untuk menggunakan sesuatu yang sudah ada (dan mungkin didebug dan dioptimalkan) daripada menulis sendiri. OTOH, C ++ menawarkan banyak fitur tingkat tinggi yang bagus yang lebih disukai orang, jadi mereka menggunakannya untuk yang lain.

TMN
sumber
-2

Ada berbagai level platform tertanam yang menggunakan C sebagai bahasa pemrograman (tentu saja Anda bebas menggunakan bahasa assembly kapan saja)

Untuk 'Level' saya berbicara tentang level sumber daya SRAM dan ROM Internal untuk suatu sistem.

Platform ini terkadang dibatasi sumber daya (mis. Beberapa platform 8.051 hanya memiliki 128 byte SRAM Pengguna).

Tidak ada artinya untuk mendukung alokasi memori dinamis dengan jumlah RAM yang begitu kecil. (baru / hapus) atau bahkan malloc di C.

Salah satu peningkatan utama dari C ke C ++ adalah paradigma berorientasi objek. C ++ cocok untuk perangkat lunak dengan jejak memori yang lebih besar

tetapi tidak dalam firmware tertanam yang memiliki batasan ukuran hingga 32KB. (mis. dalam plaform MCU 16-bit)

Tidak perlu memiliki kompiler C ++ yang umumnya lebih rumit daripada kompiler C. (setidaknya penyedia SDK tidak akan repot untuk melakukan ini).

Sebenarnya saya hampir tidak dapat menemukan kompiler C ++ melalui platform ARM7 32-bit.

Itu tidak sebanding dengan kompleksitasnya

Dalam Some 8051 (8 bit): 1MB ROM, 128B RAM

TI MSP430 (16 Bit): ROM 32KB, RAM 4KB

ST Mikroelektronika ARM 32-bit Cortex ™ -M3 CPU Core (STM32F103T4): 16 atau 32 Kbytes memori Flash 6 atau 10 Kbytes SRAM

ansonchau
sumber
2
Ini bukan sesuatu yang baru untuk jawaban lain yang sudah diposting di sini.
Martijn Pieters
Kompiler C ++ 32-bit untuk ARM? Jika Anda mau, Anda bisa mengkompilasi LLVM dari sumber sendiri setelah beberapa modifikasi untuk mendapatkan kompiler C ++ untuk iOS.
Cole Johnson
-4

Saya melihat beberapa kemungkinan alasan:

  • C sedikit lebih efisien jika dibandingkan dengan setara C ++.
  • Beberapa perpustakaan yang mereka gunakan ditulis dalam C.
  • Mereka menggunakan beberapa bagian dari kernel Linux, yang ditulis dalam C.

Diedit: Ternyata, argumen ketiga tidak benar (lihat komentar).

Pijusn
sumber
5
(1) Orang-orang C ++ akan berbeda. Dan secara objektif saya tidak melihat alasan mengapa ini harus terjadi. (2) C ++ dapat memanggil kode C dengan baik (itulah inti dari kompatibilitas mundur dan extern "C").
1
Jika MS menggunakan beberapa bagian dari kernel Linux, dan kernel Linux adalah GPL, bukankah itu berarti bahwa Windows juga harus menjadi GPL?
TomJ
1
@ TomJ sebenarnya itu sebabnya mereka dipaksa untuk menyumbangkan beberapa ribu baris ke Linux juga. + Mengapa menurut Anda mereka mendukung pengembangan Linux?
Pijusn
2
@Pius Maksudnya adalah (dan dia benar AFAIK), jika ada kode GPL yang terhubung ke kernel Windows, seluruh kernel harus GPL (asalkan tidak ada perjanjian terpisah dengan pemegang hak cipta).
@nannan, tidak yakin tentang detailnya. Saya bukan pengacara jadi saya tidak bisa mengomentari itu. Tetapi ada skandal kecil beberapa tahun yang lalu tentang ini. Tidak yakin tapi saya pikir saya mungkin modul jaringan semua hal gila tentang.
Pijusn
-4

Karena C bisa dibilang bahasa yang lebih baik daripada C ++. Dan karena beberapa kode ditulis sebelum C ++ menjadi populer dan orang tidak punya alasan untuk menggantinya.

Dan karena C ++ memiliki banyak fitur yang dapat merusak kode Anda jika Anda tidak hati-hati saat menggunakannya di kernel.

Minthos
sumber
C ++ mengharapkan perpustakaan dinamis? Dan apa itu memori dinamis?
4
-1 untuk [stuff] that C++ expects. Mengapa C ++ menggunakan lebih banyak tumpukan daripada C? Mengapa C ++ membutuhkan lebih banyak dll daripada C? Simply NOT TRUE
Thomas Eding
1
Koreksi: Anda kehilangan perpustakaan yang ditulis dalam C ++. Jadi kembalilah ke titik 1 jika Anda menggunakan C ++ atau C. Mengapa membatasi diri Anda pada fungsionalitas C jika Anda dapat menggunakan templat, kelas, destruktor, const, dan segala macam kebaikan lainnya.
Thomas Eding
6
Apa? Templat, pengecualian, objek (termasuk konstruktor, destruktor, operator kelebihan beban, kini memindahkan konstruksi, dan - praktis? - segalanya), dll. Berfungsi dengan baik terlepas dari mana memori berasal (tumpukan, memori statis, kumpulan khusus Anda, atau apa pun) . Kontainer standar menggunakan alokasi heap secara default, tetapi pengalokasi mereka dapat dikustomisasi dan kernel juga menulis koleksi dan manajemen memori mereka sendiri. -1
2
FYI: Saya menghapus downvote saya karena saya pikir jawaban Anda saat ini tidak berbahaya, tetapi saya juga tidak menganggapnya berguna atau berwawasan luas.