Linux Programming Interface menunjukkan tata letak ruang alamat virtual dari suatu proses. Apakah setiap wilayah dalam diagram adalah segmen?
Dari Memahami Kernel Linux ,
apakah benar bahwa berikut ini berarti bahwa unit segmentasi dalam MMU memetakan segmen dan offset dalam segmen ke alamat memori virtual, dan unit paging kemudian memetakan alamat memori virtual ke alamat memori fisik?
Memory Management Unit (MMU) mengubah alamat logis menjadi alamat linier melalui sirkuit perangkat keras yang disebut unit segmentasi; selanjutnya, rangkaian perangkat keras kedua yang disebut unit paging mengubah alamat linier menjadi alamat fisik (lihat Gambar 2-1).
Lalu mengapa dikatakan bahwa Linux tidak menggunakan segmentasi tetapi hanya paging?
Segmentasi telah dimasukkan dalam mikroprosesor 80x86 untuk mendorong programmer untuk membagi aplikasi mereka menjadi entitas yang berhubungan secara logis, seperti subrutin atau area data global dan lokal. Namun, Linux menggunakan segmentasi dengan cara yang sangat terbatas. Bahkan, segmentasi dan paging agak berlebihan, karena keduanya dapat digunakan untuk memisahkan ruang alamat fisik proses: segmentasi dapat menetapkan ruang alamat linear yang berbeda untuk setiap proses, sementara paging dapat memetakan ruang alamat linear yang sama ke dalam ruang alamat fisik yang berbeda . Linux lebih suka paging untuk segmentasi karena alasan berikut:
• Manajemen memori lebih sederhana ketika semua proses menggunakan nilai register segmen yang sama — yaitu, ketika mereka berbagi set alamat linear yang sama.
• Salah satu tujuan desain Linux adalah portabilitas ke berbagai arsitektur; Arsitektur RISC, khususnya, memiliki dukungan terbatas untuk segmentasi.
Versi 2.6 Linux menggunakan segmentasi hanya jika diperlukan oleh arsitektur 80x86.
Jawaban:
Arsitektur x86-64 tidak menggunakan segmentasi dalam mode panjang (mode 64-bit).
Empat dari register segmen: CS, SS, DS, dan ES dipaksa ke 0, dan batas ke 2 ^ 64.
https://en.wikipedia.org/wiki/X86_memory_segmentation#Later_developments
Tidak mungkin lagi bagi OS untuk membatasi rentang "alamat linear" mana yang tersedia. Karena itu ia tidak dapat menggunakan segmentasi untuk perlindungan memori; itu harus bergantung sepenuhnya pada paging.
Jangan khawatir tentang detail CPU x86 yang hanya akan berlaku saat berjalan dalam mode 32-bit lama. Linux untuk mode 32-bit tidak banyak digunakan. Bahkan mungkin dianggap "dalam keadaan diabaikan jinak selama beberapa tahun". Lihat dukungan x86 32-Bit di Fedora [LWN.net, 2017].
(Kebetulan Linux 32-bit tidak menggunakan segmentasi juga. Tapi Anda tidak perlu mempercayai saya tentang itu, Anda bisa mengabaikannya :-).
sumber
mov eax, [fs:rdi + 16]
). Kernel menggunakan GS (setelahswapgs
) untuk menemukan tumpukan kernel proses saat ini disyscall
titik masuk. Tapi ya, segmentasi tidak digunakan sebagai bagian dari manajemen memori OS utama / mekanisme perlindungan memori.Karena x86 memiliki segmen, tidak mungkin untuk tidak menggunakannya. Tetapi alamat basis
cs
(segmen kode) dands
(segmen data) diatur ke nol, sehingga segmentasi tidak benar-benar digunakan. Pengecualian adalah utas data lokal, salah satu segmen yang biasanya tidak digunakan mendaftarkan poin untuk utas data lokal. Tapi itu terutama untuk menghindari pemesanan salah satu register tujuan umum untuk tugas ini.Itu tidak mengatakan bahwa Linux tidak menggunakan segmentasi pada x86, karena itu tidak mungkin. Anda telah menyoroti satu bagian, Linux menggunakan segmentasi dengan cara yang sangat terbatas . Bagian kedua adalah Linux menggunakan segmentasi hanya jika diperlukan oleh arsitektur 80x86
Anda sudah mengutip alasannya, paging lebih mudah dan lebih portabel.
sumber
Tidak.
Sementara sistem segmentasi (dalam mode dilindungi 32-bit pada x86) dirancang untuk mendukung segmen kode, data, dan stack yang berbeda, dalam praktiknya semua segmen diatur ke area memori yang sama. Yaitu, mereka mulai dari 0 dan berakhir pada akhir memori (*) . Itu membuat alamat logis dan alamat linear sama.
Ini disebut model memori "datar", dan agak lebih sederhana daripada model di mana Anda memiliki segmen yang berbeda dan kemudian menunjuk di dalamnya. Khususnya, model yang tersegmentasi membutuhkan pointer yang lebih panjang, karena pemilih segmen harus dimasukkan sebagai tambahan dari pointer offset. (Pemilih segmen 16-bit + offset 32-bit untuk total pointer 48 bit; dibandingkan hanya pointer datar 32-bit.)
Mode 64-bit panjang bahkan tidak mendukung segmentasi selain model memori datar.
Jika Anda memprogram dalam mode terproteksi 16-bit pada 286, Anda akan membutuhkan lebih banyak untuk segmen, karena ruang alamat 24 bit tetapi pointer hanya 16 bit.
(* Perhatikan bahwa saya tidak dapat mengingat bagaimana Linux 32-bit menangani pemisahan kernel / userspace. Segmentasi akan memungkinkan melalui pengaturan batas-batas segmen userspace sehingga mereka tidak menyertakan ruang kernel. Paging memungkinkan untuk itu karena ia menyediakan tingkat perlindungan per halaman.)
X86 masih memiliki segmen dan Anda tidak dapat menonaktifkannya. Mereka hanya digunakan sesedikit mungkin. Dalam mode terproteksi 32-bit, segmen perlu diatur untuk model datar, dan bahkan dalam mode 64-bit mereka masih ada.
sumber
wrfsbase
ilegal dalam mode protected / compat, hanya mode panjang, jadi pada ruang pengguna kernel 32-bit tidak dapat mengatur basis FS tinggi.Linux x86 / 32 tidak menggunakan segmentasi dalam arti bahwa ia menginisialisasi semua segmen ke alamat dan batas linier yang sama. arsitektur x86 membutuhkan program untuk memiliki segmen: kode hanya dapat dijalankan dari segmen kode, tumpukan hanya dapat ditemukan di segmen tumpukan, data hanya dapat dimanipulasi di salah satu segmen data. Linux memintas mekanisme ini dengan mengatur semua segmen dengan cara yang sama (dengan pengecualian yang tidak disebutkan oleh buku Anda), sehingga alamat logis yang sama berlaku di segmen mana pun. Ini sebenarnya setara dengan tidak memiliki segmen sama sekali.
sumber
Ini adalah 2 penggunaan yang hampir sama sekali berbeda dari kata "segmen"
The penggunaan memiliki asal usul yang sama: jika Anda sedang menggunakan model memori tersegmentasi (terutama tanpa memori virtual paged), Anda mungkin memiliki data dan alamat BSS menjadi relatif terhadap DS dasar segmen, tumpukan relatif terhadap basis SS, dan kode relatif terhadap Alamat dasar CS.
Jadi banyak program yang berbeda dapat dimuat ke alamat linear yang berbeda, atau bahkan dipindahkan setelah memulai, tanpa mengubah offset 16 atau 32-bit relatif terhadap basis segmen.
Tetapi kemudian Anda harus tahu segmen mana yang relatif menjadi pointer, sehingga Anda memiliki "pointer jauh" dan seterusnya. (Sebenarnya program 16-bit x86 sering tidak perlu mengakses kode mereka sebagai data, sehingga dapat menggunakan segmen kode 64k di suatu tempat, dan mungkin blok 64k lainnya dengan DS = SS, dengan tumpukan yang tumbuh dari offset tinggi, dan data di bagian bawah atau model kode kecil dengan semua basis segmen sama).
Bagaimana segmentasi x86 berinteraksi dengan paging
Pemetaan alamat dalam mode 32/64-bit adalah:
tabel halaman (di-cache oleh TLB) memetakan linear ke 32 (mode legacy), 36 (legacy PAE), atau alamat fisik 52-bit (x86-64). ( /programming/46509152/why-in-64bit-the-virtual-address-are-4-bits-short-48bit-long-compared-with-the ).
Langkah ini opsional: paging harus diaktifkan selama bootup dengan mengatur sedikit dalam register kontrol. Tanpa paging, alamat linear adalah alamat fisik.
Perhatikan bahwa segmentasi tidak memungkinkan Anda menggunakan lebih dari 32 atau 64 bit ruang alamat virtual dalam satu proses (atau utas) , karena ruang alamat datar (linier) semuanya dipetakan ke dalam hanya memiliki jumlah bit yang sama seperti offset sendiri. (Ini tidak berlaku untuk 16-bit x86, di mana segmentasi sebenarnya berguna untuk menggunakan lebih dari 64k memori dengan sebagian besar register dan offset 16-bit.)
CPU cache cache segmen yang dimuat dari GDT (atau LDT), termasuk basis segmen. Saat Anda menentukan referensi sebuah pointer, tergantung pada register yang mana, itu default ke DS atau SS sebagai segmen. Nilai register (pointer) diperlakukan sebagai offset dari basis segmen.
Karena basis segmen biasanya nol, CPU melakukan hal khusus ini. Atau dari perspektif lain, jika Anda memang memiliki basis segmen yang tidak nol, beban memiliki latensi tambahan karena kasus "khusus" (normal) untuk memintas menambahkan penambahan alamat basis tidak berlaku.
Bagaimana Linux mengatur register segmen x86:
Basis dan batas CS / DS / ES / SS semuanya 0 / -1 dalam mode 32 dan 64-bit. Ini disebut model memori datar karena semua pointer menunjuk ke ruang alamat yang sama.
(Arsitek AMD CPU mensegmentasi segmentasi dengan memberlakukan model memori datar untuk mode 64-bit karena OS mainstream tidak menggunakannya, kecuali untuk perlindungan no-exec yang disediakan dengan cara yang jauh lebih baik dengan paging dengan PAE atau x86- Format 64 halaman-tabel.)
TLS (Thread Local Storage): FS dan GS tidak diperbaiki pada base = 0 dalam mode panjang. (Mereka baru dengan 386, dan tidak digunakan secara implisit oleh instruksi apa pun, bahkan
rep
instruksi -string yang menggunakan ES). x86-64 Linux menetapkan alamat dasar FS untuk setiap utas ke alamat blok TLS.misal
mov eax, [fs: 16]
memuat nilai 32-bit dari 16 byte ke blok TLS untuk utas ini.deskriptor segmen CS memilih mode apa yang digunakan CPU (mode terproteksi 16/32/64-bit / mode panjang). Linux menggunakan entri GDT tunggal untuk semua proses ruang pengguna 64-bit, dan entri GDT lain untuk semua proses ruang pengguna 32-bit. (Agar CPU berfungsi dengan benar, DS / ES juga harus diatur ke entri yang valid, dan begitu juga SS). Ia juga memilih level privilege (kernel (ring 0) vs. user (ring 3)), sehingga bahkan ketika kembali ke ruang pengguna 64-bit, kernel masih harus mengatur agar CS berubah, menggunakan
iret
atausysret
bukannya normal. lompat atau ret instruksi.Di x86-64,
syscall
titik masuk digunakanswapgs
untuk membalikkan GS dari ruang pengguna GS ke kernel, yang digunakannya untuk menemukan tumpukan kernel untuk utas ini. (Kasus khusus penyimpanan thread-lokal). Thesyscall
instruksi tidak mengubah stack pointer ke titik di stack kernel; itu masih menunjuk ke tumpukan pengguna ketika kernel mencapai titik masuk 1 .DS / ES / SS juga harus diatur ke deskriptor segmen yang valid agar CPU berfungsi dalam mode terproteksi / mode lama, meskipun basis / batas dari deskriptor tersebut diabaikan dalam mode panjang.
Jadi pada dasarnya segmentasi x86 digunakan untuk TLS, dan untuk hal-hal wajib x86 osdev yang diperlukan oleh perangkat keras untuk Anda lakukan.
Catatan Kaki 1: Riwayat menyenangkan: ada arsip milis pesan antara devs kernel dan arsitek AMD dari beberapa tahun sebelum silikon AMD64 dirilis, menghasilkan perubahan pada desain
syscall
sehingga dapat digunakan. Lihat tautan dalam jawaban ini untuk detailnya.sumber