Windows adalah salah satu OS yang paling beragam dan fleksibel, ia bekerja pada arsitektur yang sangat berbeda dan tersedia dalam versi yang berbeda. Hari ini mendukung arsitektur x86, x64, ARM, dan ARM64. Windows
pada satu waktu mendukung Itanium, PowerPC, DEC Alpha, dan MIPS. Selain itu, Windows mendukung berbagai SKU yang beroperasi di berbagai kondisi; Dari pusat data, laptop, Xbox, dan telepon ke versi Internet yang tertanam, misalnya, di ATM.
Aspek yang paling menakjubkan adalah bahwa kernel Windows tetap tidak berubah tergantung pada semua arsitektur dan
SKU ini . Kernel secara dinamis berskala tergantung pada arsitektur dan prosesor di mana ia bekerja, sehingga dapat mengambil keuntungan penuh dari peralatan. Tentu saja, kernel memiliki sejumlah kode yang terkait dengan arsitektur tertentu, tetapi ada jumlah minimal di sana, yang memungkinkan Windows untuk berjalan pada berbagai arsitektur.
Dalam artikel ini, saya akan berbicara tentang evolusi bagian-bagian penting dari kernel Windows yang memungkinkannya untuk menskalakan secara transparan dari chip NVidia Tegra berdaya rendah yang berjalan di
Surface RT 2012 ke
monster raksasa yang bekerja di pusat data Azure.
Manajer tugas Windows yang berjalan pada mesin prerelease Windows DataCenter, dengan 896 core mendukung 1792 prosesor logis dan 2 TB memori
Evolusi inti tunggal
Sebelum membahas rincian kernel Windows, mari kita sedikit menyimpang ke arah
refactoring . Refactoring memainkan peran penting dalam meningkatkan penggunaan kembali komponen OS pada berbagai SKU dan platform (misalnya, klien, server, dan telepon). Ide dasar dari refactoring adalah untuk memungkinkan Anda menggunakan kembali DLL yang sama pada SKU yang berbeda, mendukung modifikasi kecil yang dibuat khusus untuk SKU yang diinginkan, tanpa mengubah nama DLL dan tanpa merusak pekerjaan aplikasi.
Teknologi inti dari Windows refactoring adalah teknologi kecil yang didokumentasikan yang disebut
set API . API suites adalah mekanisme yang memungkinkan OS untuk memisahkan DLL dan tempat penggunaannya. Sebagai contoh, set API memungkinkan aplikasi untuk win32 untuk terus menggunakan kernel32.dll, terlepas dari kenyataan bahwa implementasi semua API ditulis dalam DLL lain. DLL implementasi ini juga mungkin berbeda di antara SKU. Anda dapat melihat set API beraksi dengan menjalankan dependensi traversal pada Windows DLL tradisional, misalnya, kernel32.dll.
Setelah menyelesaikan penyimpangan ini tentang struktur Windows, yang memungkinkan sistem untuk memaksimalkan penggunaan kembali dan berbagi kode, mari kita beralih ke kedalaman teknis memulai kernel sesuai dengan penjadwal, yang merupakan kunci untuk penskalaan OS.
Komponen Kernel
Windows NT sebenarnya adalah
microkernel , dalam arti bahwa ia memiliki inti Kernel (KE) sendiri dengan serangkaian fungsi terbatas, menggunakan lapisan yang dapat dieksekusi (lapisan Eksekutif, Ex) untuk menjalankan semua kebijakan tingkat tinggi. EX masih merupakan mode kernel, jadi ini bukan microkernel. Kernel bertanggung jawab untuk menjadwalkan utas, menyinkronkan antara prosesor, menangani pengecualian tingkat perangkat keras, dan mengimplementasikan fungsi-fungsi yang bergantung pada perangkat keras tingkat rendah. Lapisan EX berisi berbagai subsistem yang menyediakan serangkaian fungsi yang biasanya dianggap sebagai inti - IO, Manajer Objek, Manajer Memori, Subsistem Proses, dll.
Untuk lebih memahami ukuran komponen, berikut adalah perkiraan jumlah baris kode di beberapa direktori utama pohon kode sumber kernel (termasuk komentar). Tabel belum memasukkan banyak hal yang berhubungan dengan kernel.
Subsistem kernel | Baris-baris kode |
---|
Manajer memori | 501.000 |
Daftar | 211.000 |
Kekuasaan | 238.000 |
Eksekutif | 157.000 |
Keamanan | 135.000 |
Kernel | 339.000 |
Sub-sistem proses | 116.000 |
Untuk informasi lebih lanjut tentang arsitektur Windows, lihat seri buku
Windows Internals .
Perencana
Setelah menyiapkan landasan dengan cara ini, mari kita bicara sedikit tentang penjadwal, evolusinya, dan bagaimana kernel Windows dapat menskala ke sejumlah arsitektur yang berbeda dengan begitu banyak prosesor.
Sebuah utas adalah unit dasar yang mengeksekusi kode program, dan justru pekerjaannya yang direncanakan oleh penjadwal Windows. Ketika memutuskan utas mana yang akan mulai, penjadwal menggunakan prioritas mereka, dan secara teori, utas dengan prioritas tertinggi harus dimulai pada sistem, bahkan jika ini berarti tidak akan ada waktu tersisa untuk utas dengan prioritas yang lebih rendah.
Setelah bekerja waktu kuantum (jumlah waktu minimum agar sebuah thread dapat bekerja), thread tersebut mengalami penurunan dalam prioritas dinamis sehingga thread prioritas tinggi tidak dapat bekerja selamanya, jiwa semua orang. Ketika utas lain mulai berfungsi, diberi prioritas, dihitung berdasarkan pentingnya acara yang menyebabkan penantian (misalnya, prioritas sangat ditingkatkan untuk antarmuka pengguna ujung depan, dan sedikit untuk menyelesaikan operasi I / O). Oleh karena itu, utas berfungsi dengan prioritas tinggi sementara tetap interaktif. Ketika terhubung secara dominan dengan perhitungan (terikat CPU), prioritasnya turun, dan mereka kembali ke sana setelah utas lain dengan prioritas tinggi memiliki waktu prosesor mereka. Selain itu, kernel secara sewenang-wenang meningkatkan prioritas utas yang sudah jadi yang belum menerima waktu prosesor untuk periode tertentu untuk mencegah kelaparan komputasi mereka dan memperbaiki inversi prioritas.
Penjadwal Windows awalnya memiliki satu antrian kesiapan, dari mana ia memilih utas berikutnya, prioritas tertinggi untuk dijalankan. Namun, dengan dukungan awal untuk peningkatan jumlah prosesor, antrian hanya berubah menjadi hambatan, dan scheduler mengubah pekerjaan di sekitar area rilis Windows Server 2003 dan mengatur satu antrian kesiapan per prosesor. Ketika beralih ke mendukung beberapa permintaan untuk satu prosesor, mereka tidak melakukan kunci global tunggal yang melindungi semua antrian, dan memungkinkan penjadwal untuk membuat keputusan berdasarkan pada optima lokal. Ini berarti bahwa setiap saat dalam sistem ada satu utas dengan prioritas tertinggi, tetapi itu tidak berarti bahwa N dari utas prioritas tertinggi dalam daftar (di mana N adalah jumlah prosesor) bekerja dalam sistem. Pendekatan ini terbayar sampai Windows mulai beralih ke CPU berdaya rendah seperti laptop dan tablet. Ketika utas dengan prioritas tertinggi tidak berfungsi pada sistem seperti itu (misalnya, utas antarmuka pengguna), ini menyebabkan gangguan antarmuka yang nyata. Oleh karena itu, di Windows 8.1, penjadwal dipindahkan ke model hybrid, dengan antrian untuk setiap prosesor untuk utas yang terkait dengan prosesor ini, dan antrian bersama dari proses siap pakai untuk semua prosesor. Ini tidak mempengaruhi kinerja secara nyata karena perubahan lain dalam arsitektur scheduler, misalnya, refactoring kunci database dispatcher.
Windows 7 memperkenalkan sesuatu seperti penjadwal berbagi adil dinamis (Penjadwal Berbagi Adil Dinamis, DFSS); ini terutama terminal server. Fitur ini mencoba menyelesaikan masalah bahwa satu sesi terminal dengan beban CPU yang tinggi dapat memengaruhi utas di sesi terminal lainnya. Karena penjadwal tidak mempertimbangkan sesi akun dan hanya menggunakan prioritas untuk mendistribusikan arus, pengguna dalam berbagai sesi dapat memengaruhi pekerjaan pengguna di sesi lain dengan mencekik arus mereka. Ini juga memberikan keuntungan yang tidak adil untuk sesi (dan pengguna) dengan sejumlah besar utas, karena sesi dengan sejumlah besar utas memiliki lebih banyak peluang untuk mendapatkan waktu prosesor. Upaya telah dilakukan untuk menambahkan aturan ke penjadwal, yang menurutnya setiap sesi dianggap setara dengan yang lain dalam hal waktu prosesor. Fungsionalitas serupa ada di Linux dengan penjadwal yang sepenuhnya jujur (Penjadwal
Sepenuhnya Adil ). Di Windows 8, konsep ini digeneralisasi sebagai grup penjadwal dan ditambahkan ke penjadwal, sehingga setiap sesi jatuh ke dalam kelompok independen. Selain prioritas untuk utas, penjadwal menggunakan grup penjadwal sebagai indeks tingkat kedua, memutuskan utas mana yang akan mulai berikutnya. Di server terminal, semua grup penjadwal memiliki bobot yang sama, sehingga semua sesi menerima jumlah waktu prosesor yang sama, terlepas dari jumlah atau prioritas utas dalam grup penjadwal. Selain itu, kelompok-kelompok tersebut juga digunakan untuk kontrol yang lebih tepat atas proses. Di Windows 8, objek Pekerjaan telah ditingkatkan untuk mendukung
manajemen waktu prosesor . Menggunakan API khusus, Anda dapat memutuskan berapa lama waktu proses yang dapat digunakan suatu proses, apakah itu batas lunak atau keras, dan menerima pemberitahuan saat proses mencapai batas-batas ini. Ini mirip dengan manajemen sumber daya di
cgroups di Linux.
Dimulai dengan Windows 7, Windows Server memperkenalkan
dukungan untuk lebih dari 64 prosesor logis pada satu komputer. Untuk menambahkan dukungan ke begitu banyak prosesor, kategori baru telah diperkenalkan dalam sistem, "kelompok prosesor". Grup adalah serangkaian prosesor logis yang tidak lebih dari 64 buah, yang dianggap oleh penjadwal sebagai unit komputasi. Kernel saat boot menentukan prosesor mana yang termasuk kelompok mana, dan untuk mesin dengan kurang dari 64 inti prosesor, pendekatan ini hampir tidak mungkin untuk diperhatikan. Satu proses dapat dibagi menjadi beberapa kelompok (misalnya, contoh dari SQL server), satu utas pada satu waktu hanya dapat dilakukan dalam kelompok yang sama.
Tetapi pada mesin di mana jumlah core CPU melebihi 64, Windows mulai menunjukkan kemacetan baru yang tidak memungkinkan aplikasi yang menuntut seperti SQL-server untuk skala secara linear dengan meningkatnya jumlah core prosesor. Oleh karena itu, bahkan dengan penambahan core dan memori baru, pengukuran kecepatan tidak menunjukkan peningkatan yang signifikan. Salah satu masalah utama yang terkait dengan ini adalah perselisihan tentang memblokir basis operator. Mengunci basis data operator melindungi akses ke objek yang pekerjaannya harus direncanakan. Di antara objek-objek ini adalah utas, pengatur waktu, port input / output, objek kernel lain yang dapat menunggu (peristiwa, semaphore, mutex). Di bawah tekanan dari kebutuhan untuk menyelesaikan masalah seperti itu, pada Windows 7, pekerjaan dilakukan untuk menghilangkan pemblokiran database dispatcher dan menggantinya dengan penyesuaian yang lebih tepat, misalnya, penguncian objek-demi-blok. Ini memungkinkan pengukuran kinerja seperti SQL
TPC-C untuk menunjukkan peningkatan 290% dalam kecepatan dibandingkan dengan skema sebelumnya pada beberapa konfigurasi. Itu adalah salah satu peningkatan kinerja terbesar dalam sejarah Windows yang terjadi karena perubahan dalam satu fitur.
Windows 10 membawa inovasi lain dengan memperkenalkan set CPU. Set CPU memungkinkan suatu proses untuk mempartisi suatu sistem sehingga suatu proses dapat didistribusikan di beberapa kelompok prosesor, mencegah proses lain menggunakannya. Kernel Windows bahkan tidak mengizinkan perangkat menyela untuk menggunakan prosesor yang termasuk dalam set Anda. Ini memastikan bahwa bahkan perangkat tidak dapat menjalankan kode mereka pada prosesor yang dikeluarkan untuk grup aplikasi Anda. Sepertinya mesin virtual berteknologi rendah. Jelas bahwa ini adalah fitur yang kuat, begitu banyak langkah-langkah keamanan dibangun ke dalamnya sehingga pengembang aplikasi tidak membuat kesalahan besar ketika bekerja dengan API. Fungsionalitas set CPU digunakan dalam Mode Game.
Akhirnya, kami datang untuk mendukung ARM64,
yang muncul di Windows 10 . Arsitektur ARM mendukung arsitektur
big.LITTLE , yang sifatnya heterogen - inti "besar" cepat dan mengonsumsi banyak energi, dan inti "kecil" lambat dan mengonsumsi lebih sedikit. Idenya adalah bahwa tugas yang tidak signifikan dapat dilakukan pada inti kecil, sehingga menghemat baterai. Untuk mendukung arsitektur big.LITTLE dan meningkatkan masa pakai baterai ketika menjalankan Windows 10 pada ARM, dukungan tata letak yang heterogen ditambahkan ke penjadwal, dengan mempertimbangkan keinginan aplikasi yang bekerja dengan arsitektur big.LITTLE.
Dengan harapan, maksud saya Windows mencoba memberikan layanan berkualitas untuk aplikasi, melacak utas yang berjalan di latar depan (atau yang tidak memiliki waktu prosesor), dan menjamin eksekusi mereka pada inti "besar". Semua tugas latar belakang, layanan, dan utas bantu lainnya berjalan pada inti kecil. Juga dalam program ini, Anda dapat
secara paksa mencatat pentingnya thread untuk membuatnya bekerja pada inti kecil.
Bekerja atas nama orang lain [Bekerja atas nama]: di Windows, banyak pekerjaan di latar depan dilakukan oleh layanan lain yang bekerja di latar belakang. Misalnya, saat mencari di Outlook, pencarian itu sendiri dilakukan oleh layanan latar belakang Pengindeks. Jika kita menjalankan semua layanan pada inti kecil, kualitas dan kecepatan aplikasi di latar depan akan berkurang. Untuk mencegahnya melambat pada arsitektur big.LITTLE di bawah skenario kerja seperti itu, Windows memonitor panggilan aplikasi yang datang ke proses lain untuk melakukan pekerjaan atas nama mereka. Dalam hal ini, kami memberikan prioritas latar depan ke utas terkait dengan layanan dan memaksanya untuk berjalan pada inti besar.
Biarkan saya menyelesaikan artikel pertama ini pada kernel Windows, yang memberikan gambaran umum tentang penjadwal. Artikel dengan detail teknis serupa tentang cara kerja OS internal akan mengikuti nanti.