Diyagramdaki her bölge bir bölüm mü?
Bunlar "segment" kelimesinin neredeyse tamamen farklı 2 kullanımıdır
- x86 segmentasyon / segment kayıtları: modern x86 işletim sistemleri, tüm segmentlerin aynı taban = 0 ve limit = 32-bit modunda maksimum olduğu, donanımın da 64-bit modda uyguladığı ve bölümleme türünü daha belirgin hale getirdiği düz bir bellek modeli kullanır . (FS veya GS hariç, 64 bit modunda bile yerel iş parçacığı depolaması için kullanılır.)
- Bağlayıcı / program yükleyici bölümleri / bölümleri. ( ELF dosya formatındaki kesit ve segment farkı nedir )
Kullanımları ortak orjine sahip: eğer edildi parçalara ayrılmış bir hafıza modeli (özellikle disk belleği sanal bellek olmadan) kullanılarak, veri sahip olabilir ve BSS adresleri DS kademeli baz SS tabanına yığın göre ve kod göreli olarak göreli CS taban adresi.
Böylelikle birden fazla farklı program, farklı doğrusal adreslere yüklenebilir ya da bölüm tabanlarına göre 16 veya 32 bit ofsetleri değiştirmeden başlattıktan sonra bile taşınabilir.
Ancak bir işaretçinin hangi segmente göre olduğunu bilmeniz gerekir, bu yüzden "uzak işaretçiler" vb. Vardır. (Gerçek 16-bit x86 programları genellikle kodlarına veri olarak erişmeye ihtiyaç duymazlardı, bu nedenle bir yerde 64k kod segmentini ve belki de DS = SS ile başka bir 64k bloğunu kullanabilirdi; Ya da tüm segment bazları eşit olan küçük bir kod modeli).
X86 segmentasyonu sayfalama ile nasıl etkileşime girer?
32/64-bit modunda adres eşleme:
- segment: offset (ofseti tutan ya da bir talimat önekiyle geçersiz kılınan kayıt defterinde belirtilen bölüm tabanı)
- 32 veya 64-bit doğrusal sanal adres = base + offset. (Linux gibi düz bir bellek modelinde, işaretçiler / ofsetler = doğrusal adresler de geçerlidir. FS veya GS'ye göre TLS'ye erişme hariç.)
sayfa tabloları (TLB tarafından önbelleğe alınmış), 32 (eski mod), 36 (eski PAE) veya 52 bit (x86-64) fiziksel adrese doğrusal eşlenir. ( /programming/46509152/why-in-64bit-the-virtual-address-are-4-bits-short-48bit-long-compared-with-the ).
Bu adım isteğe bağlıdır: disk belleği, başlatma sırasında bir kontrol kaydında bir bit ayarlayarak etkinleştirilmelidir. Sayfalama olmadan, doğrusal adresler fiziksel adreslerdir.
Segmentasyon olmadığını Bildirimi değil tek bir süreç (veya iplik) sanal adres alanı fazla 32 veya 64 bit kullanmasına izin sadece uzaklıklar kendilerini bit aynı sayıda içine düz (doğrusal) adres alanı her şey eşleştirilmiş çünkü. (Bu, 16 bit x86 için geçerli değildi, burada bölümlendirme, çoğunlukla 16 bit kayıt ve ofsetlerde 64k'dan fazla bellek kullanmak için faydalıydı.)
CPU, segment tabanı da dahil olmak üzere GDT'den (veya LDT) yüklenen segment tanımlayıcılarını önbelleğe alır. Bir işaretçiyi tercih ettiğinizde, hangi kayıt defterine bağlı olduğuna bağlı olarak, varsayılan olarak DS veya SS olarak değişir. Kayıt değeri (işaretçi), segment tabanından bir kayma olarak değerlendirilir.
Segment tabanı normalde sıfır olduğundan, CPU'lar bunu özel olarak yapar. Eğer Veya başka bir perspektiften, do sıfır olmayan bir segmenti üssü var, yükler ekstra gecikme var çünkü taban adresi geçerli değildir ekleyerek atlatacak bir "özel" (normal) durumda.
Linux x86 segment kayıtlarını nasıl kurar:
CS / DS / ES / SS'nin tabanı ve sınırı 32 ve 64-bit modunda 0 / -1'dir. Buna tüm işaretçiler aynı adres alanına işaret ettiği için buna düz bellek modeli denir.
(AMD CPU , 64-bit modu için düz bellek modelini zorlayarak bölümlendirmeyi kısırlaştırır, çünkü ana işletim sistemleri zaten PAE veya x86 ile çağrı yaparak çok daha iyi bir şekilde sağlanan yürütme koruması dışında 64 sayfa tablosu formatı.)
TLS (Konu Yerel Depolama): FS ve GS edilir değil uzun modda tabanında = 0 sabit. (386 ile rep
yeniydiler ve ES kullanan -sürekli yönergeler bile değil, hiçbir talimatla örtük olarak kullanılmamışlardı ). x86-64 Linux, her iş parçacığı için FS temel adresini TLS bloğunun adresine ayarlar.
örneğin mov eax, [fs: 16]
, bu iş parçacığı için 32 bitlik bir değeri 16 baytlık TLS bloğuna yükler.
CS segmenti tanımlayıcısı CPU'nun hangi modda olduğunu seçer (16/32/64-bit korumalı mod / uzun mod). Linux, tüm 64 bit kullanıcı alanı işlemleri için tek bir GDT girişi ve tüm 32 bit kullanıcı alanı işlemleri için başka bir GDT girişi kullanır. (İşlemcinin düzgün çalışması için DS / ES'nin de geçerli girişlere ayarlanması gerekir, SS de öyledir). Ayrıca, ayrıcalık seviyesini de seçer (çekirdek (ring 0) vs. kullanıcı (ring 3)), bu yüzden 64 bitlik bir kullanıcı alanına geri dönerken bile, çekirdeğin CS'yi normal bir yerine değiştirmek, kullanmak iret
veya sysret
yerine değiştirmek için düzenlemesi gerekir. atlama veya ret talimatı.
X86-64'te syscall
giriş noktası GS'yi swapgs
kullanıcı alanının GS'sinden çekirdeğe çevirmek için kullanır, bu iş parçacığı için çekirdek yığınını bulmak için kullanır. (Özel bir yerel iş parçacığı saklama durumu). syscall
Kullanıcı çekirdek yığını noktaya yığın işaretçisi değiştirmez; çekirdek, giriş noktası 1'e ulaştığında hala kullanıcı yığınına işaret ediyor .
DS / ES / SS'nin, CPU'nun korumalı modda / uzun modda çalışması için geçerli segment tanımlayıcılarına ayarlanması gerekir, ancak bu tanımlayıcılardan gelen taban / limit uzun modda göz ardı edilir.
Temelde x86 segmentasyonu, TLS ve donanımın gerektirdiği zorunlu x86 osdev işleri için kullanılır.
Dipnot 1: Eğlenceli tarih: AMD64 silikonu piyasaya sürülmesinden birkaç yıl önce çekirdek devleri ile AMD mimarları arasında mesaj listesi arşivleri var, bu da tasarımın üzerinde tweaks syscall
oldu. Ayrıntılar için bu cevaptaki bağlantılara bakın .