Apakah ruang Kernel digunakan ketika Kernel mengeksekusi atas nama program pengguna yaitu System Call? Atau apakah itu ruang alamat untuk semua utas Kernel (misalnya penjadwal)?
Ya dan ya.
Sebelum kita melangkah lebih jauh, kita harus menyatakan ini tentang memori.
Memori dapat dibagi menjadi dua area berbeda:
- Ruang pengguna , yang merupakan sekumpulan lokasi tempat proses pengguna normal dijalankan (yaitu segala sesuatu selain kernel). Peran kernel adalah untuk mengelola aplikasi yang berjalan di ruang ini dari saling mengotak, dan mesin.
- Ruang kernel , yang merupakan lokasi di mana kode kernel disimpan, dan dijalankan di bawah.
Proses yang berjalan di bawah ruang pengguna hanya memiliki akses ke bagian memori yang terbatas, sedangkan kernel memiliki akses ke semua memori. Proses yang berjalan di ruang pengguna juga tidak memiliki akses ke ruang kernel. Proses ruang pengguna hanya dapat mengakses sebagian kecil dari kernel melalui antarmuka yang terpapar oleh kernel - panggilan sistem . Jika suatu proses melakukan panggilan sistem, interupsi perangkat lunak dikirim ke kernel, yang kemudian mengirimkan penangan interupsi yang sesuai dan melanjutkan kerjanya setelah penangan selesai.
Kode ruang kernel memiliki properti untuk dijalankan dalam "mode kernel", yang (dalam komputer desktop -x86- khas Anda) adalah apa yang Anda sebut kode yang dijalankan di bawah ring 0 . Biasanya dalam arsitektur x86, ada 4 cincin perlindungan . Dering 0 (mode kernel), Dering 1 (dapat digunakan oleh hypervisor atau driver mesin virtual), Dering 2 (dapat digunakan oleh driver, saya tidak begitu yakin tentang itu). Dering 3 adalah aplikasi khas yang berjalan di bawah. Ini adalah dering yang paling tidak istimewa, dan aplikasi yang berjalan di atasnya memiliki akses ke subset dari instruksi prosesor. Dering 0 (ruang kernel) adalah dering paling istimewa, dan memiliki akses ke semua instruksi mesin. Sebagai contoh untuk ini, aplikasi "biasa" (seperti browser) tidak dapat menggunakan instruksi perakitan x86lgdt
untuk memuat tabel deskriptor global atau hlt
menghentikan prosesor.
Jika ini yang pertama, daripada apakah ini berarti bahwa program pengguna normal tidak dapat memiliki lebih dari 3GB memori (jika pembagiannya adalah 3GB + 1GB)? Juga, dalam hal ini bagaimana kernel dapat menggunakan Memori Tinggi, karena ke alamat memori virtual apa halaman dari memori tinggi akan dipetakan, karena 1GB ruang kernel akan dipetakan secara logis?
Untuk jawaban atas hal ini, silakan merujuk ke jawaban yang sangat bagus oleh wag di sini
-1
adalah untuk hypervisor? en.wikipedia.org/wiki/Protection_ringCincin CPU adalah perbedaan yang paling jelas
Dalam mode terproteksi x86, CPU selalu berada dalam salah satu dari 4 dering. Kernel Linux hanya menggunakan 0 dan 3:
Ini adalah definisi kernel vs userland yang paling keras dan cepat.
Mengapa Linux tidak menggunakan dering 1 dan 2: https://stackoverflow.com/questions/6710040/cpu-privilege-rings-why-rings-1-and-2-arent-used
Bagaimana cincin saat ini ditentukan?
Cincin saat ini dipilih oleh kombinasi dari:
tabel deskriptor global: tabel in-memory dari entri GDT, dan setiap entri memiliki bidang
Privl
yang menyandikan ring.Instruksi LGDT mengatur alamat ke tabel deskriptor saat ini.
Lihat juga: http://wiki.osdev.org/Global_Descriptor_Table
segmen mendaftarkan CS, DS, dll., yang menunjuk ke indeks entri di GDT.
Misalnya,
CS = 0
berarti entri pertama GDT saat ini aktif untuk kode pelaksana.Apa yang bisa dilakukan oleh setiap dering?
Chip CPU dibangun secara fisik sehingga:
dering 0 dapat melakukan apa saja
dering 3 tidak dapat menjalankan beberapa instruksi dan menulis ke beberapa register, terutama:
tidak dapat mengubah cincinnya sendiri! Kalau tidak, itu bisa mengatur dirinya sendiri untuk berdering 0 dan berdering akan sia-sia.
Dengan kata lain, tidak dapat memodifikasi deskriptor segmen saat ini , yang menentukan dering saat ini.
tidak dapat mengubah tabel halaman: https://stackoverflow.com/questions/18431261/how-does-x86-paging-work
Dengan kata lain, tidak dapat memodifikasi register CR3, dan paging itu sendiri mencegah modifikasi tabel halaman.
Ini mencegah satu proses dari melihat memori proses lain untuk keamanan / kemudahan alasan pemrograman.
tidak dapat mendaftarkan penangan interupsi. Itu dikonfigurasikan dengan menulis ke lokasi memori, yang juga dicegah dengan paging.
Handler dijalankan di ring 0, dan akan merusak model keamanan.
Dengan kata lain, tidak dapat menggunakan instruksi LGDT dan LIDT.
tidak dapat melakukan instruksi IO seperti
in
danout
, dan karenanya memiliki akses perangkat keras yang sewenang-wenang.Kalau tidak, misalnya, izin file tidak akan berguna jika program apa pun dapat langsung membaca dari disk.
Lebih tepatnya berkat Michael Petch : sebenarnya dimungkinkan bagi OS untuk mengizinkan instruksi IO pada cincin 3, ini sebenarnya dikendalikan oleh segmen status Tugas .
Yang tidak mungkin adalah cincin 3 memberi izin pada dirinya sendiri jika tidak memilikinya sejak awal.
Linux selalu melarangnya. Lihat juga: https://stackoverflow.com/questions/2711044/why-doesnt-linux-use-the-hardware-context-switch-via-the-tss
Bagaimana transisi program dan sistem operasi antar cincin?
ketika CPU dihidupkan, itu mulai menjalankan program awal di ring 0 (agak baik, tetapi itu adalah perkiraan yang baik). Anda dapat menganggap program awal ini sebagai kernel (tetapi biasanya bootloader yang kemudian memanggil kernel masih di ring 0).
ketika proses userland menginginkan kernel untuk melakukan sesuatu untuknya seperti menulis ke file, ia menggunakan instruksi yang menghasilkan interupsi seperti
int 0x80
atausyscall
untuk memberi sinyal kernel. x86-64 Linux syscall hello world contoh:kompilasi dan jalankan:
GitHub hulu .
Ketika ini terjadi, CPU memanggil pengendali panggilan balik interupsi yang didaftarkan kernel saat boot. Berikut adalah contoh baremetal konkret yang mendaftarkan pawang dan menggunakannya .
Handler ini berjalan di ring 0, yang memutuskan apakah kernel akan mengizinkan tindakan ini, melakukan tindakan, dan memulai kembali program userland di cincin 3. x86_64
ketika
exec
panggilan sistem digunakan (atau ketika kernel akan mulai/init
), kernel menyiapkan register dan memori dari proses userland baru, kemudian melompat ke titik masuk dan mengalihkan CPU ke dering 3Jika program mencoba melakukan sesuatu yang nakal seperti menulis ke register terlarang atau alamat memori (karena paging), CPU juga memanggil beberapa handler callback kernel di ring 0.
Tetapi karena userland nakal, kernel mungkin membunuh proses kali ini, atau memberinya peringatan dengan sinyal.
Ketika kernel melakukan boot, ia akan mengatur jam perangkat keras dengan frekuensi tetap, yang menghasilkan interupsi secara berkala.
Jam perangkat keras ini menghasilkan interupsi yang menjalankan dering 0, dan memungkinkannya untuk menjadwalkan pengguna mana proses untuk bangun.
Dengan cara ini, penjadwalan dapat terjadi bahkan jika proses tidak membuat panggilan sistem apa pun.
Apa gunanya memiliki beberapa dering?
Ada dua keuntungan utama dari pemisahan kernel dan userland:
Bagaimana cara bermain-main dengannya?
Saya telah membuat pengaturan logam kosong yang seharusnya menjadi cara yang baik untuk memanipulasi cincin secara langsung: https://github.com/cirosantilli/x86-bare-metal-examples
Saya tidak memiliki kesabaran untuk membuat contoh userland sayangnya, tapi saya melakukan pengaturan paging, jadi userland harus layak. Saya ingin melihat permintaan tarik.
Sebagai alternatif, modul kernel Linux berjalan di ring 0, sehingga Anda dapat menggunakannya untuk mencoba operasi yang diistimewakan, mis. Baca register kontrol: https://stackoverflow.com/questions/7415515/how-to-access-the-control-registers -cr0-cr2-cr3-dari-program-mendapatkan-segmenta / 7419306 # 7419306
Berikut ini adalah pengaturan QEMU + Buildroot yang nyaman untuk mencobanya tanpa membunuh host Anda.
Kelemahan dari modul kernel adalah bahwa kthreads lain sedang berjalan dan dapat mengganggu percobaan Anda. Tetapi secara teori Anda dapat mengambil alih semua penangan interupsi dengan modul kernel Anda dan memiliki sistem, yang sebenarnya merupakan proyek yang menarik.
Dering negatif
Walaupun dering negatif tidak benar-benar dirujuk dalam manual Intel, sebenarnya ada mode CPU yang memiliki kemampuan lebih lanjut dari dering 0 itu sendiri, dan begitu juga cocok untuk nama "cincin negatif".
Salah satu contoh adalah mode hypervisor yang digunakan dalam virtualisasi.
Untuk perincian lebih lanjut, lihat: https://security.stackexchange.com/questions/129098/what-is-protection-ring-1
LENGAN
Dalam ARM, cincinnya disebut Tingkat Pengecualian, tetapi gagasan utamanya tetap sama.
Ada 4 level pengecualian dalam ARMv8, yang biasa digunakan sebagai:
EL0: userland
EL1: kernel ("supervisor" dalam terminologi ARM).
Dimasukkan dengan
svc
instruksi (Panggilan SuperVisor), yang sebelumnya dikenal sebagaiswi
unified assembly , yang merupakan instruksi yang digunakan untuk melakukan panggilan sistem Linux. Contoh Hello world ARMv8:GitHub hulu .
Uji dengan QEMU di Ubuntu 16.04:
Berikut ini adalah contoh nyata beton yang mendaftarkan penangan SVC dan melakukan panggilan SVC .
EL2: hypervisors , misalnya Xen .
Dimasukkan dengan
hvc
instruksi (Panggilan HyperVisor).Hypervisor adalah untuk OS, apa OS untuk userland.
Sebagai contoh, Xen memungkinkan Anda untuk menjalankan banyak OS seperti Linux atau Windows pada sistem yang sama secara bersamaan, dan itu mengisolasi OS satu sama lain untuk keamanan dan kemudahan debug, seperti halnya Linux untuk program userland.
Hypervisor adalah bagian penting dari infrastruktur cloud saat ini: mereka memungkinkan banyak server untuk berjalan pada satu perangkat keras, menjaga penggunaan perangkat keras selalu mendekati 100% dan menghemat banyak uang.
AWS misalnya menggunakan Xen hingga 2017 ketika kepindahannya ke KVM menjadi berita .
EL3: tingkat lain. Contoh TODO.
Dimasukkan dengan
smc
instruksi (Panggilan Mode Aman)The ARMv8 Arsitektur Model Referensi DDI 0487C.a - Bab D1 - The AArch64 Sistem Tingkat Programmer Model - Gambar D1-1 menggambarkan ini indah:
Perhatikan bagaimana ARM, mungkin karena manfaat dari belakang, memiliki konvensi penamaan yang lebih baik untuk tingkat hak istimewa daripada x86, tanpa perlu tingkat negatif: 0 menjadi yang lebih rendah dan 3 tertinggi. Level yang lebih tinggi cenderung dibuat lebih sering daripada level yang lebih rendah.
EL saat ini dapat ditanyakan dengan
MRS
instruksi: https://stackoverflow.com/questions/31787617/what-is-the-current-execution-mode-exception-level-etcARM tidak memerlukan semua level pengecualian untuk hadir untuk memungkinkan implementasi yang tidak memerlukan fitur untuk menghemat area chip. ARMv8 "Level pengecualian" mengatakan:
QEMU misalnya default ke EL1, tetapi EL2 dan EL3 dapat diaktifkan dengan opsi baris perintah: https://stackoverflow.com/questions/42824706/qemu-system-aarch64-entering-el1-when-emulating-a53-power-up
Cuplikan kode diuji di Ubuntu 18.10.
sumber
Ya ini terjadi pada sistem linux normal. Ada satu set tambalan "4G / 4G" melayang di satu titik yang membuat ruang alamat pengguna dan kernel benar-benar independen (dengan biaya kinerja karena membuat kernel lebih sulit untuk mengakses memori pengguna) tapi saya tidak berpikir mereka pernah bergabung ke hulu dan minat berkurang dengan munculnya x86-64
Cara linux digunakan untuk bekerja (dan masih dilakukan pada sistem di mana memori kecil dibandingkan dengan ruang alamat) adalah bahwa seluruh memori fisik secara permanen dipetakan ke bagian kernel dari ruang alamat. Ini memungkinkan kernel untuk mengakses semua memori fisik tanpa memetakan kembali tetapi jelas itu tidak skala ke mesin 32-bit dengan banyak memori fisik.
Maka lahirlah konsep memori rendah dan tinggi. memori "rendah" secara permanen dipetakan ke dalam ruang alamat kernel. memori "tinggi" tidak.
Ketika prosesor menjalankan panggilan sistem, prosesor berjalan dalam mode kernel tetapi masih dalam konteks proses saat ini. Sehingga ia dapat secara langsung mengakses ruang alamat kernel dan ruang alamat pengguna dari proses saat ini (dengan asumsi Anda tidak menggunakan tambalan 4G / 4G yang disebutkan di atas). Ini berarti tidak ada masalah untuk memori "tinggi" dialokasikan untuk proses userland.
Menggunakan memori "tinggi" untuk keperluan kernel lebih merupakan masalah. Untuk mengakses memori tinggi yang tidak dipetakan ke proses saat ini, ia harus sementara dipetakan ke dalam ruang alamat kernel. Itu berarti kode tambahan dan penalti kinerja.
sumber