You are on page 1of 300

Machine Translated by Google

234 Bölüm 5 CPU Programlama

• SCHED FIFO

• SCHED RR

SCHED FIFO , Bölüm 5.3.1'de özetlendiği gibi bir FIFO kuyruğu kullanarak ilk
gelen, ilk hizmet alır ilkesine göre iş parçacıklarını programlar . Ancak, eşit önceliğe
sahip iş parçacıkları arasında zaman dilimleme yoktur. Bu nedenle, FIFO kuyruğunun
önündeki en yüksek öncelikli gerçek zamanlı iş parçacığına, sonlandırılana veya
bloke olana kadar CPU verilecektir . SCHED RR , bir döngüsel deneme ilkesi kullanır.
Eşit öncelikli iş parçacıkları arasında zaman dilimleme sağlaması dışında SCHED
FIFO'ya benzer . POSIX , ek bir zamanlama sınıfı—SCHED OTHER— sağlar , ancak
uygulaması tanımlanmamıştır ve sisteme özeldir; farklı sistemlerde farklı davranabilir.

POSIX API , zamanlama ilkesini almak ve ayarlamak için aşağıdaki iki işlevi belirtir:

• pthread attr getchedpolicy(pthread attr t *attr, int


*politika)
• pthread attr setchedpolicy(pthread attr t *attr, int
politika)

Her iki işlevin ilk parametresi, iş parçacığı için nitelikler kümesine yönelik bir
işaretçidir. İkinci parametre, (1) geçerli zamanlama ilkesine ( pthread attr getched
policy() için) ayarlanmış bir tamsayıya yönelik bir işaretçi veya (2) pthread attr setched
ilke() işlevi. Bir hata oluşursa her iki işlev de sıfır olmayan değerler döndürür.

Şekil 5.25'te bu API'yi kullanan bir POSIX Pthread programını gösteriyoruz . Bu


program önce mevcut çizelgeleme politikasını belirler ve ardından çizelgeleme
algoritmasını SCHED FIFO'ya ayarlar.

5.7 İşletim Sistemi Örnekleri

Linux, Windows ve Solaris işletim sistemlerinin zamanlama ilkelerinin açıklamasının


yanına dönüyoruz. Burada süreç çizelgeleme terimini genel anlamda kullandığımızı
belirtmek önemlidir . Aslında, Solaris ve Windows sistemleri ile çekirdek iş
parçacıklarının ve Linux zamanlayıcı ile görevlerin zamanlamasını tanımlıyoruz.

5.7.1 Örnek: Linux Programlama

Linux'ta süreç programlamanın ilginç bir geçmişi vardır. Sürüm 2.5'ten önce, Linux
çekirdeği, geleneksel UNIX zamanlama algoritmasının bir varyasyonunu çalıştırıyordu.
Ancak bu algoritma SMP sistemleri düşünülerek tasarlanmadığından, birden çok
işlemcili sistemleri yeterince desteklemiyordu. Ayrıca, çok sayıda çalıştırılabilir sürece
sahip sistemler için düşük performansa neden oldu. Çekirdeğin 2.5 Sürümü ile,
zamanlayıcı , sistemdeki görev sayısından daha azını dikkate alarak sabit zamanda
çalışan O(1) olarak bilinen bir zamanlama algoritmasını içerecek şekilde elden
geçirildi . O (1) zamanlayıcı da sağlanır
5.7 İşletim Sistemi Örnekleri 235
Machine Translated by Google

#include <pthread.h> #include


<stdio.h> #define NUM
THREADS 5

int main(int argc, char *argv[]) {

int i, ilke; pthread t


tid[NUM THEADS]; pthread attr t attr;

/* varsayılan öznitelikleri al */ pthread attr


init(&attr);

/* mevcut zamanlama politikasını al */ if (pthread attr


getchedpolicy(&attr, &policy) != 0) fprintf(stderr, "Politika alınamadı. n");
else { if (politika == SCHED DİĞER) printf("SCHED OTHER n"); else
if (politika == SCHED RR) printf("SCHED RR n"); else if (politika ==
SCHED FIFO) printf("SCHED FIFO n");

/* zamanlama politikasını ayarla - FIFO, RR veya OTHER */ if (pthread attr


setchedpolicy(&attr, SCHED FIFO) != 0) fprintf(stderr, "Politika
ayarlanamıyor. n");

/* thread'leri yarat */ for (i = 0; i <


NUM THREADS; i++) pthread
create(&tid[i],&attr,runner,NULL);

/* şimdi her diziye katıl */ for (i = 0; i <


NUM THREADS; i++) pthread join(tid[i], NULL);

/* Bu fonksiyonda her thread kontrole başlayacaktır */ void *runner(void


*param) {

/* biraz iş yap ... */

pthread çıkış (0);


}

Şekil 5.25 POSIX gerçek zamanlı zamanlama API'si.


236 Bölüm 5 CPU Programlama
Machine Translated by Google

işlemci benzerliği ve işlemciler arasında yük dengeleme dahil olmak üzere SMP
sistemleri için artırılmış destek . Bununla birlikte, pratikte, O(1) zamanlayıcı SMP
sistemlerinde mükemmel performans sunmasına rağmen, birçok masaüstü bilgisayar
sisteminde yaygın olan etkileşimli işlemler için yetersiz yanıt sürelerine yol açtı. 2.6
çekirdeğinin geliştirilmesi sırasında, zamanlayıcı yeniden revize edildi; ve çekirdeğin
2.6.23 sürümünde, Tamamen Adil Zamanlayıcı (CFS) , varsayılan Linux zamanlama
algoritması oldu.
Linux sisteminde çizelgeleme, çizelgeleme sınıflarına dayalıdır . Her sınıfa belirli bir
öncelik atanır. Çekirdek, farklı zamanlama sınıfları kullanarak, sistemin ve süreçlerinin
ihtiyaçlarına göre farklı zamanlama algoritmalarını barındırabilir. Örneğin, bir Linux
sunucusu için zamanlama kriterleri, Linux çalıştıran bir mobil cihaz için olanlardan farklı
olabilir. Daha sonra hangi görevin çalıştırılacağına karar vermek için zamanlayıcı, en
yüksek öncelikli zamanlama sınıfına ait olan en yüksek öncelikli görevi seçer. Standart
Linux çekirdekleri iki zamanlama sınıfı uygular: (1) CFS zamanlama algoritmasını kullanan
bir varsayılan zamanlama sınıfı ve (2) bir gerçek zamanlı zamanlama sınıfı. Bu sınıfların
her birini burada tartışıyoruz. Yeni zamanlama sınıfları elbette eklenebilir.

Göreceli bir öncelik değerini bir zaman kuantumunun uzunluğuyla ilişkilendiren


katı kurallar kullanmak yerine, CFS zamanlayıcı her göreve CPU işleme süresinin bir
oranını atar . Bu oran, her göreve atanan hoş değere göre hesaplanır . Nice değerleri
-20 ile +19 arasında değişir; burada sayısal olarak daha düşük bir Nice değeri daha
yüksek bir göreli önceliği gösterir. Daha düşük Nice değerlerine sahip görevler, daha
yüksek Nice değerlerine sahip görevlerden daha yüksek oranda CPU işleme süresi alır.
Varsayılan Nice değeri 0'dır. ( Güzel terimi , bir görev Nice değerini örneğin 0'dan
+10'a çıkarırsa, göreli önceliğini düşürerek sistemdeki diğer görevlere iyi davrandığı
fikrinden gelir. kelimeler, güzel işlemler en son biter!) CFS , zaman dilimlerinin ayrık
değerlerini kullanmaz ve bunun yerine , her çalıştırılabilir görevin en az bir kez çalışması
gereken bir zaman aralığı olan hedeflenen bir gecikmeyi tanımlar. CPU zamanının
oranları , hedeflenen gecikme değerinden ayrılır. Varsayılan ve minimum değerlere
sahip olmanın yanı sıra, sistemdeki etkin görevlerin sayısı belirli bir eşiğin üzerine
çıkarsa hedeflenen gecikme artabilir.

CFS zamanlayıcı, öncelikleri doğrudan atamaz . Bunun yerine, görev başına


değişken vruntime'ı kullanarak her bir görevin sanal çalışma süresini koruyarak her bir
görevin ne kadar sürdüğünü kaydeder. Sanal çalışma süresi, bir görevin önceliğine
dayalı bir azalma faktörü ile ilişkilidir: düşük öncelikli görevler, yüksek öncelikli
görevlerden daha yüksek bozulma oranlarına sahiptir. Normal önceliğe sahip görevler
için (0'ın güzel değerleri), sanal çalıştırma süresi gerçek fiziksel çalıştırma süresiyle
aynıdır. Bu nedenle, varsayılan önceliğe sahip bir görev 200 milisaniye çalışırsa,
vruntime da 200 milisaniye olacaktır. Ancak, daha düşük öncelikli bir görev 200 milisaniye
boyunca çalışırsa , çalışma zamanı 200 milisaniyeden daha yüksek olacaktır. Benzer
şekilde, daha yüksek öncelikli bir görev 200 milisaniye boyunca çalışırsa , çalışma süresi 200 m
Daha sonra hangi görevin çalıştırılacağına karar vermek için zamanlayıcı, en küçük
vruntime değerine sahip görevi seçer. Ayrıca, çalıştırılabilir hale gelen daha yüksek
öncelikli bir görev, daha düşük öncelikli bir görevi önceleyebilir.
CFS zamanlayıcısını çalışırken inceleyelim : İki görevin aynı Nice değerlerine sahip
olduğunu varsayalım. Görevlerden biri G/Ç'ye, diğeri ise CPU'ya bağlıdır.
Tipik olarak, G/Ç'ye bağlı görev, ek G/Ç'yi engellemeden önce yalnızca kısa süreler için
çalışır ve CPU'ya bağlı görev, bir işlemci üzerinde çalışma fırsatı bulduğunda zaman
periyodunu tüketir. Bu nedenle, vruntime değeri
Machine Translated by Google

5.7 İşletim Sistemi Örnekleri 237

CFS PERFORMANSI

Linux CFS zamanlayıcısı, bir sonraki görevin çalıştırılacağını seçmek için verimli bir
algoritma sağlar. Standart bir kuyruk veri yapısı kullanmak yerine, çalıştırılabilir her
görev kırmızı-siyah bir ağaca - anahtarı vruntime değerine dayanan dengeli bir ikili
arama ağacına - yerleştirilir. Bu ağaç aşağıda gösterilmiştir.

T0
en küçük vruntime
T1 T2
değerine sahip görev

T3 T4 T5 T6

T7 T8 T9

daha küçük daha büyük


vruntime değeri

Bir görev çalıştırılabilir hale geldiğinde ağaca eklenir. Ağaçtaki bir görev
çalıştırılamazsa (örneğin, G/Ç beklerken engellenirse), kaldırılır. Genel olarak
konuşursak, daha az işlem süresi verilen görevler ( vruntime'ın daha küçük
değerleri) ağacın sol tarafındadır ve daha fazla işlem süresi verilen görevler sağ
taraftadır. İkili arama ağacının özelliklerine göre, en soldaki düğüm en küçük
anahtar değere sahiptir, bu da CFS zamanlayıcısı için en yüksek önceliğe sahip
görev olduğu anlamına gelir. Kırmızı-siyah ağaç dengeli olduğundan, en soldaki
düğümü keşfetmek için gezinmek O(log N) işlemlerini gerektirir (burada N ,
ağaçtaki düğüm sayısıdır). Bununla birlikte, verimlilik nedenleriyle, Linux
zamanlayıcı bu değeri en soldaki rb değişkeninde önbelleğe alır ve bu nedenle
bir sonraki hangi görevin çalıştırılacağını belirlemek yalnızca önbelleğe alınan
değerin alınmasını gerektirir.

sonuçta G/Ç'ye bağlı görev için CPU'ya bağlı görevden daha düşük olur ve G/Ç'ye bağlı
göreve CPU'ya bağlı görevden daha yüksek öncelik verir . Bu noktada, G/Ç'ye bağlı
görev çalışmaya uygun hale geldiğinde (örneğin, görevin beklediği G/Ç kullanılabilir
hale geldiğinde) CPU'ya bağlı görev yürütülüyorsa, G/Ç'ye bağlı görev öncelikli
olacaktır . CPU'ya bağlı görev .
Linux ayrıca Bölüm 5.6.6'da açıklandığı gibi POSIX standardını kullanarak gerçek
zamanlı zamanlama uygular . SCHED FIFO veya SCHED RR gerçek zamanlı ilkesi
kullanılarak zamanlanan herhangi bir görev , normal (gerçek zamanlı olmayan)
görevlerden daha yüksek bir öncelikte çalışır. Linux, biri gerçek zamanlı görevler için
diğeri normal görevler için olmak üzere iki ayrı öncelik aralığı kullanır. Gerçek zamanlı
görevlere 0 ila 99 aralığında statik öncelikler atanır ve normal görevlere 100 ila 139 arasında öncelikler atanır.
Bu iki aralık, sayısal olarak daha düşük değerlerin daha yüksek göreli öncelikleri
gösterdiği bir küresel öncelik şemasına eşlenir. Normal görevlere öncelik verilir
Machine Translated by Google

238 Bölüm 5 CPU Programlama

gerçek zamanlı normal


0 99 100 139

daha yüksek daha düşük

öncelik

Şekil 5.26 Bir Linux sisteminde zamanlama öncelikleri.

-20 haritanın değeri 100'e ve +19 haritanın nice değerinin 139'a denk geldiği nice
değerlerine dayalıdır. Bu şema Şekil 5.26'da gösterilmektedir.
CFS zamanlayıcı, aynı zamanda NUMA'nın farkında olduğu ve iş parçacıklarının
geçişini en aza indiren, işleme çekirdekleri arasındaki yükü eşitleyen karmaşık bir
teknik kullanarak yük dengelemeyi de destekler . CFS , her iş parçacığının yükünü, iş
parçacığının önceliği ile ortalama CPU kullanım oranının bir birleşimi olarak tanımlar.
Bu nedenle, yüksek önceliğe sahip, ancak çoğunlukla G/Ç'ye bağlı olan ve az CPU
kullanımı gerektiren bir iş parçacığı, yüksek CPU kullanımına sahip düşük öncelikli bir
iş parçacığının yüküne benzer şekilde, genellikle düşük bir yüke sahiptir . Bu metriği
kullanarak, bir kuyruğun yükü, kuyruktaki tüm iş parçacıklarının yüklerinin toplamıdır
ve dengeleme, basitçe tüm sıraların yaklaşık olarak aynı yüke sahip olmasını sağlamaktır.
Bununla birlikte, Bölüm 5.5.4'te vurgulandığı gibi, bir iş parçacığının taşınması,
önbellek içeriklerinin geçersiz kılınması veya NUMA sistemlerinde daha uzun bellek
erişim sürelerine maruz kalması nedeniyle bellek erişim cezasına neden olabilir. Bu
sorunu çözmek için Linux, hiyerarşik bir zamanlama etki alanı sistemi tanımlar.
Bir zamanlama alanı , birbirine karşı dengelenebilen bir dizi CPU çekirdeğidir. Bu fikir
Şekil 5.27'de gösterilmektedir. Her bir zamanlama alanındaki çekirdekler, sistemin
kaynaklarını nasıl paylaştıklarına göre gruplandırılır.
Örneğin, Şekil 5.27'de gösterilen her çekirdeğin kendi seviye 1 (L1) önbelleği
olmasına rağmen, çekirdek çiftleri seviye 2 (L2) önbelleğini paylaşır ve bu nedenle
ayrı domain0 ve domain1 olarak düzenlenir. Benzer şekilde, bu iki alan bir seviye 3 (L3)
önbelleğini paylaşabilir ve bu nedenle işlemci düzeyinde bir alan ( NUMA düğümü
olarak da bilinir) halinde düzenlenir . Bir NUMA sisteminde bunu bir adım daha ileri götürerek,

fiziksel işlemci alanı


(NUMA düğümü)

etki alanı0 etki alanı1

çekirdek2
çekirdek0

L2 L2

çekirdek3
çekirdek1

L3

Şekil 5.27 Linux CFS zamanlayıcı ile NUMA uyumlu yük dengeleme.
Machine Translated by Google

5.7 İşletim Sistemi Örnekleri 239

sistem düzeyinde daha büyük bir etki alanı, ayrı işlemci düzeyinde NUMA düğümlerini
birleştirir.
CFS'nin arkasındaki genel strateji , hiyerarşinin en alt seviyesinden başlayarak, etki
alanları içindeki yükleri dengelemektir. Örnek olarak Şekil 5.27'yi kullanarak, başlangıçta
bir iş parçacığı yalnızca aynı etki alanındaki (yani, etki alanı0 veya etki alanı1 içindeki )
çekirdekler arasında göç eder. Bir sonraki düzeyde yük dengeleme, etki alanı0 ve etki
alanı1 arasında gerçekleşir . CFS , bir iş parçacığı yerel belleğinden daha uzağa
taşınacaksa, iş parçacıklarını ayrı NUMA düğümleri arasında taşıma konusunda isteksizdir
ve bu tür geçiş yalnızca ciddi yük dengesizlikleri altında gerçekleşir. Genel bir kural
olarak, genel sistem meşgulse, CFS , NUMA sistemlerinin bellek gecikme cezalarından
kaçınmak için her bir çekirdeğe yerel etki alanının ötesinde yük dengelemesi yapmaz .

5.7.2 Örnek: Windows Zamanlama Windows, öncelik

tabanlı, önleyici bir zamanlama algoritması kullanarak iş parçacıklarını zamanlar.


Windows zamanlayıcı, en yüksek öncelikli iş parçacığının her zaman çalışmasını sağlar.
Windows çekirdeğinin zamanlamayı yöneten kısmına sevk programı denir. Gönderici
tarafından çalıştırılmak üzere seçilen bir iş parçacığı, daha yüksek öncelikli bir iş
parçacığı tarafından öncelenene kadar, sona erene kadar, zaman kuantumu bitene
kadar veya G/Ç için olduğu gibi bir engelleme sistemi çağrısını çağırana kadar
çalışacaktır. Daha düşük öncelikli bir iş parçacığı çalışırken daha yüksek öncelikli bir
gerçek zamanlı iş parçacığı hazır hale gelirse, düşük öncelikli iş parçacığı öncelikli
olacaktır. Bu öncelik , iş parçacığı böyle bir ihtiyaç duyduğunda, gerçek zamanlı bir iş parçacığına CPU'ya tercihli eriş
erişim.

Dağıtıcı, iş parçacığı yürütme sırasını belirlemek için 32 düzeyli bir öncelik şeması
kullanır. Öncelikler iki sınıfa ayrılır. Değişken sınıf , 1'den 15'e kadar önceliklere sahip iş
parçacıklarını içerir ve gerçek zamanlı sınıf , 16'dan 31'e kadar olan önceliğe sahip iş
parçacıklarını içerir. (Ayrıca, bellek yönetimi için kullanılan, 0 önceliğinde çalışan bir iş
parçacığı da vardır.) Gönderici bir Her bir zamanlama önceliği için kuyruk oluşturur ve
çalışmaya hazır bir iş parçacığı bulana kadar kuyruklar kümesini en yüksekten en
düşüğe doğru hareket ettirir. Hazır iş parçacığı bulunamazsa, gönderici boş iş
parçacığı adı verilen özel bir iş parçacığı yürütür.
Windows çekirdeğinin sayısal öncelikleri ile Windows API'si arasında bir ilişki vardır.
Windows API , bir işlemin ait olabileceği aşağıdaki altı öncelik sınıfını tanımlar:

• BOŞTA ÖNCELİKLİ SINIF

• NORMAL ÖNCELİKLİ SINIF ALTINDA

• NORMAL ÖNCELİKLİ SINIF

• NORMAL ÖNCELİKLİ SINIF ÜZERİNDE

• YÜKSEK ÖNCELİKLİ SINIF

• GERÇEK ZAMANLI ÖNCELİKLİ SINIF

Süreçler tipik olarak NORMAL ÖNCELİK SINIFI'nın üyeleridir. Sürecin ebeveyni, IDLE
PRIORITY CLASS'ın bir üyesi olmadığı veya süreç oluşturulurken başka bir sınıf
belirtilmediği sürece , bir süreç bu sınıfa aittir . Ek olarak, bir işlemin öncelik sınıfı şu
şekilde değiştirilebilir:
Machine Translated by Google

240 Bölüm 5 CPU Programlama

Windows API'sindeki SetPriorityClass () işlevi . REALTIME PRIORITY CLASS dışındaki tüm


sınıflardaki öncelikler değişkendir, yani bu sınıflardan birine ait bir iş parçacığının önceliği
değişebilir.
Belirli bir öncelik sınıfındaki bir iş parçacığının da göreli bir önceliği vardır. Göreceli
öncelikler için değerler şunları içerir:

• BOŞTA

• EN DÜŞÜK

• NORMALİN ALTINDA

• NORMAL

• NORMALİN ÜZERİNDE

• EN YÜKSEK

• ZAMAN KRİTİK

Her iş parçacığının önceliği, hem ait olduğu öncelik sınıfına hem de o sınıf içindeki
göreli önceliğine bağlıdır. Bu ilişki Şekil 5.28'de gösterilmektedir. Öncelik sınıflarının
değerleri üst satırda görünür. Sol sütun, göreli önceliklerin değerlerini içerir. Örneğin,
NORMAL ÖNCELİK SINIFINDAN YUKARIDAKİ bir iş parçacığının göreli önceliği NORMAL
ise , o iş parçacığının sayısal önceliği 10'dur.

Ayrıca, her iş parçacığının, iş parçacığının ait olduğu sınıf için öncelik aralığında bir
değeri temsil eden bir temel önceliği vardır. Varsayılan olarak, temel öncelik, o sınıf için
NORMAL göreli önceliğin değeridir. Her bir öncelik sınıfı için temel öncelikler aşağıdaki
gibidir:

• GERÇEK ZAMAN ÖNCELİKLİ SINIF—24

• YÜKSEK ÖNCELİKLİ SINIF—13

• NORMAL ÖNCELİKLİ SINIF—10 ÜZERİNDE

• NORMAL ÖNCELİKLİ SINIF-8

gerçek normalin
yüksek normal
zamanlı üstünde normalin altında
boşta öncelik

zaman açısından kritik 31 15 15 15 15 15

en yüksek 26 15 12 10 8 6

normalin üstünde 25 14 11 9 7 5

normal 24 13 10 8 6 4

normalin altında 23 12 9 7 5 3

en düşük 22 11 8 6 4 2

Boşta 16 1 1 1 1 1

Şekil 5.28 Windows iş parçacığı öncelikleri.


5.7 İşletim Sistemi Örnekleri 241
Machine Translated by Google
• NORMAL ÖNCELİKLİ SINIF—6 ALTINDA

• BOŞTA ÖNCELİKLİ SINIF—4

Bir iş parçacığının ilk önceliği, genellikle iş parçacığının ait olduğu işlemin temel
önceliğidir, ancak Windows API'sindeki SetThreadPriority() işlevi bir iş parçacığının
temel önceliğini değiştirmek için de kullanılabilir.
Bir iş parçacığının zaman kuantumu bittiğinde, o iş parçacığı kesintiye uğrar.
İş parçacığı değişken öncelikli sınıftaysa, önceliği düşürülür. Ancak öncelik hiçbir
zaman temel önceliğin altına düşürülmez. Önceliği düşürmek, hesaplamaya bağlı iş
parçacıklarının CPU tüketimini sınırlama eğilimindedir . Bir bekleme işleminden
değişken öncelikli bir iş parçacığı serbest bırakıldığında, sevk programı önceliği
artırır. Destek miktarı, iş parçacığının ne beklediğine bağlıdır.
Örneğin, klavye G/ Ç'sini bekleyen bir iş parçacığı büyük bir artış elde ederken, disk
işlemi için bekleyen bir iş parçacığı orta düzeyde bir artış elde eder.
Bu strateji, fare ve pencereleri kullanan etkileşimli iş parçacıklarına iyi yanıt süreleri
verme eğilimindedir. Ayrıca, G/Ç'ye bağlı iş parçacıklarının, G/Ç aygıtlarını meşgul
etmesini sağlarken, hesaplamaya bağlı iş parçacıklarının arka planda yedek CPU
döngüleri kullanmasına izin verir . Bu strateji, UNIX dahil olmak üzere çeşitli işletim
sistemleri tarafından kullanılır . Ayrıca, kullanıcının şu anda etkileşimde olduğu pencere,
yanıt süresini iyileştirmek için bir öncelik artışı alır.
Bir kullanıcı etkileşimli bir program çalıştırdığında, sistemin özellikle iyi performans
sağlaması gerekir. Bu nedenle Windows'un NORMAL ÖNCELİK SINIFI'ndaki işlemler
için özel bir zamanlama kuralı vardır . Windows , ekranda seçili olan ön plan süreci ile
seçili olmayan arka plan süreci arasında ayrım yapar . Bir işlem ön plana geçtiğinde,
Windows zamanlama kuantumunu bir faktör kadar artırır - tipik olarak 3 oranında. Bu
artış, bir zaman paylaşımlı önalım gerçekleşmeden önce ön plan işleminin çalışması
için üç kat daha uzun süre verir.

Windows 7 , uygulamaların çekirdekten bağımsız olarak iş parçacıkları


oluşturmasına ve yönetmesine olanak tanıyan kullanıcı modu zamanlamayı (UMS)
tanıttı. Böylece, bir uygulama, Windows çekirdek zamanlayıcısını dahil etmeden birden
çok iş parçacığı oluşturabilir ve zamanlayabilir. Çok sayıda iş parçacığı oluşturan
uygulamalar için, hiçbir çekirdek müdahalesi gerekmediğinden, iş parçacıklarını
kullanıcı modunda zamanlamak, çekirdek modu iş parçacığı planlamasından çok daha ver
Windows'un önceki sürümleri, birkaç kullanıcı modu iş parçacığının (liflerin) tek ,
bir çekirdek iş parçacığına eşlenmesine izin veren , fiber olarak bilinen benzer bir
özellik sağlıyordu. Bununla birlikte, liflerin pratik kullanımı sınırlıydı. Bir fiber, tüm
fiberlerin üzerinde çalıştıkları iş parçacığının iş parçacığı ortam bloğunu (TEB)
paylaşması gerektiğinden Windows API'sine çağrı yapamadı . Bu, bir Windows API
işlevi TEB'e bir fiber için durum bilgisini yerleştirdiğinde , yalnızca bilgilerin üzerine
farklı bir fiber tarafından yazılması için bir sorun oluşturdu.
UMS , her kullanıcı modu iş parçacığını kendi iş parçacığı bağlamıyla sağlayarak bu engelin
üstesinden gelir.
Ayrıca, fiberlerin aksine UMS'nin doğrudan programcı tarafından kullanılması
amaçlanmamıştır. Kullanıcı modu zamanlayıcıları yazmanın ayrıntıları çok zor olabilir ve
UMS böyle bir zamanlayıcı içermez. Bunun yerine, zamanlayıcılar UMS'nin üzerine inşa
edilen programlama dili kitaplıklarından gelir . Örneğin Microsoft, C++ için görev
tabanlı paralellik için tasarlanmış eşzamanlı bir programlama çerçevesi olan Eşzamanlılık
Çalışma Zamanı (ConcRT) sağlar.
Machine Translated by Google

242 Bölüm 5 CPU Programlama

(Bölüm 4.2) çok çekirdekli işlemciler hakkında. ConcRT , programları görevlere


ayrıştırmak için olanaklarla birlikte bir kullanıcı modu zamanlayıcı sağlar ve bunlar
daha sonra mevcut işlem çekirdeklerinde programlanabilir.
Windows ayrıca, Bölüm 5.5'te açıklandığı gibi, bir iş parçacığının tercih edilen ve
en son işlemciyi korumayı da içeren, o iş parçacığı için en uygun işlem çekirdeğinde
bir iş parçacığı zamanlamaya çalışarak çok işlemcili sistemlerde zamanlamayı destekler.
Windows tarafından kullanılan bir teknik, mantıksal işlemci kümeleri ( SMT kümeleri
olarak bilinir ) oluşturmaktır. Hiper iş parçacıklı bir SMT sisteminde, aynı CPU
çekirdeğine ait donanım iş parçacıkları da aynı SMT kümesine ait olacaktır. Mantıksal
işlemciler 0'dan başlayarak numaralandırılır. Örnek olarak, çift iş parçacıklı/dört
çekirdekli bir sistem, dört SMT kümesinden oluşan sekiz mantıksal işlemci içerir: {0, 1},
{2, 3}, {4, 5} ve {6, 7}. Bölüm 5.5.4'te vurgulanan önbelleğe erişim cezalarından
kaçınmak için, zamanlayıcı aynı SMT seti içindeki mantıksal işlemciler üzerinde çalışan
bir iş parçacığını sürdürmeye çalışır.

Yükleri farklı mantıksal işlemciler arasında dağıtmak için, her iş parçacığına, iş


parçacığının tercih edilen işlemcisini temsil eden bir sayı olan ideal bir işlemci atanır.
Her işlem, o işleme ait bir iş parçacığı için ideal CPU'yu tanımlayan bir başlangıç tohum
değerine sahiptir . Bu tohum, bu işlem tarafından oluşturulan her yeni iş parçacığı
için artırılır, böylece yükü farklı mantıksal işlemciler arasında dağıtır. SMT sistemlerinde ,
bir sonraki ideal işlemci için artış, bir sonraki SMT setindedir . Örneğin, çift iş parçacıklı/
dört çekirdekli bir sistemde, belirli bir işlemdeki iş parçacıkları için ideal işlemciler 0, 2,
4, 6, 0, 2, ... olarak atanır. İlk iş parçacığının oluşturduğu durumdan kaçınmak için
her işlem için işlemci 0 atanır, işlemlere farklı tohum değerleri atanır, böylece iş
parçacıklarının yükü sistemdeki tüm fiziksel işlem çekirdeklerine dağıtılır. Örneğimize
yukarıdan devam edersek, ikinci bir işlem için tohum 1 olsaydı, ideal işlemciler 1, 3, 5,
7, 1, 3 ve benzeri sırayla atanırdı.

5.7.3 Örnek: Solaris Planlama Solaris, önceliğe

dayalı iş parçacığı planlamasını kullanır. Her iş parçacığı altı sınıftan birine aittir:

1. Zaman paylaşımı (TS)


2. Etkileşimli (IA)

3. Gerçek zamanlı (RT)

4. Sistem (SYS)
5. Adil paylaşım (FSS)

6. Sabit öncelik (FP)

Her sınıf içinde farklı öncelikler ve farklı zamanlama algoritmaları vardır.

Bir süreç için varsayılan zamanlama sınıfı zaman paylaşımıdır. Zaman paylaşımlı
sınıf için zamanlama ilkesi, dinamik olarak öncelikleri değiştirir ve çok düzeyli bir geri
bildirim kuyruğu kullanarak farklı uzunluklarda zaman dilimleri atar. Varsayılan olarak,
öncelikler ve zaman dilimleri arasında ters bir ilişki vardır. daha yüksek
Machine Translated by Google

5.7 İşletim Sistemi Örnekleri 243

zaman

kuantumunun

öncelik zaman kuantumu süresi doldu uykudan dönüş

0 200 0 50

5 200 0 50

10 160 0 51

15 160 5 51

20 120 10 52

25 120 15 52

30 80 20 53

35 80 25 54

40 40 30 55

45 40 35 56

50 40 40 58

55 40 45 58

59 20 49 59

Şekil 5.29 Zaman paylaşımlı ve etkileşimli iş parçacıkları için Solaris gönderme tablosu.

öncelik, zaman dilimi ne kadar küçükse; ve öncelik ne kadar düşükse, zaman dilimi de o kadar
büyük olur. Etkileşimli süreçler tipik olarak daha yüksek bir önceliğe sahiptir; CPU'ya bağlı
işlemler, daha düşük bir öncelik. Bu zamanlama ilkesi, etkileşimli işlemler için iyi yanıt süresi ve
CPU'ya bağlı işlemler için iyi verim sağlar. Etkileşimli sınıf, zaman paylaşımlı sınıfla aynı
zamanlama politikasını kullanır, ancak KDE veya GNOME pencere yöneticileri tarafından
oluşturulanlar gibi pencereleme uygulamalarına daha iyi performans için daha yüksek bir
öncelik verir.
Şekil 5.29, zaman paylaşımı ve etkileşimli iş parçacıklarının zamanlanması için basitleştirilmiş
sevk tablosunu gösterir. Bu iki zamanlama sınıfı, 60 öncelik seviyesi içerir, ancak kısaca, sadece
bir avuç görüntülüyoruz. (Solaris sisteminde veya sanal makinede tam gönderim tablosunu
görmek için dispadmin -c TS -g'yi çalıştırın . ) Şekil 5.29'da gösterilen gönderim tablosu
aşağıdaki alanları içerir:

• Öncelik. Zaman paylaşımı ve etkileşim için sınıfa bağlı öncelik


sınıflar. Daha yüksek bir sayı, daha yüksek bir önceliği gösterir.

• Zaman kuantumu. İlişkili öncelik için zaman kuantumu. Bu, öncelikler ve zaman niceliği
arasındaki ters ilişkiyi gösterir: en düşük öncelik (öncelik 0) en yüksek zaman kuantumuna
(200 milisaniye) sahiptir ve en yüksek öncelik (öncelik 59) en düşük zaman kuantumuna
(20 milisaniye) sahiptir.

• Zaman kuantumunun süresi doldu. Tüm zaman kuantumunu bloke etmeden kullanan bir iş
parçacığının yeni önceliği. Bu tür iş parçacıkları CPU yoğun olarak kabul edilir. Tabloda
gösterildiği gibi, bu iş parçacıklarının öncelikleri azaltılmıştır.
Machine Translated by Google

244 Bölüm 5 CPU Programlama

• Uykudan dönüş. Uykudan dönen bir iş parçacığının önceliği (örneğin, G/Ç'yi


beklemekten). Tabloda gösterildiği gibi, bekleyen bir iş parçacığı için G/Ç mevcut
olduğunda, önceliği 50 ile 59 arasına yükseltilir ve etkileşimli işlemler için iyi yanıt
süresi sağlamaya yönelik zamanlama politikasını destekler.

Gerçek zamanlı sınıftaki iş parçacıklarına en yüksek öncelik verilir. Gerçek zamanlı


bir süreç, başka herhangi bir sınıftaki bir süreçten önce çalışacaktır. Bu atama, gerçek
zamanlı bir sürecin, sınırlı bir süre içinde sistemden garantili bir yanıt almasına izin verir.
Ancak genel olarak, gerçek zamanlı sınıfa ait çok az süreç vardır.

Solaris, zamanlayıcı ve sayfalama arka plan programı gibi çekirdek iş parçacıklarını


çalıştırmak için sistem sınıfını kullanır. Bir sistem iş parçacığının önceliği belirlendikten
sonra değişmez. Sistem sınıfı, çekirdek kullanımı için ayrılmıştır (çekirdek modunda
çalışan kullanıcı işlemleri, sistem sınıfında değildir).
Sabit öncelikli ve adil paylaşım sınıfları Solaris 9 ile tanıtıldı.
Sabit öncelikli sınıftaki iş parçacıkları, zaman paylaşımlı sınıftakilerle aynı öncelik
aralığına sahiptir; ancak öncelikleri dinamik olarak ayarlanmaz.
Fair-share sınıfı, zamanlama kararları vermek için öncelikler yerine CPU paylaşımlarını
kullanır. CPU paylaşımları, mevcut CPU kaynaklarına ilişkin yetkiyi gösterir ve
bir dizi sürece tahsis edilir ( proje olarak bilinir).
Her zamanlama sınıfı bir dizi öncelik içerir. Ancak, zamanlayıcı sınıfa özel öncelikleri
global önceliklere dönüştürür ve çalıştırılacak en yüksek global önceliğe sahip iş
parçacığını seçer. Seçilen iş parçacığı (1) bloke edene, (2) kendi zaman dilimini
kullanana veya (3) daha yüksek öncelikli bir iş parçacığı tarafından öncelenene kadar
CPU üzerinde çalışır. Aynı önceliğe sahip birden çok iş parçacığı varsa, zamanlayıcı bir
döngüsel sıra kullanır. Şekil 5.30, altı çizelgeleme sınıfının birbiriyle nasıl ilişkili olduğunu
ve bunların küresel önceliklerle nasıl eşleştiğini göstermektedir. Çekirdeğin servis
kesintileri için on iş parçacığı tuttuğuna dikkat edin. Bu iş parçacıkları herhangi bir
zamanlama sınıfına ait değildir ve en yüksek öncelikte (160–169) yürütülür.
Belirtildiği gibi, Solaris geleneksel olarak çoktan çoğa modeli kullanmıştır (Kısım 4.3.3),
ancak Solaris 9 ile başlayarak bire bir modele (Kısım 4.3.2) geçmiştir.

5.8 Algoritma Değerlendirmesi

Belirli bir sistem için bir CPU zamanlama algoritmasını nasıl seçeriz? Bölüm 5.3'te
gördüğümüz gibi, her biri kendi parametrelerine sahip birçok çizelgeleme algoritması
vardır. Sonuç olarak, bir algoritma seçmek zor olabilir.
İlk problem, bir algoritma seçiminde kullanılacak kriterleri tanımlamaktır. Bölüm
5.2'de gördüğümüz gibi, kriterler genellikle CPU kullanımı, yanıt süresi veya verim
açısından tanımlanır. Bir algoritma seçmek için önce bu elemanların göreceli önemini
tanımlamamız gerekir. Kriterlerimiz aşağıdakiler gibi çeşitli önlemleri içerebilir:

• Maksimum yanıt süresinin 300 milisaniye olduğu kısıtlaması altında CPU kullanımını
maksimize etme
5.8 Algoritma Değerlendirmesi 245
Machine Translated by Google

küresel zamanlama
öncelik sırası

169
en yüksek ilk
konuları kesmek
160
159

gerçek zamanlı (RT) iş parçacıkları

100
99

sistem (SYS) iş parçacıkları

60
59
adil paylaşım (FSS) konuları

sabit öncelikli (FX) iş parçacıkları

devre mülk (TS) konuları

etkileşimli (IA) diziler


en düşük 0 geçen

Şekil 5.30 Solaris zamanlaması.

• Geri dönüş süresinin (ortalama olarak) toplam yürütme süresiyle doğrusal orantılı
olduğu şekilde verimi en üst düzeye çıkarmak

Seçim kriterleri tanımlandıktan sonra, ele alınan algoritmaları değerlendirmek


istiyoruz. Daha sonra çeşitli değerlendirme yöntemlerini açıklayacağız
kullanabiliriz.

5.8.1 Deterministik Modelleme


Değerlendirme yöntemlerinin ana sınıflarından biri analitik değerlendirmedir.
Analitik değerlendirme, bu iş yükü için algoritmanın performansını değerlendirmek
üzere bir formül veya sayı üretmek için verilen algoritmayı ve sistem iş yükünü kullanır.
Deterministik modelleme , bir tür analitik değerlendirmedir. Bu yöntem, önceden
belirlenmiş belirli bir iş yükünü alır ve bu iş yükü için her bir algoritmanın performansını
tanımlar. Örneğin, aşağıda gösterilen iş yüküne sahip olduğumuzu varsayalım. Beş
işlemin tümü, verilen sıraya göre, milisaniye cinsinden verilen CPU patlamasının
uzunluğu ile 0 zamanında gelir :
246 Bölüm 5 CPU Programlama
Machine Translated by Google
İşlem Patlama Süresi

P1 10
P2 29
P3 3
P4 7
P5 12

Bu süreç kümesi için FCFS, SJF ve RR (kuantum = 10 milisaniye) zamanlama


algoritmalarını düşünün. Hangi algoritma minimum verir
ortalama bekleme süresi?
FCFS algoritması için süreçleri şu şekilde yürütürüz:

P1 P2 P3 P4 P5
0 10 39 42 49 61

Bekleme süresi P1 prosesi için 0 milisaniye, proses için 10 milisaniyedir.


P2, P3 işlemi için 39 milisaniye , P4 işlemi için 42 milisaniye ve 49
P5 işlemi için milisaniye . Böylece ortalama bekleme süresi (0 + 10 + 39 +
42 + 49)/5 = 28 milisaniye.
Önleyici olmayan SJF çizelgeleme ile süreçleri şu şekilde yürütürüz :

P3 P4 P1 P5 P2
03 10 20 32 61

Bekleme süresi P1 prosesi için 10 milisaniye, proses için 32 milisaniyedir.


P2, P3 işlemi için 0 milisaniye , P4 işlemi için 3 milisaniye ve P5 işlemi için 20
milisaniye . Böylece ortalama bekleme süresi (10 + 32 + 0 + 3 + 20)/5
= 13 milisaniye.
RR algoritması ile süreçleri şu şekilde yürütüyoruz:

P1 P2 P3 P4 P5 P2 P5 P2
0 10 20 23 30 40 50 52 61

Bekleme süresi P1 prosesi için 0 milisaniye, proses için 32 milisaniyedir.


P2, P3 işlemi için 20 milisaniye , P4 işlemi için 23 milisaniye ve 40
P5 işlemi için milisaniye . Böylece ortalama bekleme süresi (0 + 32 + 20 +
23 + 40)/5 = 23 milisaniye.
Bu durumda SJF ile elde edilen ortalama bekleme süresinin
politika, FCFS zamanlaması ile elde edilenin yarısından azdır; RR algoritması _
bize bir ara değer verir.
Deterministik modelleme basit ve hızlıdır. Bize kesin sayıları verir, algoritmaları
karşılaştırmamızı sağlar. Ancak, giriş için kesin sayılar gerektirir,
ve cevapları sadece bu durumlar için geçerlidir. Deterministiğin ana kullanımları
modelleme, zamanlama algoritmalarını tanımlamada ve örnekler sağlamadadır.
Aynı programı tekrar tekrar çalıştırdığımız ve
5.8 Algoritma Değerlendirmesi 247
Machine Translated by Google

programın işlem gereksinimlerini tam olarak ölçün, bir zamanlama algoritması


seçmek için deterministik modellemeyi kullanabiliriz. Ayrıca, bir dizi örnek üzerinden,
deterministik modelleme, daha sonra ayrı ayrı analiz edilebilecek ve kanıtlanabilecek
eğilimleri gösterebilir. Örneğin, açıklanan ortam için (tüm süreçler ve bunların
zamanları 0 zamanında kullanılabilir), SJF politikasının her zaman minimum bekleme
süresiyle sonuçlanacağı gösterilebilir.

5.8.2 Kuyruk Modelleri Birçok

sistemde, yürütülen süreçler günden güne değişir, bu nedenle deterministik


modelleme için kullanılacak statik bir süreç (veya zaman) seti yoktur. Ancak
belirlenebilecek olan, CPU ve G/Ç patlamalarının dağılımıdır. Bu dağılımlar
ölçülebilir ve daha sonra yaklaşık olarak veya basitçe tahmin edilebilir. Sonuç, belirli
bir CPU patlamasının olasılığını tanımlayan matematiksel bir formüldür . Genellikle
bu dağılım üsteldir ve ortalaması ile tanımlanır.
Benzer şekilde, süreçlerin sisteme geldiği zamanların dağılımını (varış zamanı
dağılımı) tanımlayabiliriz. Bu iki dağıtımdan, çoğu algoritma için ortalama çıktı,
kullanım, bekleme süresi vb. hesaplamak mümkündür.

Bilgisayar sistemi, bir sunucu ağı olarak tanımlanır. Her sunucunun bir bekleme
süreci kuyruğu vardır. CPU , cihaz kuyruklarıyla G/Ç sistemi gibi hazır kuyruğu olan
bir sunucudur . Varış oranlarını ve hizmet oranlarını bilerek, kullanımı, ortalama
kuyruk uzunluğunu, ortalama bekleme süresini vb. hesaplayabiliriz.
Bu çalışma alanına kuyruklama-ağ analizi denir .
Örnek olarak, n ortalama uzun vadeli kuyruk uzunluğu (hizmet verilen süreç
hariç), W kuyrukta ortalama bekleme süresi olsun ve λ kuyruktaki yeni süreçler için
ortalama varış oranı (örn. saniyede üç işlem). Bir sürecin beklediği W süresi
boyunca , λ × W yeni süreçlerin kuyruğa gelmesini bekliyoruz. Sistem kararlı
durumdaysa, kuyruktan çıkan işlemlerin sayısı gelen işlemlerin sayısına eşit olmalıdır.
Böylece,

n = λ × W.

Little formülü olarak bilinen bu denklem, herhangi bir çizelgeleme algoritması ve


varış dağılımı için geçerli olduğu için özellikle yararlıdır. Örneğin n , bir
mağazadaki müşteri sayısı olabilir.
Diğer ikisini biliyorsak, üç değişkenden birini hesaplamak için Little formülünü
kullanabiliriz. Örneğin, her saniyede (ortalama olarak) 7 işlemin geldiğini ve
kuyrukta normalde 14 işlem olduğunu biliyorsak, işlem başına ortalama bekleme
süresini 2 saniye olarak hesaplayabiliriz.
Kuyruk analizi, zamanlama algoritmalarını karşılaştırmada faydalı olabilir, ancak
aynı zamanda sınırlamaları da vardır. Şu anda, ele alınabilecek algoritma sınıfları ve
dağılımlar oldukça sınırlıdır. Karmaşık algoritmaların ve dağılımların matematiğiyle
çalışmak zor olabilir. Bu nedenle, varış ve hizmet dağılımları genellikle matematiksel
olarak izlenebilir - ancak gerçekçi olmayan - şekillerde tanımlanır. Ayrıca, genellikle
doğru olmayabilecek bir dizi bağımsız varsayımda bulunmak da gereklidir. Bu
zorlukların bir sonucu olarak, kuyruğa alma modelleri genellikle sadece gerçek
sistemlerin yaklaşık değerleridir ve hesaplanan sonuçların doğruluğu sorgulanabilir.
Machine Translated by Google

248 Bölüm 5 CPU Programlama

5.8.3 Simülasyonlar

Zamanlama algoritmalarının daha doğru bir değerlendirmesini elde etmek için


simülasyonları kullanabiliriz. Çalışan simülasyonlar, bilgisayar sisteminin bir
modelinin programlanmasını içerir. Yazılım veri yapıları, sistemin ana bileşenlerini
temsil eder. Simülatörün bir saati temsil eden bir değişkeni vardır. Bu değişkenin
değeri arttıkça, simülatör sistem durumunu cihazların, süreçlerin ve planlayıcının
aktivitelerini yansıtacak şekilde değiştirir. Simülasyon yürütülürken, algoritma
performansını gösteren istatistikler toplanır ve yazdırılır.
Simülasyonu sürdürecek veriler birkaç yolla oluşturulabilir. En yaygın yöntem,
olasılık dağılımlarına göre süreçler, CPU patlama süreleri, varışlar, çıkışlar vb.
oluşturmak üzere programlanmış bir rasgele sayı üreteci kullanır. Dağılımlar
matematiksel (tek biçimli, üstel, Poisson) veya ampirik olarak tanımlanabilir. Bir
dağılım ampirik olarak tanımlanacaksa, incelenen gerçek sistemin ölçümleri alınır.
Sonuçlar, gerçek sistemdeki olayların dağılımını tanımlar; bu dağıtım daha sonra
simülasyonu yürütmek için kullanılabilir.

Bununla birlikte, gerçek sistemdeki ardışık olaylar arasındaki ilişkiler nedeniyle


dağıtım odaklı bir simülasyon yanlış olabilir. Sıklık dağılımı, yalnızca her olayın kaç
örneğinin gerçekleştiğini gösterir; bunların oluşum sırası hakkında hiçbir şey
göstermez. Bu sorunu düzeltmek için izleme dosyalarını kullanabiliriz. Gerçek
sistemi izleyerek ve gerçekleşen olayların sırasını kaydederek bir iz oluşturuyoruz
(Şekil 5.31). Daha sonra simülasyonu yürütmek için bu diziyi kullanırız. İzleme
dosyaları, tam olarak aynı gerçek girdiler kümesinde iki algoritmayı karşılaştırmak
için mükemmel bir yol sağlar. Bu yöntem girdileri için doğru sonuçlar üretebilir.

Simülasyonlar pahalı olabilir ve genellikle saatlerce bilgisayar zamanı gerektirir.


Daha ayrıntılı bir simülasyon daha doğru sonuçlar sağlar, ancak aynı zamanda

FCFS için
simülasyon performans
istatistikleri
FCFS

•••

CPU 10
G/Ç 213
gerçek CPU 12 SJF için
süreç G/Ç 112 simülasyon performans
yürütme CPU 2 istatistikleri
G/Ç 147
SJF
işlemci 173
•••

iz bandı

RR için
simülasyon performans
istatistikleri (q = 14)
RR (q = 14)

Şekil 5.31 CPU zamanlayıcılarının simülasyonla değerlendirilmesi.


Machine Translated by Google

5.8 Algoritma Değerlendirmesi 249

daha fazla bilgisayar zamanı alır. Ek olarak, izleme dosyaları büyük miktarda depolama
alanı gerektirebilir. Son olarak, simülatörün tasarımı, kodlaması ve hata ayıklaması
önemli bir görev olabilir.

5.8.4 Uygulama

Bir simülasyon bile sınırlı doğruluktadır. Bir çizelgeleme algoritmasını değerlendirmenin


tamamen doğru tek yolu, onu kodlamak, işletim sistemine yerleştirmek ve nasıl
çalıştığını görmektir. Bu yaklaşım, gerçek çalışma koşulları altında değerlendirme için
gerçek algoritmayı gerçek sisteme yerleştirir.
Bu yöntem masrafsız değildir. Algoritmayı kodlamak ve işletim sistemini (gerekli
veri yapılarıyla birlikte) desteklemek için değiştirmek için masraf yapılır. Ayrıca,
değişiklikleri özel donanım yerine genellikle sanal makinelerde test etmenin de bir
maliyeti vardır. Regresyon testi , değişikliklerin hiçbir şeyi daha da kötüleştirmediğini
ve yeni hatalara neden olmadığını veya eski hataların yeniden yaratılmasına neden
olmadığını (örneğin, değiştirilen algoritmanın bazı hataları çözmesi ve değiştirmenin
bu hatanın yeniden oluşmasına neden olması nedeniyle) firmayı ikna eder.
Diğer bir zorluk ise algoritmanın kullanıldığı ortamın değişmesidir. Ortam, yalnızca
yeni programlar yazıldıkça ve sorun türleri değiştikçe olağan şekilde değil, aynı
zamanda zamanlayıcının performansının bir sonucu olarak da değişecektir. Kısa
süreçlere öncelik verilirse, kullanıcılar daha büyük süreçleri daha küçük süreç kümelerine
bölebilir. Etkileşimli işlemlere etkileşimli olmayan işlemlere göre öncelik verilirse,
kullanıcılar etkileşimli kullanıma geçebilir. Bu sorun genellikle, eylemlerin tamamını
kapsayan araçlar veya komut dosyaları kullanılarak, bu araçları tekrar tekrar kullanarak
ve sonuçları ölçerken (ve yeni ortamda neden oldukları sorunları tespit ederken) bu
araçları kullanarak giderilir.

Elbette insan veya program davranışı, zamanlama algoritmalarını atlatmaya


çalışabilir. Örneğin, araştırmacılar, terminal G/Ç miktarına bakarak etkileşimli ve
etkileşimli olmayan süreçleri otomatik olarak sınıflandıran bir sistem tasarladılar . Bir
işlem 1 saniyelik aralıklarla terminale giriş veya çıkış yapmadıysa, işlem etkileşimsiz
olarak sınıflandırılır ve daha düşük öncelikli bir kuyruğa taşınır. Bu politikaya yanıt
olarak, bir programcı programlarını 1 saniyeden daha az düzenli aralıklarla terminale
rastgele bir karakter yazacak şekilde değiştirdi. Sistem, terminal çıktısı tamamen
anlamsız olmasına rağmen programlarına yüksek öncelik verdi.

Genel olarak, en esnek zamanlama algoritmaları, sistem yöneticileri veya kullanıcılar


tarafından belirli bir uygulama veya uygulama kümesi için ayarlanabilmeleri için
değiştirilebilen algoritmalardır. Örneğin, üst düzey grafik uygulamaları gerçekleştiren
bir iş istasyonu, bir web sunucusu veya dosya sunucusundan farklı zamanlama
gereksinimlerine sahip olabilir. Bazı işletim sistemleri, özellikle UNIX'in çeşitli sürümleri ,
sistem yöneticisinin belirli bir sistem yapılandırması için zamanlama parametrelerinde
ince ayar yapmasına izin verir. Örneğin Solaris , sistem yöneticisinin Bölüm 5.7.3'te
açıklanan zamanlama sınıflarının parametrelerini değiştirmesine izin vermek için
dispadmin komutunu sağlar.
Başka bir yaklaşım, bir işlemin veya iş parçacığının önceliğini değiştirebilen
API'leri kullanmaktır. Java, POSIX ve Windows API'leri bu tür işlevleri sağlar. Bu yaklaşımın
dezavantajı, bir sistem veya uygulamanın performans ayarının çoğu zaman daha genel
durumlarda performansın artmasıyla sonuçlanmamasıdır.
250 Bölüm 5 CPU Programlama
Machine Translated by Google

5.9 Özet
• CPU çizelgeleme, hazır kuyruktan bir bekleyen işlemin seçilmesi ve CPU'nun buna tahsis
edilmesi görevidir. CPU , dağıtıcı tarafından seçilen sürece tahsis edilir.

• Programlama algoritmaları, önleyici ( bir işlemden CPU'nun alınabileceği) veya önleyici


olmayan (bir işlemin gönüllü olarak CPU'nun denetiminden vazgeçmesi gerektiği)
olabilir. Hemen hemen tüm modern işletim sistemleri önleyicidir.

• Programlama algoritmaları aşağıdaki beş kritere göre değerlendirilebilir: (1) CPU


kullanımı, (2) verim, (3) geri dönüş süresi, (4) bekleme süresi ve (5) yanıt süresi.

• İlk gelen, ilk hizmet alır (FCFS) zamanlaması en basit zamanlama algoritmasıdır, ancak
kısa süreçlerin çok uzun süreçler için beklemesine neden olabilir.

• Önce en kısa iş (SJF) planlaması, en kısa ortalama bekleme süresini sağlayarak,


kanıtlanabilir şekilde optimaldir. Bununla birlikte, SJF zamanlamasını uygulamak zordur,
çünkü bir sonraki CPU patlamasının uzunluğunu tahmin etmek zordur.

• Round-robin (RR) zamanlama, CPU'yu bir zaman kuantumu için her işleme tahsis eder .
Süreç, zaman kuantumu sona ermeden önce CPU'dan vazgeçmezse, süreç öncelenir ve
bir zaman kuantumu için başka bir süreç çalışacak şekilde programlanır.

• Öncelik zamanlaması, her işleme bir öncelik atar ve CPU , en yüksek önceliğe sahip sürece
tahsis edilir. Aynı önceliğe sahip işlemler, FCFS sırasına göre veya RR planlaması
kullanılarak programlanabilir. • Çok düzeyli kuyruk zamanlama, işlemleri önceliğe göre

düzenlenmiş birkaç ayrı kuyruğa böler ve zamanlayıcı, süreçleri en yüksek öncelikli kuyrukta
yürütür. Her kuyrukta farklı zamanlama algoritmaları kullanılabilir.

• Çok düzeyli geri bildirim kuyrukları, bir işlemin farklı kuyruklar arasında geçiş yapabilmesi
dışında çok düzeyli kuyruklara benzer. • Çok çekirdekli işlemciler , aynı fiziksel çip üzerine

bir veya daha fazla CPU yerleştirir ve her CPU'nun birden fazla donanım iş parçacığı olabilir.
İşletim sistemi açısından bakıldığında, her bir donanım iş parçacığı mantıksal bir CPU
gibi görünür.

• Çok çekirdekli sistemlerde yük dengeleme, CPU çekirdekleri arasındaki yükleri eşitler,
ancak çekirdekler arasında yükleri dengelemek için geçiş yapmak önbellek içeriğini
geçersiz kılabilir ve bu nedenle bellek erişim sürelerini artırabilir. • Yumuşak gerçek

zamanlı zamanlama, gerçek zamanlı görevlere gerçek zamanlı olmayan görevlere göre
öncelik verir. Zor gerçek zamanlı zamanlama, gerçek zamanlı görevler için zamanlama
garantileri sağlar,

• Oran-monotonik gerçek zamanlı zamanlama, periyodik görevleri bir


Öncelikli statik öncelik politikası.
Alıştırmalar 251
Machine Translated by Google

• En erken son teslim tarihi (EDF) zamanlaması, öncelikleri aşağıdakilere göre atar:
son tarih. Son teslim tarihi ne kadar erken olursa, öncelik o kadar yüksek olur; daha sonra
son tarih, öncelik o kadar düşük.

• Orantılı paylaşım planlaması , tüm uygulamalar arasında T payı tahsis eder. Eğer
bir uygulamaya N zaman payı tahsis edilir, N T'ye sahip olması sağlanır .
toplam işlemci süresi

• Linux , bir orantı atayan tamamen adil zamanlayıcıyı (CFS) kullanır.


Her görev için CPU işleme süresi. Oran, sanal
her görevle ilişkili çalışma zamanı (vruntime) değeri.

• Windows zamanlaması, iş parçacığı zamanlamasının sırasını belirlemek için


önleyici, 32 seviyeli bir öncelik şeması kullanır.

• Solaris, global bir sistemle eşlenen altı benzersiz zamanlama sınıfını tanımlar.
öncelik. CPU yoğun iş parçacıklarına genellikle daha düşük öncelikler atanır
(ve daha uzun zaman kuantumları) ve G/Ç'ye bağlı iş parçacıkları genellikle atanır
daha yüksek öncelikler (daha kısa zaman kuantumlarıyla.)

• Bir CPU programlama algoritmasını değerlendirmek için modelleme ve simülasyonlar kullanılabilir


ritim.

Alıştırmalar

5.1 Bir CPU zamanlama algoritması, işleyişinin yürütülmesi için bir sıra belirler.
zamanlanmış süreçler. Bir işlemde programlanacak n işlem verildiğinde veya
kaç farklı çizelgeleme mümkündür? terimlerle bir formül verin
n.

5.2 Önleyici ve önleyici olmayan çizelge arasındaki farkı açıklayın


ing.

5.3 Farzedelim ki, aşağıdaki süreçler zaman zaman yürütülmek üzere geliyor:
belirtilen. Her işlem listelenen süre boyunca çalışacaktır. Soruları cevaplarken,
önleyici olmayan zamanlama kullanın ve tüm kararları temel alın.
o anda sahip olduğunuz bilgilere göre karar verilmelidir.

İşlem Varış zamanı Patlama Süresi

P1 0.0 8
P2 0.4 4
P3 1.0 1

a. Bu süreçler için ortalama geri dönüş süresi nedir?


FCFS zamanlama algoritması?

b. Bu süreçler için ortalama geri dönüş süresi nedir?


SJF zamanlama algoritması?

c. SJF algoritmasının performansı iyileştirmesi gerekiyordu, ancak dikkat edin


bilmediğimiz için P1 sürecini 0 zamanında çalıştırmayı seçtiğimizi
iki daha kısa sürecin yakında geleceğini söyledi. ne olduğunu hesapla
252 Bölüm 5 CPU Programlama
Machine Translated by Google

CPU ilk kez boşta bırakılırsa ortalama geri dönüş süresi olacaktır
1 birim ve ardından SJF zamanlaması kullanılır. Bu süreçleri unutmayın
P1 ve P2 bu bekleme süresi boyunca bekliyorlar, dolayısıyla bekleme süreleri
artırabilir. Bu algoritma gelecek bilgisi olarak bilinebilir.
zamanlama.

5.4 CPU patlamasının uzunluğuyla birlikte aşağıdaki süreç dizisini göz önünde bulundurun.
milisaniye cinsinden verilen süre:

İşlem Patlama Süresi Öncelik


P1 2 2
P2 1 1
P3 8 4
P4 4 2
P5 5 3

Proseslerin P1, P2, P3, P4, P5, P1, P2, P3, P4, P5,
hepsi 0 zamanında.

a. Aşağıdaki zamanlama algoritmalarını kullanarak bu süreçlerin yürütülmesini


gösteren dört Gantt şeması çizin: FCFS, SJF, önleyici olmayan öncelik (daha
büyük bir öncelik numarası, daha yüksek bir öncelik anlamına gelir).
öncelik) ve RR (kuantum = 2).

b. Her bir sürecin geri dönüş süresi nedir?


a bölümündeki zamanlama algoritmaları?

c. Bu çizelgeleme algoritmalarının her biri için her bir sürecin bekleme süresi nedir?

d. Algoritmalardan hangisi minimum ortalama bekleme ile sonuçlanır?


zaman (tüm süreçlerde)?

5.5 Aşağıdaki işlemler, önleyici, döngüsel bir zamanlama algoritması kullanılarak


programlanmaktadır.

İşlem Öncelik Patlamak Varış

P1 40 30 20 0
P2 30 35 25 25
P3 5 10 25 30
P4 15 60
P5 10 100
P6 10 105

Her sürece sayısal bir öncelik atanır ve daha yüksek bir sayı, daha yüksek bir göreli
önceliği belirtir. Aşağıda listelenen işlemlere ek olarak,
sistemin ayrıca boşta bir görevi vardır (bu, hiçbir CPU kaynağı tüketmez ve
Pidle olarak tanımlanır ). Bu görevin önceliği 0'dır ve sistemde çalıştırılacak başka bir
işlem olmadığında zamanlanır. uzunluğu
Alıştırmalar 253
Machine Translated by Google

zaman kuantumu 10 birimdir. Bir işlem, daha yüksek öncelikli bir işlem tarafından
öncelenirse, önceden alınan işlem kuyruğun sonuna yerleştirilir.

a. Bir Gantt şeması kullanarak süreçlerin zamanlama sırasını gösterin. b. Her bir

süreç için geri dönüş süresi nedir? c. Her işlem için bekleme süresi nedir?

d. CPU kullanım oranı nedir ?

5.6 Çok seviyeli bir kuyruk sisteminin farklı seviyelerinde farklı zaman-kuantum boyutlarına
sahip olmanın ne avantajı vardır?

5.7 Birçok CPU programlama algoritması parametrelendirilir. Örneğin, RR algoritması,


zaman dilimini belirtmek için bir parametre gerektirir. Çok düzeyli geri bildirim
kuyrukları, kuyruk sayısını, her kuyruk için zamanlama algoritmalarını, süreçleri
kuyruklar arasında taşımak için kullanılan kriterleri vb. tanımlamak için parametreler
gerektirir.
Bu algoritmalar bu nedenle gerçekten algoritma kümeleridir (örneğin, tüm zaman
dilimleri için RR algoritmaları kümesi vb.). Bir dizi algoritma, bir diğerini içerebilir
(örneğin, FCFS algoritması, sonsuz zaman kuantumlu RR algoritmasıdır). Aşağıdaki
algoritma seti çiftleri arasında (eğer varsa) nasıl bir ilişki vardır?

a. Öncelik ve SJF b. Çok

düzeyli geri bildirim kuyrukları ve FCFS c. Öncelik

ve FCFS d. RR ve SJF

5.8 Bir CPU zamanlama algoritmasının yakın geçmişte en az işlemci zamanını kullanan
süreçleri desteklediğini varsayalım . Bu algoritma neden G/Ç'ye bağlı programları
tercih edecek ve yine de CPU'ya bağlı programları kalıcı olarak aç bırakmayacak?

5.9 PCS ve SCS zamanlamasını ayırt edin.

5.10 Geleneksel UNIX zamanlayıcı, öncelik numaraları ve öncelikler arasında ters bir ilişki
kurar: sayı ne kadar yüksekse, öncelik o kadar düşük olur. Zamanlayıcı, aşağıdaki
işlevi kullanarak işlem önceliklerini saniyede bir kez yeniden hesaplar:

Öncelik = (son CPU kullanımı / 2) + taban

burada taban = 60 ve son CPU kullanımı , önceliklerin en son yeniden hesaplanmasından


bu yana bir işlemin CPU'yu ne sıklıkta kullandığını gösteren bir değeri ifade eder .
P1 işlemi için son CPU kullanımının 40, P2 işlemi için 18 ve P3 işlemi için 10
olduğunu varsayın . Öncelikler yeniden hesaplandığında bu üç işlem için yeni
öncelikler ne olacak? Bu bilgilere dayanarak, geleneksel UNIX zamanlayıcısı, CPU'ya
bağlı bir işlemin göreli önceliğini yükseltir mi yoksa düşürür mü?
Machine Translated by Google

254 Bölüm 5 CPU Programlama

Daha fazla okuma

UNIX FreeBSD 5.2'de kullanılan zamanlama ilkeleri [McKusick et al. (2015)]; Linux
CFS zamanlayıcısı, https://www.ibm.com/developerworks/library/l-completely-
fair-scheduler/ adresinde daha ayrıntılı olarak açıklanmıştır.
Solaris zamanlaması [Mauro ve McDougall (2007)] tarafından açıklanmıştır. [Rus
novich et al. (2017)], Windows dahili bileşenlerinde zamanlamayı tartışır. [Butenhof
(1997)] ve [Lewis ve Berg (1998)], Pthreads sistemlerinde zamanlamayı açıklar.
Çok çekirdekli zamanlama [McNairy ve Bhatia (2005)], [Kongetira et al. (2005)] ve
[Siddha et al. (2007)].

bibliyografya

[Butenhof (1997)] D. Butenhof, POSIX İş Parçacıkları ile Programlama, Addison


Wesley (1997).

[Kongetira et al. (2005)] P. Kongetira, K. Aingaran ve K. Olukotun, “Niagara: A 32-Way


Multithreaded SPARC Processor”, IEEE Micro Magazine, Cilt 25, Sayı 2 (2005), sayfa
21-29.

[Lewis ve Berg (1998)] B. Lewis ve D. Berg, Multithreaded Programming with


Pthreads, Sun Microsystems Press (1998).

[Mauro ve McDougall (2007)] J. Mauro ve R. McDougall, Solaris Internals:


Çekirdek Çekirdek Mimarisi, Prentice Hall (2007).

[McKusick et al. (2015)] MK McKusick, GV Neville-Neil ve RNM Wat son, The Design and
Implementation of the FreeBSD UNIX İşletim Sistemi –İkinci Baskı, Pearson (2015).

[McNairy ve Bhatia (2005)] C. McNairy ve R. Bhatia, “Montecito: A Dual– Core, Dual-


Threaded Itanium Processor”, IEEE Micro Magazine, Cilt 25, Sayı 2 (2005), sayfa 10–20.

[Russinovich et al. (2017)] M. Russinovich, DA Solomon ve A. Ionescu, Win


dows Internals –Bölüm 1, Yedinci Baskı, Microsoft Press (2017).

[Siddha et al. (2007)] S. Siddha, V. Pallipadi ve A. Mallick, “Process Schedul ing Challenges
in the Era of Multi-Core Processors”, Intel Technology Journal, Cilt 11, Sayı 4 (2007).
Egzersizler EX-12
Machine Translated by Google
Bölüm 5 Alıştırmalar

5.11 Bu iki program türünden:


a. G/Ç'ye bağlı
b. CPU'ya bağlı

hangisinin gönüllü bağlam geçişlerine sahip olma olasılığı daha yüksektir ve


hangisinin gönüllü olmayan bağlam geçişlerine sahip olma olasılığı daha yüksektir? açı
Cevap.

5.12 Aşağıdaki çizelgeleme kriteri çiftlerinin belirli durumlarda nasıl çatıştığını tartışın.
ayarlar.

a. CPU kullanımı ve yanıt süresi

b. Ortalama geri dönüş süresi ve maksimum bekleme süresi


c. G/Ç cihaz kullanımı ve CPU kullanımı

5.13 CPU zamanını tahsis etmek için kullanılan piyango biletleri süreçleri atayarak
piyango çizelgeleme çalışmalarını uygulamak için bir teknik . Bir zamanlama
kararı verilmesi gerektiğinde, rastgele bir piyango bileti seçilir ve bu bileti tutan
süreç CPU'yu alır. BTV işletim sistemi, her piyango kazananının 20 milisaniye CPU
zamanı (20 milisaniye × 50 = 1 saniye) aldığı bir piyangoyu saniyede 50 kez tutarak
piyango planlamasını uygular . BTV zamanlayıcısının, daha yüksek öncelikli iş
parçacıklarının düşük öncelikli iş parçacıklarına göre CPU'dan daha fazla ilgi
görmesini nasıl sağlayabileceğini açıklayın.

5.14 Çoğu zamanlama algoritması , bir işlemci üzerinde çalışmaya uygun süreçleri
listeleyen bir çalıştırma kuyruğunu korur. Çok çekirdekli sistemlerde iki genel
seçenek vardır: (1) her işlem çekirdeğinin kendi çalıştırma kuyruğu vardır veya
(2) tek bir çalıştırma sırası tüm işlem çekirdekleri tarafından paylaşılır. Bu
yaklaşımların her birinin avantajları ve dezavantajları nelerdir?

5.15 Bir sonraki CPU patlamasının uzunluğunu tahmin etmek için kullanılan üstel
ortalama formülü düşünün . Algoritma tarafından kullanılan parametrelere
aşağıdaki değerleri atamanın sonuçları nelerdir?

a. α = 0 ve τ0 = 100 milisaniye

b. α = 0.99 ve τ0 = 10 milisaniye

5.16 Tekrarlı sıralı zamanlayıcının bir varyasyonu, gerileyen sıralı sıralı zamanlayıcıdır. Bu
zamanlayıcı, her işleme bir zaman kuantumu ve bir öncelik atar. Bir zaman
kuantumunun başlangıç değeri 50 milisaniyedir. Bununla birlikte, bir işlem
CPU'ya tahsis edildiğinde ve tüm zaman kuantumunu kullandığında ( G/Ç için
bloke etmez ), zaman kuantumuna 10 milisaniye eklenir ve öncelik düzeyi
yükseltilir. (Bir işlemin zaman kuantumu maksimum 100 milisaniyeye yükseltilebilir.)
Bir işlem tüm zaman kuantumunu kullanmadan önce bloke ettiğinde, zaman
kuantumu 5 milisaniye azalır, ancak önceliği aynı kalır. Gerileyen döngüsel
zamanlayıcı ne tür bir işlemi (CPU'ya bağlı veya G/Ç'ye bağlı) tercih eder?
Açıklamak.
EX-13
Machine Translated by Google

5.17 CPU patlamasının uzunluğuyla birlikte aşağıdaki süreç dizisini göz önünde bulundurun.
milisaniye cinsinden verilir:

İşlem Patlama Süresi Öncelik


P1 5 4
P2 3 1
P3 1 2
P4 7 2
P5 4 3

Proseslerin P1, P2, P3, P4, P5, P1, P2, P3, P4, P5,
hepsi 0 zamanında.

a. Aşağıdaki zamanlama algoritmalarını kullanarak bu süreçlerin yürütülmesini


gösteren dört Gantt şeması çizin: FCFS, SJF, önleyici olmayan öncelik (daha
büyük bir öncelik numarası, daha yüksek bir öncelik numarası anlamına gelir).
öncelik) ve RR (kuantum = 2).

b. Her bir sürecin geri dönüş süresi nedir?


a bölümündeki zamanlama algoritmaları?

c. Bu çizelgeleme algoritmalarının her biri için her bir sürecin bekleme süresi nedir?

d. Algoritmalardan hangisi minimum ortalama bekleme ile sonuçlanır?


zaman (tüm süreçlerde)?

5.18 Aşağıdaki işlemler bir önleyici kullanılarak planlanmaktadır,


önceliğe dayalı, döngüsel zamanlama algoritması.
İşlem Öncelik Patlamak Varış

P1 8 15 0
P2 3 20 0

P3 4 20 20

P4 4 20 25

P5 5 545
P6 5 15 55

Her sürece sayısal bir öncelik atanır ve daha yüksek bir sayı, daha yüksek bir göreli
önceliği belirtir. Zamanlayıcı, en yüksek öncelikli işlemi yürütecektir. Aynı önceliğe
sahip işlemler için, bir döngüsel deneme
zamanlayıcı, 10 birimlik bir zaman kuantumu ile kullanılacaktır. bir süreç ise
daha yüksek öncelikli bir süreç tarafından önlenen, önceden alınan süreç
kuyruğun sonunda.

a. Bir Gantt şeması kullanarak süreçlerin zamanlama sırasını gösterin.

b. Her bir süreç için geri dönüş süresi nedir?

c. Her işlem için bekleme süresi nedir?

5.19 Nice komutu , Linux'ta bir işlemin nice değerini ayarlamak için kullanılır,
yanı sıra diğer UNIX sistemlerinde. Bazı sistemlerin neden izin verebileceğini açıklayın
herhangi bir kullanıcı bir işleme Nice değeri >= 0 atayacak, ancak yalnızca köke (veya
yönetici) kullanıcı < 0 güzel değerler atamak için .
Egzersizler EX-14
Machine Translated by Google

5.20 Aşağıdaki programlama algoritmalarından hangisi açlıkla sonuçlanabilir?


a. İlk gelen alır b. Önce en

kısa iş
c. tekrar tekrar

d. Öncelik

5.21 Hazır kuyruğundaki girişlerin PCB'leri işaret ettiği bir RR zamanlama algoritması
türevi düşünün .

a. Hazır kuyruğunda aynı işleme iki işaretçi koymanın etkisi ne olurdu?

b. Bu planın iki büyük avantajı ve iki dezavantajı ne olabilir?

c. Aynı şeyi elde etmek için temel RR algoritmasını nasıl değiştirirsiniz?


yinelenen işaretçiler olmadan etki?

5.22 On G/Ç'ye bağlı görev ve bir CPU'ya bağlı görev çalıştıran bir sistem düşünün. G/
Ç'ye bağlı görevlerin her milisaniye CPU hesaplaması için bir G/Ç işlemi
yayınladığını ve her G/Ç işleminin tamamlanmasının 10 milisaniye sürdüğünü
varsayalım . Ayrıca bağlam değiştirme ek yükünün 0,1 milisaniye olduğunu ve
tüm işlemlerin uzun süreli görevler olduğunu varsayalım.
Aşağıdaki durumlarda bir döngüsel zamanlayıcı için CPU kullanımını tanımlayın:

a. Zaman kuantumu 1 milisaniyedir b.

Zaman kuantumu 10 milisaniyedir 5.23 Çok

düzeyli kuyruk zamanlaması uygulayan bir sistem düşünün. Bir bilgisayar kullanıcısı ,
kullanıcının işlemine ayrılan CPU süresini en üst düzeye çıkarmak için hangi
stratejiyi kullanabilir ?

5.24 Dinamik olarak değişen önceliklere dayalı bir önleyici öncelik zamanlama
algoritması düşünün. Daha büyük öncelik numaraları daha yüksek öncelik anlamına g
Bir işlem CPU'yu beklerken (hazır kuyruğunda, ancak çalışmıyor), önceliği α
oranında değişir. Çalışırken önceliği β oranında değişir. Tüm işlemlere hazır
kuyruğuna girdiklerinde 0 öncelik verilir. α ve β parametreleri birçok farklı
çizelgeleme algoritması verecek şekilde ayarlanabilir.

a. β > α > 0'dan elde edilen algoritma nedir ? b. α < β < 0

sonucu elde edilen algoritma nedir ?

5.25 Aşağıdaki çizelgeleme algoritmalarının ikisinden birini nasıl ayırt ettiğini açıklayın.
kısa süreçler lehine veya aleyhine:
a. FCFS

b. RR

c. Çok düzeyli geri bildirim kuyrukları


EX-15
Machine Translated by Google

5.26 Paylaşılan bir hazır kuyruğun bir SMP ortamındaki performans sorunlarından neden
zarar görebileceğini açıklayın.

5.27 Öncelikten bağımsız olarak her kuyruğun yaklaşık olarak aynı sayıda iş parçacığına
sahip olmasını sağlayan bir yük dengeleme algoritması düşünün.
Bir çalıştırma kuyruğunda tüm yüksek öncelikli iş parçacıkları ve ikinci bir kuyrukta
tüm düşük öncelikli iş parçacıkları varsa, önceliğe dayalı bir zamanlama algoritması
bu durumu ne kadar etkili bir şekilde ele alır?

5.28 Bir SMP sisteminin özel, işlemci başına çalıştırma kuyruklarına sahip olduğunu varsayın .
Yeni bir süreç oluşturulduğunda, üst süreçle aynı kuyruğa veya ayrı bir kuyruğa
yerleştirilebilir.

a. Yeni süreci ebeveyni ile aynı kuyruğa yerleştirmenin faydaları nelerdir? b. Yeni
süreci farklı bir sürece yerleştirmenin faydaları nelerdir?

sıra?

5.29 Bir iş parçacığının ağ G/ Ç'sini engellediğini ve yeniden çalıştırmaya uygun olduğunu


varsayın. NUMA uyumlu bir zamanlama algoritmasının, iş parçacığını daha önce
çalıştığı aynı CPU'da neden yeniden zamanlaması gerektiğini açıklayın .

5.30 Windows zamanlama algoritmasını kullanarak sayısal ön değeri belirleyin.


aşağıdaki iş parçacıklarının her birinin ority.

a. Göreli önceliğe sahip GERÇEK ZAMAN ÖNCELİK SINIFINDAKİ bir iş parçacığı


NORMAL _

b. YUKARI NORMAL ÖNCELİK SINIFINDA bir akraba ile bir iş parçacığı

YÜKSEK önceliği
c. Bir akraba ile AŞAĞIDAKİ NORMAL ÖNCELİK SINIFINDAKİ bir iş parçacığı

NORMALİN ÜSTÜNDE öncelik

5.31 Hiçbir iş parçacığının GERÇEK ZAMAN ÖNCELİK SINIFINA ait olmadığını ve hiçbirine
ZAMAN KRİTİK bir öncelik atanamayacağını varsayarsak, Windows zamanlamasında
hangi öncelik sınıfı ve öncelik kombinasyonu mümkün olan en yüksek göreli önceliğe
karşılık gelir?

5.32 Solaris işletim sistemindeki zamanlama algoritmasını düşünün:


zaman paylaşımı konuları.

a. Önceliği 15 olan bir iş parçacığı için zaman kuantumu (milisaniye cinsinden)


nedir? Öncelik 40 ile mi? b. Önceliği 50 olan bir iş parçacığının tüm zaman

kuantumunu engellemeden kullandığını varsayalım. Zamanlayıcı bu iş parçacığına


hangi yeni önceliği atayacak? c. Kuantum süresi dolmadan önce G/Ç için
önceliği 20 olan bir iş parçacığının olduğunu varsayın . Zamanlayıcı bu iş

parçacığına hangi yeni önceliği atayacak?


Machine Translated by Google

Egzersizler EX-16

5.33 A ve B adlı iki görevin bir Linux sisteminde çalıştığını varsayın. A ve B'nin nice
değerleri sırasıyla -5 ve +5'tir. CFS zamanlayıcısını bir kılavuz olarak kullanarak ,
aşağıdaki senaryoların her birinde verilen iki işlem arasında ilgili vruntime
değerlerinin nasıl değiştiğini açıklayın:
• Hem A hem de B CPU'ya bağlıdır.

• A , G/Ç'ye bağlıdır ve B , CPU'ya bağlıdır.

• A , CPU'ya bağlıdır ve B , G/Ç'ye bağlıdır.

5.34 Gerçek zamanlı süreç son tarihlerini karşılamada oran-monotonik çizelgelemenin


en erken-son tarih-ilk çizelgelemeye göre daha düşük olduğu durumları
gösteren özel bir durum sağlayın?

5.35 p1 = 50 , t1 = 25 , p2 = 75 ve
t2 = 30.

a. Bu iki süreç, oran monotonik zamanlama kullanılarak planlanabilir mi?


Cevabınızı Şekil 5.21–Şekil 5.24'tekiler gibi bir Gantt şeması kullanarak
gösterin.

b. En erken son teslim tarihi (EDF) zamanlamasını kullanarak bu iki sürecin


zamanlamasını gösterin.

5.36 Kesinti ve gönderme gecikme sürelerinin neden bir


zor gerçek zamanlı sistem.

5.37 Bir sistemde heterojen çoklu işleme kullanmanın avantajlarını tanımlayın.


mobil sistem.
Machine Translated by Google

P-29 Bölüm 5 CPU Programlama

Programlama Projeleri

Zamanlama Algoritmaları
Bu proje, birkaç farklı süreç çizelgeleme algoritmasının uygulanmasını içerir. Zamanlayıcıya
önceden tanımlanmış bir dizi görev atanacak ve görevleri seçilen zamanlama algoritmasına
göre planlayacaktır. Her göreve bir öncelik ve CPU patlaması atanır. Aşağıdaki zamanlama
algoritmaları uygulanacaktır:

• Görevleri CPU'dan talep ettikleri sıraya göre zamanlayan ilk gelen, ilk hizmet alır (FCFS) .

• Önce en kısa iş (SJF), görevlerin bir sonraki CPU patlamasının uzunluğuna göre
zamanlama.

• Önceliğe göre görevleri zamanlayan öncelik zamanlaması. • Her görevin

bir zaman kuantumu için çalıştırıldığı döngüsel (RR) zamanlama


(veya CPU patlamasının geri kalanı için ).

• Görevleri öncelik sırasına göre zamanlayan ve eşit önceliğe sahip görevler için
döngüsel zamanlamayı kullanan, sıralı deneme ile öncelik.

Öncelikler 1 ile 10 arasında değişir; burada daha yüksek bir sayısal değer, daha yüksek
bir göreli önceliği gösterir. Round-robin zamanlama için, bir zaman kuantumunun
uzunluğu 10 milisaniyedir.

I. Uygulama

Bu projenin uygulanması, C veya Java'da tamamlanabilir ve bu dillerin her ikisini de


destekleyen program dosyaları, metin için kaynak kod indirmesinde sağlanır. Bu
destekleyici dosyalar, görevlerin zamanlamasını okur, görevleri bir listeye ekler ve
zamanlayıcıyı çağırır.
Görevlerin zamanlaması , aşağıdaki örnek formatta [görev adı] [öncelik] [CPU
patlaması] biçimindedir:

T1, 4, 20
T2, 2, 25
T3, 3, 25
T4, 3, 15
T5, 10, 10

Bu nedenle, görev T1'in önceliği 4 ve CPU patlaması 20 milisaniye vb. Tüm görevlerin aynı
anda geldiği varsayılır, bu nedenle zamanlayıcı algoritmalarınızın daha düşük öncelikli
süreçleri önleyen daha yüksek öncelikli süreçleri desteklemesi gerekmez. Ayrıca, görevlerin
belirli bir sıraya göre sıraya veya listeye yerleştirilmesi gerekmez.

İlk olarak Bölüm 5.1.2'de sunulduğu gibi, görev listesini düzenlemek için birkaç
farklı strateji vardır. Bir yaklaşım, tüm görevleri, görev seçimi stratejisinin zamanlamaya
bağlı olduğu tek bir sırasız listeye yerleştirmektir.
Machine Translated by Google

Programlama Projeleri P-30

algoritma. Örneğin, SJF zamanlaması, bir sonraki en kısa CPU patlamasına sahip görevi
bulmak için listeyi arayacaktır . Alternatif olarak, zamanlama kriterlerine göre (yani
önceliğe göre) bir liste sıralanabilir. Diğer bir strateji, Şekil 5.7'de gösterildiği gibi,
her benzersiz öncelik için ayrı bir kuyruğa sahip olmayı içerir. Bu yaklaşımlar Kısım
5.3.6'da kısaca tartışılmaktadır. Ayrıca terimler listesini kullandığımızı ve birbirinin
yerine geçecek şekilde sıraya koyduğumuzu vurgulamakta fayda var .
Bununla birlikte, bir sıranın çok özel FIFO işlevi vardır, oysa bir listenin bu kadar katı
ekleme ve silme gereksinimleri yoktur. Bu projeyi tamamlarken genel bir listenin
işlevselliğini daha uygun bulmanız olasıdır.

II. C Uygulama Detayları


driver.c dosyası görevlerin zamanlamasını okur, her görevi bağlantılı bir listeye ekler
ve program() işlevini çağırarak süreç zamanlayıcısını çağırır . Schedule() işlevi , her
görevi belirtilen zamanlama algoritmasına göre yürütür. CPU üzerinde yürütülmek
üzere seçilen görevler , Pick NextTask() işlevi tarafından belirlenir ve CPU.c dosyasında
tanımlanan run() işlevi çağrılarak yürütülür. AMakefile , sürücü tarafından çağrılacak
belirli zamanlama algoritmasını belirlemek için kullanılır . Örneğin, FCFS zamanlayıcısını
oluşturmak için şunu gireriz:

fcfs yapmak

ve zamanlayıcıyı (programlama.txt görevlerinin zamanlamasını kullanarak) aşağıdaki


gibi yürütür:

./fcfs program.txt

Daha fazla ayrıntı için kaynak kod indirme dosyasındaki BENİOKU dosyasına bakın.
Devam etmeden önce, sağlanan kaynak kodun yanı sıra Makefile'ı da tanıdığınızdan
emin olun.

III. Java Uygulama Ayrıntıları

Driver.java dosyası görev çizelgesinde okur, her görevi bir Java ArrayList'e ekler ve
program() yöntemini çağırarak işlem zamanlayıcısını çağırır . Aşağıdaki arayüz, beş
farklı zamanlama algoritmasının uygulayacağı genel bir zamanlama algoritmasını
tanımlar:

genel arayüz Algoritması {

// Zamanlama algoritmasının uygulanması public void


program();

// Zamanlanacak bir sonraki görevi seçer public Task


pickNetTask();
}

Schedule() yöntemi , pickNextTask () yöntemini çağırarak CPU'da çalıştırılacak bir


sonraki görevi alır ve ardından bu Görevi , CPU.java sınıfındaki statik run() yöntemini
çağırarak yürütür.
Program şu şekilde çalıştırılır:

java Sürücüsü fcfs program.txt


P-31 Bölüm 5 CPU Programlama
Machine Translated by Google
Daha fazla ayrıntı için kaynak kod indirme dosyasındaki BENİOKU dosyasına bakın.
Devam etmeden önce, kaynak kodu indirmesinde sağlanan tüm Java kaynak dosyalarına
aşina olduğunuzdan emin olun.

IV. Diğer Zorluklar

Bu proje için iki ek zorluk sunulmaktadır:

1. Zamanlayıcıya sağlanan her göreve benzersiz bir görev (tid) atanır.


Bir zamanlayıcı, her CPU'nun ayrı ayrı kendi zamanlayıcısını çalıştırdığı bir SMP
ortamında çalışıyorsa, görev tanımlayıcılarını atamak için kullanılan değişken
üzerinde olası bir yarış durumu vardır. Bir atomik tamsayı kullanarak bu yarış
durumunu düzeltin.

Linux ve macOS sistemlerinde, bir tamsayı değerini atomik olarak artırmak için sync
fetch ve add() işlevi kullanılabilir. Örnek olarak, aşağıdaki kod örneği, değeri
atomik olarak 1 artırır:
int değeri = 0;
senkronizasyon getir ve ekle(&value,1);

Java programları için AtomicInteger sınıfının nasıl kullanılacağına ilişkin ayrıntılar


için Java API'sine bakın.

2. Ortalama geri dönüş süresini, bekleme süresini ve yanıt süresini hesaplayın


zamanlama algoritmalarının her biri için.
Machine Translated by Google

Üçüncü Bölüm

İşlem

senkronizasyon
Bir sistem tipik olarak, aynı anda veya paralel olarak çalışan birkaç (belki de yüzlerce
hatta binlerce) iş parçacığından oluşur. Konular genellikle kullanıcı verilerini paylaşır.
Bu arada, işletim sistemi, birden çok iş parçacığını desteklemek için çeşitli veri
yapılarını sürekli olarak günceller. Paylaşılan verilere erişim kontrol edilmediğinde,
muhtemelen bozuk veri değerlerine neden olan bir yarış durumu mevcuttur.

Süreç senkronizasyonu, yarış koşullarından kaçınmak için paylaşılan verilere


erişimi kontrol eden araçların kullanılmasını içerir. Yanlış kullanımları kilitlenme de
dahil olmak üzere düşük sistem performansına neden olabileceğinden, bu araçlar
dikkatli kullanılmalıdır.
Machine Translated by Google
Machine Translated by Google

6BÖLÜM
senkronizasyon
Aletler

İşbirliği süreci , sistemde yürütülen diğer süreçleri etkileyebilen veya bunlardan


etkilenebilen bir süreçtir . İşbirliği yapan süreçler ya doğrudan bir mantıksal adres
alanını (yani hem kod hem de veriyi) paylaşabilir ya da yalnızca paylaşılan bellek veya
mesaj geçişi yoluyla verileri paylaşmasına izin verilebilir. Bununla birlikte, paylaşılan
verilere eşzamanlı erişim, veri tutarsızlığına neden olabilir. Bu bölümde, veri
tutarlılığının korunması için mantıksal bir adres alanını paylaşan işbirliği yapan
süreçlerin düzenli bir şekilde yürütülmesini sağlamak için çeşitli mekanizmaları tartışıyoruz.

BÖLÜM HEDEFLERİ

• Kritik bölüm problemini tanımlayın ve bir yarış durumunu gösterin. • Bellek


engellerini, karşılaştırma ve değiştirme işlemlerini ve atomik değişkenleri kullanarak
kritik bölüm sorununa donanım çözümlerini gösterin.
• Kritik bölüm problemini çözmek için muteks kilitlerinin, semaforların, monitörlerin
ve koşul değişkenlerinin nasıl kullanılabileceğini gösterin.
• Düşük, orta, kritik bölüm problemini çözen araçları değerlendirin.
ve yüksek çekişmeli senaryolar.

6.1 Arka Plan

Süreçlerin eşzamanlı veya paralel olarak yürütülebileceğini zaten gördük. Bölüm


3.2.2, süreç programlamanın rolünü tanıttı ve CPU zamanlayıcısının eşzamanlı
yürütme sağlamak için süreçler arasında nasıl hızla geçiş yaptığını açıkladı. Bu, bir
işlemin başka bir işlem planlanmadan önce yürütmeyi yalnızca kısmen
tamamlayabileceği anlamına gelir. Aslında, bir işlem talimat akışının herhangi bir
noktasında kesintiye uğrayabilir ve işlem çekirdeği, başka bir işlemin talimatlarını
yürütmek için atanabilir. Ek olarak, Bölüm 4.2, iki komut akışının (farklı süreçleri
temsil eden) aynı anda ayrı işlem çekirdeklerinde yürütüldüğü paralel yürütmeyi
tanıttı. Bu bölümde, eşzamanlı veya paralel yürütmenin, çeşitli süreçler tarafından
paylaşılan verilerin bütünlüğünü içeren sorunlara nasıl katkıda bulunabileceğini
açıklıyoruz.

257
Machine Translated by Google

258 Bölüm 6 Senkronizasyon Araçları

Bunun nasıl olabileceğine dair bir örnek düşünelim. Bölüm 3'te, tümü
asenkron olarak çalışan ve muhtemelen veri paylaşan, birlikte çalışan sıralı
işlemlerden veya iş parçacıklarından oluşan bir sistem modeli geliştirdik. Bu modeli,
birçok işletim sistemi fonksiyonunun temsili bir paradigması olan üretici-tüketici
problemi ile gösterdik. Spesifik olarak, Bölüm 3.5'te, işlemlerin belleği paylaşmasını
sağlamak için sınırlı bir arabelleğin nasıl kullanılabileceğini açıkladık.

Şimdi sınırlı tamponla ilgili değerlendirmemize dönüyoruz. Belirttiğimiz gibi,


orijinal çözümümüz aynı anda arabellekte en fazla BUFFER SIZE 1 öğeye izin
verdi. Bu eksikliği gidermek için algoritmayı değiştirmek istediğimizi varsayalım.
Bir olasılık, 0 olarak başlatılan bir tamsayı değişkeni eklemektir. Sayım, arabelleğe
her yeni öğe eklediğimizde artar ve arabellekten bir öğeyi her çıkardığımızda
azalır. Üretici sürecinin kodu aşağıdaki gibi değiştirilebilir:

while (true) { /*
sonraki üretimde bir öğe üret */

while (sayım == TAMPON BOYUTU) ; /*


hiçbir şey yapma */

tampon[in] = sonraki üretilen; in = (+1


olarak) % TAMPON BOYUTU; say++;

Tüketici sürecinin kodu aşağıdaki gibi değiştirilebilir:

while (true) { while


(sayım == 0)
; /* hiçbir şey yapma */

sonraki tüketilen = arabellek[çıkış]; çıkış


= (çıkış + 1) % TAMPON BOYUTU; saymak--;

/* sonraki tüketilen öğeyi tüket */


}

Yukarıda gösterilen üretici ve tüketici rutinleri ayrı ayrı doğru olsa da, aynı anda
yürütüldüklerinde düzgün çalışmayabilirler. Örnek olarak, sayım değişkeninin
değerinin şu anda 5 olduğunu ve üretici ve tüketici süreçlerinin aynı anda "count+
+" ve "count--" ifadelerini yürüttüğünü varsayalım. Bu iki ifadenin yürütülmesini
takiben, değişken sayısı 4, 5 veya 6 olabilir! Yine de tek doğru sonuç, üretici ve
tüketici ayrı ayrı yürütürse doğru şekilde oluşturulan count == 5'tir.
Machine Translated by Google

6.1 Arka Plan 259

count değerinin yanlış olabileceğini aşağıdaki gibi gösterebiliriz. "count++"


ifadesinin makine dilinde (tipik bir makinede) aşağıdaki gibi uygulanabileceğini
unutmayın:

register1 = sayma
register1 = register1 +
1 sayma = register1

burada register1 yerel CPU kayıtlarından biridir. Benzer şekilde, “say- -” ifadesi
aşağıdaki gibi uygulanır:

register2 =
register2 = register2
1 sayım = register2

burada yine register2 , yerel CPU kayıtlarından biridir. register1 ve register2 aynı
fiziksel kayıt olsa bile , bu kaydın içeriğinin kesme işleyicisi tarafından kaydedileceğini
ve geri yükleneceğini unutmayın (Bölüm 1.2.3).
"count++" ve "count--" nin eşzamanlı yürütülmesi, daha önce sunulan alt düzey
ifadelerin rastgele bir sırayla serpiştirildiği (ancak her bir üst düzey ifadedeki sıranın
korunduğu) sıralı bir yürütmeye eşdeğerdir. Böyle bir serpiştirme şudur:

T0: üretici register1 yürütür = say {register1 = 5}


T1: üretici yürütür register1 = register1 + 1 {register1 = 6}
T2: tüketici çalıştırma kaydı2 = say {kayıt2 = 5}
T3: tüketici çalıştırma register2 = register2 1 {register2 = 4}
T4: üretici çalıştırma sayısı = register1 {sayım = 6}
T5: tüketici çalıştırma sayısı = register2 {sayım = 4}

Dört arabelleğin dolu olduğunu gösteren, aslında beş arabellek doluyken, yanlış
“sayım == 4” durumuna ulaştığımıza dikkat edin . T4 ve T5'teki ifadelerin sırasını tersine
çevirirsek, yanlış “sayım == 6” durumuna ulaşırız .

Bu yanlış duruma varırdık çünkü her iki işlemin de değişken sayısını aynı anda
manipüle etmesine izin verdik. Birkaç işlemin aynı anda aynı verilere eriştiği ve bunları
manipüle ettiği ve yürütmenin sonucunun erişimin gerçekleştiği belirli sıraya bağlı
olduğu böyle bir duruma yarış koşulu denir. Yukarıdaki yarış koşuluna karşı korunmak
için, aynı anda yalnızca bir işlemin değişken sayımı manipüle edebileceğinden emin
olmamız gerekir. Böyle bir garanti verebilmek için süreçlerin bir şekilde senkronize
edilmesini şart koşuyoruz.

Sistemin farklı bölümleri kaynakları manipüle ettiğinden, az önce açıklanana


benzer durumlar işletim sistemlerinde sıklıkla meydana gelir. Ayrıca, daha önceki
bölümlerde vurguladığımız gibi, çok çekirdekli sistemlerin öne çıkması, çok iş
parçacıklı uygulamaların geliştirilmesine artan bir vurgu getirdi. Bu tür uygulamalarda,
büyük olasılıkla veri paylaşan birkaç iş parçacığı, farklı işlem çekirdeklerinde paralel
olarak çalışır. Açıkçası, bu tür faaliyetlerden kaynaklanan herhangi bir değişikliğin
bir tanesine müdahale etmemesini istiyoruz.
Machine Translated by Google

260 Bölüm 6 Senkronizasyon Araçları

bir diğer. Bu konunun önemi nedeniyle, bu bölümün büyük bir bölümünü, işbirliği
yapan süreçler arasındaki senkronizasyon ve koordinasyonun işlenmesine ayırdık.

6.2 Kritik Kesit Problemi

Kritik bölüm problemini tartışarak süreç senkronizasyonu değerlendirmemize


başlıyoruz. {P0, P1, ..., Pn 1} n süreçten oluşan bir sistem düşünün . Her işlemin, en
az bir başka işlemle paylaşılan verilere eriştiği ve güncellediği , kritik bölüm adı
verilen bir kod bölümü vardır. Sistemin önemli özelliği, kritik bölümünde bir işlem
yürütülürken, kritik bölümünde başka bir işlemin yürütülmesine izin verilmemesidir.
Yani, kritik bölümlerinde aynı anda iki işlem yürütülmüyor. Kritik bölüm problemi ,
süreçlerin işbirliği içinde veri paylaşacak şekilde etkinliklerini senkronize etmek için
kullanabilecekleri bir protokol tasarlamaktır. Her işlem, kritik bölümüne girmek için
izin istemelidir. Bu isteği uygulayan kod bölümü giriş bölümüdür. Kritik bölümü bir
çıkış bölümü takip edebilir. Kalan kod kalan kısımdır. Tipik bir prosesin genel yapısı
Şekil 6.1'de gösterilmektedir. Giriş bölümü ve çıkış bölümü, bu önemli kod
bölümlerini vurgulamak için kutular içine alınmıştır.

Kritik bölüm probleminin çözümü aşağıdaki üç gereksinimi karşılamalıdır:

1. Karşılıklı dışlama. Pi süreci kritik bölümünde yürütülüyorsa, kritik bölümlerinde


başka hiçbir süreç yürütülemez.
2. İlerleme. Kritik bölümünde herhangi bir süreç yürütülmüyorsa ve bazı
süreçler kritik bölümlerine girmek istiyorsa, bir sonraki kritik bölümüne
hangisinin gireceğine karar vermeye yalnızca geri kalan bölümlerinde
yürütülmeyen süreçler katılabilir ve bu seçim yapılamaz. süresiz olarak
ertelendi.

while (doğru) {

giriş bölümü

kritik Bölüm

çıkış bölümü

kalan bölüm

Şekil 6.1 Tipik bir sürecin genel yapısı.


Machine Translated by Google

6.2 Kritik Kesit Problemi 261

3. Sınırlı bekleme. Bir işlem kritik bölümüne girmek için bir talepte bulunduktan
sonra ve bu talep kabul edilmeden önce diğer işlemlerin kritik bölümlerine
girmelerine izin verilen sayıda bir sınır veya sınır vardır.

Her işlemin sıfırdan farklı bir hızda yürütüldüğünü varsayıyoruz. Ancak, n prosesin
nispi hızıyla ilgili hiçbir varsayımda bulunamayız .
Belirli bir zamanda, işletim sisteminde birçok çekirdek modu işlemi etkin olabilir.
Sonuç olarak, bir işletim sistemini uygulayan kod (çekirdek kodu) birkaç olası yarış
koşuluna tabidir. Örnek olarak, sistemdeki tüm açık dosyaların bir listesini tutan bir
çekirdek veri yapısını düşünün. Bu liste, yeni bir dosya açıldığında veya
kapatıldığında (dosyanın listeye eklenmesi veya listeden çıkarılması) değiştirilmelidir.
İki işlem aynı anda dosyaları açacak olsaydı, bu listedeki ayrı güncellemeler bir
yarış durumuna neden olabilir.
Başka bir örnek Şekil 6.2'de gösterilmektedir. Bu durumda, iki süreç, P0 ve P1,
fork() sistem çağrısını kullanarak alt süreçler yaratıyor .
Bölüm 3.3.1'den fork() 'un yeni oluşturulan sürecin süreç tanımlayıcısını ana sürece
döndürdüğünü hatırlayın. Bu örnekte, bir sonraki kullanılabilir süreç tanımlayıcısının
değerini temsil eden sonraki kullanılabilir pid değişken çekirdek değişkeni üzerinde
bir yarış koşulu vardır . Karşılıklı dışlama sağlanmadıkça, aynı işlem tanımlayıcı
numarasının iki ayrı işleme atanması mümkündür.

Olası yarış koşullarına yatkın olan diğer çekirdek veri yapıları, bellek tahsisini
sürdürmek, süreç listelerini sürdürmek ve kesinti işlemek için yapıları içerir. İşletim
sisteminin bu tür yarış koşullarından arınmış olmasını sağlamak çekirdek
geliştiricilerine bağlıdır.
Paylaşılan bir değişken değiştirilirken kesintilerin oluşmasını önleyebilirsek,
kritik bölüm sorunu tek çekirdekli bir ortamda basitçe çözülebilirdi. Bu şekilde,
mevcut dizinin olduğundan emin olabiliriz.

P P1
0

pid_t çocuk = çatal (); pid_t çocuk = çatal ();

pid iste pid iste

next_available_pid = 2615

dönüş dönüş
2615 2615

çocuk = 2615 çocuk = 2615

Şekil 6.2 Bir pid atanırken yarış durumu.


262 Bölüm 6 Senkronizasyon Araçları
Machine Translated by Google

talimatların önceden alınmadan sırayla yürütülmesine izin verilecektir. Numara


diğer talimatlar çalıştırılır, bu nedenle beklenmeyen değişiklikler yapılamaz.
paylaşılan değişkene yapılır.
Ne yazık ki, bu çözüm çok işlemcili bir ortamda o kadar uygulanabilir değildir. Çok
işlemcili bir bilgisayarda kesintileri devre dışı bırakmak zaman alıcı olabilir, çünkü
mesaj tüm işlemcilere iletilir. Bu mesaj geçişi girişi geciktiriyor
her kritik bölüme girer ve sistem verimliliği düşer. Ayrıca şunları da göz önünde bulundurun:
Eğer saat kesintilerle güncel tutulursa sistemin saatine etkisi.
İşletimde kritik bölümleri ele almak için iki genel yaklaşım kullanılır.
sistemler: önleyici çekirdekler ve önleyici olmayan çekirdekler. Önleyici bir çekirdek, bir
işlemin çekirdek modunda çalışırken önceden alınmasına izin verir. A
önleyici olmayan çekirdek, çekirdek modunda çalışan bir işlemin
önceden alınmış; bir çekirdek modu işlemi, çekirdek modundan çıkana kadar çalışır, bloklar,
veya gönüllü olarak CPU'nun kontrolünü sağlar.
Açıkçası, önleyici olmayan bir çekirdek, esasen yarış koşullarından bağımsızdır.
çekirdek veri yapılarında, çekirdekte aynı anda yalnızca bir işlem etkin olduğundan.
Önleyici çekirdekler için aynı şeyi söyleyemeyiz, bu yüzden dikkatli olmalılar.
paylaşılan çekirdek verilerinin yarış koşullarından arınmış olmasını sağlamak için
tasarlanmıştır. Önleyici çekirdeklerin SMP mimarileri için tasarlanması özellikle zordur, çünkü
bu ortamlarda iki çekirdek modu işleminin çalışması mümkündür
Aynı anda farklı CPU çekirdeklerinde.
O halde neden herhangi biri, önleyici olmayan bir çekirdek yerine önleyici bir çekirdeği
tercih etsin? Daha az risk olduğundan, önleyici bir çekirdek daha duyarlı olabilir.
bir çekirdek modu işleminin, işlemciyi bekleyen işlemlere bırakmadan önce keyfi olarak uzun
bir süre boyunca çalışacağını. (Tabii ki bu risk,
bu şekilde davranmayan çekirdek kodu tasarlanarak en aza indirilir.) Daha da ötesi, bir
önleyici çekirdek, gerçek zamanlı programlama için daha uygundur, çünkü
gerçek zamanlı bir işlemin şu anda çalışan bir işlemin önüne geçmesine izin verecektir.
çekirdek.

6.3 Peterson Çözümü

Daha sonra, Peterson'ın çözümü olarak bilinen kritik bölüm problemine klasik yazılım tabanlı
bir çözüm göstereceğiz . Çünkü modern bilgisayar
mimariler, yükleme ve yükleme gibi temel makine dili talimatlarını gerçekleştirir.
mağaza, Peterson'ın çözümünün doğru çalışacağının garantisi yoktur.
Bu tür mimarilerde. Ancak, çözümü sunduğu için sunuyoruz.
Kritik bölüm problemini çözmenin iyi bir algoritmik açıklaması ve aşağıdakileri ele alan
yazılım tasarımında yer alan bazı karmaşıklıkları gösterir.
karşılıklı dışlama, ilerleme ve sınırlı bekleme gereksinimleri.
Peterson'ın çözümü, yürütmeyi değiştiren iki işlemle sınırlıdır
kritik bölümleri ve kalan bölümleri arasında. Prosesler P0 ve P1 olarak numaralandırılmıştır.
Kolaylık sağlamak için, Pi'yi sunarken , Pj'yi belirtmek için kullanırız .
diğer süreç; yani, j eşittir 1 - i.
Peterson'ın çözümü, iki işlemin iki veri öğesini paylaşmasını gerektirir:

int dönüş;
boole bayrağı[2];
Machine Translated by Google

6.3 Peterson Çözümü 263

while (true)
{ flag[i] = true;
dönüş = j; while
(bayrak[j] && dönüş == j)
;

/* kritik Bölüm */

bayrak[i] = yanlış;

/*kalan bölüm */
}

Şekil 6.3 Peterson çözümünde Pi sürecinin yapısı .

Değişken dönüş , kritik bölümüne girme sırasının kimde olduğunu gösterir. Yani,
eğer dönüş == i ise, Pi işleminin kritik bölümünde çalışmasına izin verilir. Bayrak
dizisi, bir işlemin kritik bölümüne girmeye hazır olup olmadığını belirtmek için kullanılır .
Örneğin, bayrak[i] doğruysa , Pi kritik bölümüne girmeye hazırdır. Bu veri yapılarının
açıklaması tamamlandıktan sonra, Şekil 6.3'te gösterilen algoritmayı tanımlamaya
hazırız.
Kritik bölüme girmek için, Pi süreci önce flag[i] 'yi doğru olarak ayarlar ve sonra
setler j değerine döner , böylece diğer süreç kritik bölüme girmek isterse, bunu
yapabileceğini iddia eder. Her iki işlem de aynı anda girmeye çalışırsa, dönüş kabaca
aynı anda hem i hem de j'ye ayarlanacaktır . Bu görevlerden yalnızca biri sürecek;
diğeri gerçekleşecek ancak hemen üzerine yazılacaktır. Sıranın nihai değeri , iki
süreçten hangisinin kritik bölümüne ilk önce girmesine izin verileceğini belirler.

Şimdi bu çözümün doğru olduğunu kanıtlıyoruz. Bunu göstermemiz gerekiyor:

1. Karşılıklı dışlama korunur.


2. İlerleme gereksinimi karşılanmıştır.
3. Sınırlı bekleme şartı karşılandı.

Özellik 1'i kanıtlamak için, her Pi'nin kritik bölümüne, yalnızca flag[j] == false
veya == i'yi çevirdiğinde girdiğine dikkat edin. Ayrıca, her iki işlem de aynı anda
kritik bölümlerinde yürütülebiliyorsa, flag[0] == flag[1] == true olduğunu unutmayın.
Bu iki gözlem, P0 ve P1'in while deyimlerini yaklaşık olarak aynı anda başarıyla
yürütemeyeceklerini ima eder , çünkü dönüş değeri 0 veya 1 olabilir, ancak ikisi
birden olamaz. Bu nedenle, süreçlerden biri (örneğin, Pj) while ifadesini başarıyla
yürütmüş olmalı , oysa Pi en az bir ek ifadeyi ("turn == j") yürütmek zorundaydı .

Ancak, o zaman, flag[j] == true ve == j'yi çevirin ve bu koşul, Pj kritik bölümünde


olduğu sürece devam edecektir ; sonuç olarak, karşılıklı dışlama korunur.
264 Bölüm 6 Senkronizasyon Araçları
Machine Translated by Google

Özellik 2 ve 3'ü kanıtlamak için, bir Pi işleminin kritik bölüme girmesinin, yalnızca
while döngüsünde durum flag[j] == true ve dönüş == j; bu döngü mümkün olan tek
döngüdür. Pj kritik bölüme girmeye hazır değilse, flag [j] == false ve Pi kritik bölümüne
girebilir. Pj , flag[j] 'yi true olarak ayarladıysa ve while deyiminde de çalışıyorsa, o zaman
ya == i'yi çevirin ya da == j'yi çevirin . Eğer dönüş == i ise, Pi kritik bölüme girecektir.
Eğer dönüş == j ise, Pj kritik bölüme girecektir. Ancak, Pj kritik bölümünden çıktığında,
flag[j] 'yi false olarak sıfırlayacak ve Pi'nin kritik bölümüne girmesine izin verecektir. Pj ,
flag[j] 'yi true olarak sıfırlarsa , ayrıca dönüşü i'ye ayarlaması gerekir .

Böylece, while deyimini yürütürken Pi değişken dönüş değişkeninin değerini


değiştirmediğinden , Pi , Pj'nin (sınırlı bekleme) en fazla bir girişinden sonra kritik
bölüme (ilerleme) girecektir .
Bu bölümün başında bahsedildiği gibi, Peterson'ın çözümünün modern bilgisayar
mimarileri üzerinde çalışması garanti edilmez, bunun başlıca nedeni, sistem performansını
iyileştirmek için işlemcilerin ve/veya derleyicilerin hiçbir bağımlılığı olmayan okuma ve
yazma işlemlerini yeniden sıralayabilmeleridir. Tek iş parçacıklı bir uygulama için, nihai
değerler beklenen değerlerle tutarlı olduğundan, programın doğruluğu söz konusu
olduğunda bu yeniden sıralama önemsizdir. (Bu, bir çek defterini dengelemeye benzer
- alacak ve borç işlemlerinin gerçekleştirildiği asıl sıra önemsizdir, çünkü nihai bakiye
hala aynı olacaktır.) Ancak, paylaşılan verilere sahip çok iş parçacıklı bir uygulama için,
talimatların yeniden sıralanması tutarsız hale gelebilir. veya beklenmedik sonuçlar.

Örnek olarak, iki iş parçacığı arasında paylaşılan aşağıdaki verileri göz önünde
bulundurun:

boole bayrağı = yanlış; int


x = 0;

Thread 1'in ifadeleri yerine getirdiği yer

while (!bayrak)
;
x yazdır;

ve Thread 2 gerçekleştirir

x = 100;
bayrak = doğru;

Beklenen davranış, elbette, Thread 1'in x değişkeni için 100 değerini vermesidir.
Bununla birlikte, flag ve x değişkenleri arasında veri bağımlılığı olmadığından , bir
işlemcinin Thread 2 için talimatları yeniden sıralayabilmesi ve böylece flag x = 100
atanmadan önce true olarak atanması mümkündür. Bu durumda, Thread 1, x değişkeni
için 0 çıktısı verir . Daha az belirgin olan, işlemcinin ayrıca Thread 1 tarafından verilen
ifadeleri yeniden sıralayabilmesi ve flag değerini yüklemeden önce x değişkenini
yükleyebilmesidir. Bu gerçekleşirse, Thread 2 tarafından verilen talimatlar yeniden
sıralanmasa bile , Thread 1 x değişkeni için 0 çıktısı verir.
Machine Translated by Google

6.4 Senkronizasyon için Donanım Desteği 265

süreç 0 dönüş = 1 bayrak[0] = doğru cs

süreç 1 dönüş = 0 , bayrak[1] = doğru cs

zaman

Şekil 6.4 Peterson çözümünde talimat yeniden sıralamanın etkileri.

Bu, Peterson'ın çözümünü nasıl etkiler? Şekil 6.3'teki Peterson çözümünün giriş
bölümünde görünen ilk iki ifadenin atamaları yeniden sıralanırsa ne olacağını düşünün;
Şekil 6.4'te gösterildiği gibi her iki ipliğin de kritik bölümlerinde aynı anda aktif olması
mümkündür.
Aşağıdaki bölümlerde göreceğiniz gibi, karşılıklı dışlamayı korumanın tek yolu uygun
senkronizasyon araçlarını kullanmaktır. Bu araçlarla ilgili tartışmamız, donanımdaki ilkel
destekle başlar ve hem çekirdek geliştiricileri hem de uygulama programcıları için mevcut
olan soyut, yüksek seviyeli, yazılım tabanlı API'ler aracılığıyla ilerler.

6.4 Senkronizasyon için Donanım Desteği

Az önce kritik bölüm sorununa yazılım tabanlı bir çözüm tanımladık. ( Algoritma, karşılıklı
dışlamayı sağlamak için işletim sisteminden özel bir destek veya belirli donanım talimatları
içermediğinden, buna yazılım tabanlı bir çözüm diyoruz.) Bununla birlikte, tartışıldığı gibi,
yazılım tabanlı çözümlerin modern bilgisayar mimarilerinde çalışması garanti edilmez. . Bu
bölümde, kritik bölüm sorununu çözmek için destek sağlayan üç donanım talimatı
sunuyoruz. Bu ilkel işlemler, doğrudan senkronizasyon araçları olarak kullanılabilir veya
daha soyut senkronizasyon mekanizmalarının temelini oluşturmak için kullanılabilir.

6.4.1 Bellek Engelleri Bölüm 6.3'te,

bir sistemin, güvenilir olmayan veri durumlarına yol açabilecek bir politika olan talimatları
yeniden düzenleyebileceğini gördük. Bir bilgisayar mimarisinin, bir uygulama programına
hangi belleği garanti edeceğini nasıl belirlediği, bellek modeli olarak bilinir. Genel olarak,
bir bellek modeli iki kategoriden birine girer:

1. Bir işlemcide bellek değişikliği yapılması gerektiğinde, kesinlikle sıralanmıştır .


diğer tüm işlemciler tarafından hemen görülebilir.

2. Bir işlemcideki bellekte yapılan değişikliklerin diğer işlemciler tarafından hemen


görülmeyebileceği durumlarda , zayıf sıralanmıştır .

Bellek modelleri işlemci türüne göre değişir, bu nedenle çekirdek geliştiricileri,


paylaşılan bellek çok işlemcili bellekte yapılan değişikliklerin görünürlüğüyle ilgili herhangi
bir varsayımda bulunamazlar. Bu sorunu çözmek için bilgisayar mimarileri , bellekteki
herhangi bir değişikliği diğer tüm işlemcilere yayılmaya zorlayabilecek yönergeler sağlar
ve böylece bellek değişikliklerinin kullanıcılar tarafından görülebilmesini sağlar.
Machine Translated by Google

266
Bölüm 6 Senkronizasyon Araçları

diğer işlemcilerde çalışan iş parçacıkları. Bu tür talimatlar, bellek engelleri veya


bellek çitleri olarak bilinir . Bir bellek bariyeri talimatı gerçekleştirildiğinde, sistem,
sonraki herhangi bir yükleme veya depolama işlemi gerçekleştirilmeden önce tüm
yüklemelerin ve depoların tamamlanmasını sağlar. Bu nedenle, talimatlar yeniden
sıralansa bile, bellek bariyeri, depolama işlemlerinin bellekte tamamlanmasını ve
gelecekteki yükleme veya depolama işlemleri gerçekleştirilmeden önce diğer
işlemciler tarafından görülmesini sağlar.
Talimatların yeniden sıralanmasının yanlış çıktıyla sonuçlanabileceği en son
örneğimize dönelim ve beklenen çıktıyı elde ettiğimizden emin olmak için bir
bellek engeli kullanalım.
Thread 1'e bir bellek bariyeri işlemi eklersek

while (!flag)
bellek engeli(); x
yazdır;

flag değerinin x değerinden önce yüklendiğini garanti ediyoruz .


Benzer şekilde, Thread 2 tarafından oluşturulan atamalar arasına bir bellek
bariyeri yerleştirirsek

x = 100;
bellek bariyeri();
bayrak = doğru;

x'e atamanın, flag atamasından önce gerçekleşmesini sağlıyoruz .


Peterson'ın çözümüyle ilgili olarak, Şekil 6.4'te gösterilen işlemlerin yeniden
sıralanmasını önlemek için giriş bölümündeki ilk iki atama ifadesi arasına bir bellek
bariyeri yerleştirebiliriz. Bellek engellerinin çok düşük düzeyli işlemler olarak kabul
edildiğini ve genellikle yalnızca çekirdek geliştiriciler tarafından karşılıklı dışlamayı
sağlayan özel kod yazarken kullanıldığını unutmayın.

6.4.2 Donanım Talimatları


Birçok modern bilgisayar sistemi, bir kelimenin içeriğini test etmemize ve
değiştirmemize ya da iki kelimenin içeriğini atomik olarak, yani kesintisiz bir birim
olarak değiştirmemize izin veren özel donanım talimatları sağlar. Bu özel
talimatları, kritik bölüm problemini nispeten basit bir şekilde çözmek için
kullanabiliriz. Belirli bir makine için belirli bir talimatı tartışmak yerine, test ve set()
ve karşılaştırma ve takas() talimatlarını tanımlayarak bu tür talimatların arkasındaki
ana kavramları soyutlarız.

boole testi ve set(boolean *target) { boolean rv


= *target; *hedef = doğru;

dönüş rv;
}

Şekil 6.5 Atomik testin tanımı ve set() komutu.


Machine Translated by Google

6.4 Senkronizasyon için Donanım Desteği 267

do
{ while (test et ve ayarla(&lock)); /*
hiçbir şey yapma */

/* kritik Bölüm */

kilit = yanlış;

/* kalan kısım */ } while (true);

Şekil 6.6 test ve set() ile karşılıklı dışlama uygulaması .

test ve set() komutu Şekil 6.5'te gösterildiği gibi tanımlanabilir .


Bu talimatın önemli özelliği, atomik olarak yürütülmesidir. Bu nedenle, iki test ve
set() komutu aynı anda yürütülürse (her biri farklı bir çekirdekte), bunlar rastgele bir
sırayla sırayla yürütülür. Makine test ve set() komutunu destekliyorsa, false olarak
başlatılan bir boole değişken kilidi bildirerek karşılıklı dışlamayı uygulayabiliriz . Pi
işleminin yapısı Şekil 6.6'da gösterilmektedir.

Karşılaştırma ve takas() talimatı (CAS), tıpkı test ve set() talimatı gibi, iki kelime
üzerinde atomik olarak çalışır, ancak iki kelimenin içeriğinin değiştirilmesine
dayanan farklı bir mekanizma kullanır.
CAS komutu üç işlenen üzerinde çalışır ve Şekil 6.7'de tanımlanmıştır . İşlenen
değeri , yalnızca (*değer == beklenen) ifadesi doğruysa yeni değere ayarlanır . Ne
olursa olsun, CAS her zaman değişken değerinin orijinal değerini döndürür . Bu
talimatın önemli özelliği, atomik olarak yürütülmesidir. Bu nedenle, iki CAS komutu
aynı anda yürütülürse (her biri farklı bir çekirdekte), bunlar rastgele bir sırayla sırayla
yürütülecektir.

CAS kullanılarak karşılıklı dışlama şu şekilde sağlanabilir: Global bir değişken


(kilit) bildirilir ve 0'a başlatılır. Karşılaştırma ve takas()' ı çağıran ilk süreç, kilidi 1'e
ayarlayacaktır , ardından kritik bölümüne girecektir,

int karşılaştırma ve takas(int *değer, int beklenen, int yeni değer) { int temp = *değer;

if (*değer == beklenen) *değer


= yeni değer;

dönüş sıcaklığı;
}

Şekil 6.7 Atomik karşılaştırma ve takas() komutunun tanımı .


Machine Translated by Google

268 Bölüm 6 Senkronizasyon Araçları

while (true)
{ while (karşılaştır ve değiştir(&lock, 0, 1) != 0 ); /
* hiçbir şey yapma */

/* kritik Bölüm */

kilit = 0;

/* kalan kısım */
}

Şekil 6.8 Karşılaştırma ve takas() komutuyla karşılıklı dışlama .

çünkü kilidin orijinal değeri beklenen 0 değerine eşitti. Daha sonraki


karşılaştırma ve takas() çağrıları başarılı olmaz, çünkü kilit şimdi beklenen
0 değerine eşit değildir. Bir işlem kritik bölümünden çıktığında, kilidi 0'a
geri ayarlar , bu da başka bir işlemin kritik bölümüne girmesine izin verir.
Pi işleminin yapısı Şekil 6.8'de gösterilmektedir.
Bu algoritma karşılıklı dışlama gereksinimini karşılasa da, sınırlı bekleme
gereksinimini karşılamaz. Şekil 6.9'da sunduğumuz

while (true)
{ wait[i] = true; anahtar
= 1; while (bekliyor[i]
&& tuşu == 1)
anahtar = karşılaştır ve değiştir(&lock,0,1);
bekliyor[i] = yanlış;

/* kritik Bölüm */

j = (i + 1) %n; while
((j != i) && !bekliyor[j]) j = (j + 1) % n;

if (j == i) kilit =
0; başka
bekliyor[j] =
yanlış;

/* kalan kısım */
}

Şekil 6.9 Karşılaştırma ve takas() ile sınırlı beklemeli karşılıklı dışlama .


Machine Translated by Google

6.4 Senkronizasyon için Donanım Desteği 269

KARŞILAŞTIR VE DEĞİŞTİR ATOMİK YAPMAK

Intel x86 mimarilerinde, karşılaştırma ve takas() yönergesini uygulamak için derleme dili ifadesi
cmpxchg kullanılır . Atomik yürütmeyi zorlamak için , hedef işlenen güncellenirken veri yolunu
kilitlemek için kilit öneki kullanılır. Bu talimatın genel şekli şöyle görünür:

kilit cmpxchg <hedef işlenen>, <kaynak işlenen>

tüm kritik bölüm gereksinimlerini karşılayan karşılaştırma ve takas() talimatını


kullanan başka bir algoritma . Yaygın veri yapıları boolean bekliyor[n]; int kilidi;

Bekleyen dizideki öğeler false olarak başlatılır ve kilit 0'a sıfırlanır. Karşılıklı dışlama
gereksiniminin karşılandığını kanıtlamak için, Pi işleminin kritik bölümüne ancak
wait[i] == false olduğunda girebileceğini not ederiz. veya anahtar == 0. Anahtarın
değeri, yalnızca karşılaştırma ve takas() yürütülürse 0 olabilir . Karşılaştırma ve
takas() 'ı yürüten ilk süreç key == 0 ; diğerleri beklemeli. wait[i] değişkeni , ancak
başka bir işlem kritik bölümünden çıkarsa yanlış olabilir ; karşılıklı dışlama gereksinimi
korunarak yalnızca bir bekleme[i] false olarak ayarlanır .

İlerleme şartının karşılandığını kanıtlamak için, kritik bölümden çıkan bir


işlem ya kilidi 0'a ya da wait[j]' i yanlışa ayarladığından , karşılıklı dışlama için
sunulan argümanların burada da geçerli olduğunu not ediyoruz . Her ikisi de kritik
bölümüne girmeyi bekleyen bir işlemin devam etmesine izin verir.
Sınırlı bekleme şartının karşılandığını kanıtlamak için, bir işlem kritik
bölümünden ayrıldığında döngüsel sıralamada bekleyen diziyi (i + 1, i + 2, ..., n 1,
0 ) taradığını not edelim. , ...,
(waiting[j]
ben - 1). ==
Bu true)
olarak
sıralamadaki
kritik
belirler.
bölüme
giriş
Kritik
bölümündeki
girecek
bölümüne
sonraki
girmeyi
ilk işlem
işlemi
bekleyen herhangi bir işlem, böylece n 1 dönüş içinde yapacaktır.

Atomik test ve set() ve karşılaştırma ve takas() talimatlarının uygulanmasını


açıklayan ayrıntılar , bilgisayar mimarisi üzerine kitaplarda daha ayrıntılı olarak
tartışılmaktadır.

6.4.3 Atomik Değişkenler

Tipik olarak, karşılaştırma ve takas() talimatı, karşılıklı dışlama sağlamak için


doğrudan kullanılmaz. Bunun yerine, kritik bölüm problemini çözen diğer araçları
oluşturmak için temel bir yapı taşı olarak kullanılır. Böyle bir araç, tamsayılar ve
booleanlar gibi temel veri türleri üzerinde atomik işlemler sağlayan bir atomik
değişkendir . Bölüm 6.1'den, bir tamsayı değerini artırmanın veya azaltmanın bir
yarış koşulu oluşturabileceğini biliyoruz. Tek bir değişken güncellenirken, bir sayaç
artırılırken olduğu gibi bir veri yarışının olabileceği durumlarda karşılıklı dışlamayı
sağlamak için atomik değişkenler kullanılabilir.
Atomik değişkenleri destekleyen çoğu sistem, atomik değişkenlere erişme ve
bunları işlemek için işlevlerin yanı sıra özel atomik veri türleri sağlar.
Machine Translated by Google

270 Bölüm 6 Senkronizasyon Araçları

Bu işlevler genellikle karşılaştırma ve takas() işlemleri kullanılarak uygulanır . Örnek


olarak, aşağıdaki atomik tamsayı dizisini artırır: increment(&sequence);

increment() işlevi, CAS talimatı kullanılarak uygulanır:

boşluk artışı(atomik int *v) {

int sıcaklık;

do
{ sıcaklık = *v;

} while (temp != karşılaştır ve değiştir(v, temp, temp+1));


}

Atomik değişkenlerin atomik güncellemeler sağlamasına rağmen, her koşulda


yarış koşullarını tamamen çözmediklerini belirtmek önemlidir. Örneğin, Bölüm
6.1'de açıklanan sınırlı arabellek probleminde, sayım için bir atomik tamsayı
kullanabiliriz. Bu, sayılacak güncellemelerin atomik olmasını sağlar. Bununla birlikte,
üretici ve tüketici süreçlerinde , durumu count değerine bağlı olan while döngüleri
de vardır. Tamponun şu anda boş olduğu ve sayım > 0 için beklerken iki tüketicinin
döngü yaptığı bir durumu düşünün. Bir üretici arabelleğe bir öğe girerse, her iki
tüketici de while döngülerinden çıkabilir ( sayım artık 0'a eşit olmayacağından). ve
count değeri yalnızca 1 olarak ayarlanmış olsa bile tüketmeye devam edin .

Atomik değişkenler, kullanımları genellikle sayaçlar ve dizi oluşturucular gibi


paylaşılan verilerin tek güncellemeleriyle sınırlı olmasına rağmen, işletim
sistemlerinde ve eşzamanlı uygulamalarda yaygın olarak kullanılır. Aşağıdaki
bölümlerde, daha genel durumlarda yarış koşullarını ele alan daha sağlam araçları
keşfedeceğiz.

6.5 Mutex Kilitleri

Kısım 6.4'te sunulan kritik bölüm sorununa yönelik donanım tabanlı çözümler
karmaşıktır ve uygulama programcıları tarafından genellikle erişilemez. Bunun
yerine, işletim sistemi tasarımcıları, kritik bölüm sorununu çözmek için daha üst
düzey yazılım araçları oluşturur. Bu araçların en basiti muteks kilididir. (Aslında
mutex terimi, karşılıklı dışlamanın kısaltmasıdır .) Kritik bölümleri korumak ve
böylece yarış koşullarını önlemek için mutex kilidini kullanıyoruz. Yani, bir işlem
kritik bir bölüme girmeden önce kilidi almalıdır; kritik bölümden çıktığında kilidi
serbest bırakır. Edinme () işlevi kilidi alır ve serbest bırakma() işlevi, Şekil 6.10'da
gösterildiği gibi kilidi serbest bırakır.
Bir muteks kilidi, değeri kilidin kullanılabilir olup olmadığını gösteren
kullanılabilir bir boole değişkenine sahiptir. Kilit mevcutsa, edinme() çağrısı başarılı
olur ve bu durumda kilidin kullanılamaz olduğu kabul edilir. Kullanılamayan bir kilidi
almaya çalışan bir işlem, kilit serbest bırakılıncaya kadar engellenir.
Machine Translated by Google

6.5 Mutex Kilitleri 271

while (doğru) {

kilit almak

kritik Bölüm

serbest bırakma kilidi

kalan bölüm

Şekil 6.10 Mutex kilitlerini kullanarak kritik bölüm sorununun çözümü.

Edinme() 'nin tanımı aşağıdaki gibidir:

elde() { while (!
mevcut)
; /* meşgul bekle */
mevcut = yanlış;
}

Release() tanımı aşağıdaki gibidir:

yayın() { mevcut
= doğru;
}

Edinme () veya bırakma() çağrıları atomik olarak gerçekleştirilmelidir.


Böylece, Mutex kilitleri, Bölüm 6.4'te açıklanan CAS işlemi kullanılarak
gerçekleştirilebilir ve bu tekniğin açıklamasını bir alıştırma olarak bırakıyoruz.

İÇERİĞİ KİLİTLE

Kilitler ya çekişmeli ya da çekişmesizdir. Bir iş parçacığı, kilidi almaya çalışırken


bloke ederse , bir kilit iddialı olarak kabul edilir . Bir iş parçacığı onu almaya
çalıştığında bir kilit mevcutsa, kilit çekişmesiz olarak kabul edilir. İhtilaflı kilitler,
yüksek çekişme (kilidi almaya çalışan nispeten fazla sayıda iş parçacığı) veya
düşük çekişme (kilidi almaya çalışan nispeten az sayıda iş parçacığı) yaşayabilir.
uygulamalar.
Machine Translated by Google

272 Bölüm 6 Senkronizasyon Araçları

“KISA SÜRE” İLE NE ANLAMA GELİYOR ?

Çok işlemcili sistemlerde, kilit kısa bir süre tutulacaksa, döndürme kilitleri genellikle tercih
edilen kilitleme mekanizması olarak tanımlanır. Ama tam olarak kısa bir süreyi oluşturan nedir?
Bir kilit üzerinde beklemenin iki bağlam anahtarı gerektirdiği göz önüne alındığında - iş
parçacığını bekleme durumuna taşımak için bir bağlam anahtarı ve kilit kullanılabilir hale
geldiğinde bekleyen iş parçacığını geri yüklemek için ikinci bir bağlam anahtarı - genel kural,
kilit açılacaksa bir döndürme kilidi kullanmaktır. iki bağlam anahtarından daha kısa bir süre
boyunca tutulabilir.

Burada verilen uygulamanın en büyük dezavantajı, yoğun bir bekleme gerektirmesidir.


Bir süreç kendi kritik bölümündeyken, kritik bölümüne girmeye çalışan diğer herhangi
bir süreç, elde etme () çağrısında sürekli olarak döngü yapmalıdır.
Bu sürekli döngü, tek bir CPU çekirdeğinin birçok işlem arasında paylaşıldığı gerçek bir
çoklu programlama sisteminde açıkça bir sorundur. Meşgul bekleme , başka bir işlemin
verimli bir şekilde kullanabileceği CPU döngülerini de boşa harcar.
(Bölüm 6.6'da, bekleme sürecini geçici olarak uyku moduna alarak ve ardından kilit
kullanılabilir hale geldiğinde onu uyandırarak meşgul beklemeyi önleyen bir stratejiyi
inceliyoruz.)
Tanımladığımız muteks kilidi tipine aynı zamanda döndürme kilidi denir, çünkü
işlem kilidin kullanılabilir hale gelmesini beklerken "döner". (Aynı sorunu, karşılaştırma ve
takas() talimatını gösteren kod örneklerinde görüyoruz.) Spinlock'ların bir avantajı vardır,
ancak bir işlemin bir kilit üzerinde beklemesi gerektiğinde bağlam anahtarına gerek
yoktur ve bir bağlam anahtarı olabilir. önemli ölçüde zaman ayırın. Çok çekirdekli
sistemlerde belirli durumlarda, döndürmeli kilitler aslında kilitleme için tercih edilen
seçimdir. Bir kilit kısa bir süre için tutulacaksa, bir iş parçacığı bir işlem çekirdeğinde
"dönebilir", başka bir iş parçacığı kritik bölümünü başka bir çekirdekte gerçekleştirir.
Modern çok çekirdekli bilgi işlem sistemlerinde, döndürme kilitleri birçok işletim
sisteminde yaygın olarak kullanılmaktadır.

Bölüm 7'de mutex kilitlerinin klasik senkronizasyon problemlerini çözmek için nasıl
kullanılabileceğini inceleyeceğiz. Ayrıca, muteks kilitlerinin ve döndürme kilitlerinin çeşitli
işletim sistemlerinde ve Pthreads'te nasıl kullanıldığını tartışıyoruz.

6.6 Semaforlar
Mutex kilitleri, daha önce de belirttiğimiz gibi, genellikle senkronizasyon araçlarının en
basiti olarak kabul edilir. Bu bölümde, bir muteks kilidine benzer şekilde davranabilen
ancak aynı zamanda süreçlerin etkinliklerini senkronize etmeleri için daha karmaşık yollar
sağlayabilen daha sağlam bir aracı inceleyeceğiz.
Bir semafor S , başlatma dışında, yalnızca iki standart atomik işlemle erişilen bir
tamsayı değişkenidir: wait() ve sinyal().
Semaforlar Hollandalı bilgisayar bilimcisi Edsger Dijk stra tarafından tanıtıldı ve bu şekilde,
wait() işlemi orijinal olarak P (Hollandaca'dan ) olarak adlandırıldı.
Machine Translated by Google

6.6 Semaforlar 273

proberen, “test etmek”); sinyal() orijinal olarak V olarak adlandırılıyordu ( verrhogen'den


"artırmak için"). wait() ' in tanımı aşağıdaki gibidir:

wait(S)
{ while (S <= 0) ; //
meşgul bekle
S--;
}

sinyal() tanımı aşağıdaki gibidir:

sinyal(ler) {
S++;
}

wait() ve sinyal() işlemlerinde semaforun tamsayı değerinde yapılan tüm değişiklikler


atomik olarak yürütülmelidir. Yani, bir süreç semafor değerini değiştirdiğinde, başka
hiçbir süreç aynı semafor değerini aynı anda değiştiremez. Ayrıca, wait(S) durumunda,
S (S 0) tamsayı değerinin yanı sıra olası değişikliğinin (S--) testi kesintisiz olarak
gerçekleştirilmelidir. Bu işlemlerin nasıl uygulanabileceğini Bölüm 6.6.2'de göreceğiz.
İlk olarak, semaforların nasıl kullanılabileceğini görelim.

6.6.1 Semafor Kullanımı


İşletim sistemleri genellikle sayma ve ikili semaforları birbirinden ayırır. Bir sayma
semaforunun değeri, sınırsız bir etki alanı üzerinde değişebilir. İkili bir semaforun
değeri yalnızca 0 ile 1 arasında değişebilir. Bu nedenle ikili semaforlar muteks kilitlerine
benzer şekilde davranır. Aslında, mutex kilitleri sağlamayan sistemlerde, karşılıklı dışlama
sağlamak yerine ikili semaforlar kullanılabilir.

Sayma semaforları, sınırlı sayıda örnekten oluşan belirli bir kaynağa erişimi kontrol
etmek için kullanılabilir. Semafor, mevcut kaynakların sayısına göre başlatılır. Bir kaynak
kullanmak isteyen her işlem, semafor üzerinde bir wait() işlemi gerçekleştirir (böylece
sayıyı azaltır). Bir işlem bir kaynağı serbest bıraktığında, bir sinyal() işlemi gerçekleştirir
(sayıyı artırarak). Semafor için sayı 0'a gittiğinde, tüm kaynaklar kullanılıyor. Bundan
sonra, bir kaynağı kullanmak isteyen işlemler, sayı 0'dan büyük olana kadar engellenir.

Çeşitli senkronizasyon problemlerini çözmek için semaforları da kullanabiliriz.


Örneğin, aynı anda çalışan iki işlemi düşünün: S1 deyimiyle P1 ve S2 deyimiyle P2 . S2'nin
yalnızca S1 tamamlandıktan sonra yürütülmesini istediğimizi varsayalım . Bu şemayı, P1
ve P2'nin 0'a başlatılan ortak bir semafor senkronizasyonunu paylaşmasına izin vererek
kolayca uygulayabiliriz. P1 sürecinde ,
ifadeler

S1;
sinyal(senkronizasyon);
Machine Translated by Google

274 Bölüm 6 Senkronizasyon Araçları

P2 sürecinde , ifadeleri ekliyoruz

bekle(senkronizasyon);

S2;

Senkronizasyon 0 olarak başlatıldığından, P2 S2'yi yalnızca P1 S1 ifadesi


yürütüldükten sonra olan sinyali(synch) çağırdıktan sonra yürütecektir .

6.6.2 Semafor Uygulaması

Bölüm 6.5'te tartışılan muteks kilitlerinin uygulanmasının yoğun beklemeden


muzdarip olduğunu hatırlayın. Biraz önce açıklanan wait() ve sinyal() semafor
işlemlerinin tanımları aynı sorunu ortaya koymaktadır. Bu sorunu aşmak için wait()
ve sinyal() işlemlerinin tanımını aşağıdaki gibi değiştirebiliriz: Bir proses wait()
işlemini yürüttüğünde ve semafor değerinin pozitif olmadığını bulduğunda
beklemesi gerekir. Ancak, yoğun bir beklemeye girmek yerine süreç kendini askıya
alabilir. Askıya alma işlemi, bir işlemi semaforla ilişkili bir bekleme kuyruğuna
yerleştirir ve işlemin durumu, bekleme durumuna geçirilir. Ardından kontrol,
yürütülecek başka bir işlemi seçen CPU zamanlayıcısına aktarılır .

Askıya alınmış, S semaforunu bekleyen bir işlem, başka bir işlem bir sinyal()
işlemi yürüttüğünde yeniden başlatılmalıdır . İşlem , işlemi bekleme durumundan
hazır duruma değiştiren bir wakeup() işlemi ile yeniden başlatılır. İşlem daha sonra
hazır kuyruğa alınır. ( CPU programlama algoritmasına bağlı olarak CPU, çalışan
süreçten yeni hazır sürece geçebilir veya geçmeyebilir.)

Bu tanım altında semaforları uygulamak için aşağıdaki gibi bir semafor


tanımlarız:

typedef struct
{ int değer;
yapı süreci *listesi; }
semafor;

Her semaforun bir tamsayı değeri ve bir süreç listesi listesi vardır. Bir işlemin bir
semafor üzerinde beklemesi gerektiğinde, işlemler listesine eklenir. Bir sinyal()
işlemi, bekleyen işlemler listesinden bir işlemi kaldırır ve bu işlemi uyandırır.

Şimdi wait() semafor işlemi şu şekilde tanımlanabilir:

bekle(semafor *S) {
S->değer--;
if (S->değer < 0) { bu
işlemi S->listesine ekleyin;
uyumak();
}
}
Machine Translated by Google 6.6 Semaforlar 275

ve sinyal() semafor işlemi şu şekilde tanımlanabilir:

sinyal(semafor *S) {
S->değer++;
if (S->değer <= 0) {
S->listesinden bir P prosesini kaldırın ;
uyan);
}
}

sleep() işlemi , onu çağıran işlemi askıya alır. Uyandırma(P )


işlem, askıya alınmış bir işlem P'nin yürütülmesini sürdürür. Bu iki işlem, işletim sistemi
tarafından temel sistem çağrıları olarak sağlanır.
Bu uygulamada semafor değerlerinin negatif olabileceğini unutmayın.
semafor değerleri ise klasik tanımın altında asla negatif değildir.
meşgul bekleme ile semaforlar. Bir semafor değeri negatifse, büyüklüğü
o semaforda bekleyen işlemlerin sayısıdır. Bu gerçek şundan kaynaklanır:
azaltma sırasının değiştirilmesi ve testin uygulanmasında test
bekle() işlemi.
Bekleyen işlemlerin listesi, içindeki bir bağlantı alanı ile kolayca uygulanabilir.
her bir proses kontrol bloğu (PCB). Her semafor bir tamsayı değeri içerir ve
PCB listesi için bir işaretçi . Listeye işlem eklemenin ve listeden işlem kaldırmanın bir yolu
Sınırlı beklemeyi sağlamak için, semaforun olduğu bir FIFO kuyruğu kullanmaktır.
kuyruğa hem baş hem de kuyruk işaretçileri içerir. Ancak genel olarak liste
herhangi bir kuyruk stratejisi kullanabilir. Semaforların doğru kullanımı bağlı değildir
semafor listeleri için belirli bir kuyruğa alma stratejisi üzerinde.
Belirtildiği gibi, semafor işlemlerinin atomsal olarak yürütülmesi kritiktir. İki
işlemin aynı semafor üzerinde aynı anda wait() ve signal() işlemlerini
gerçekleştiremeyeceğini garanti etmeliyiz . Bu kritik bir bölüm problemidir ve tek
işlemcili bir ortamda, wait() ve sinyal() işlemleri sırasındaki kesmeleri basitçe engelleyerek
çözebiliriz.
yürütüyorlar. Bu şema, tek işlemcili bir ortamda çalışır çünkü,
kesintiler bir kez engellendiğinde, farklı süreçlerden gelen talimatlar kullanılamaz.
serpiştirilmiş. Kesintiler tamamlanana kadar yalnızca şu anda çalışan süreç yürütülür.
yeniden etkinleştirilir ve zamanlayıcı kontrolü yeniden kazanabilir.
Çok çekirdekli bir ortamda, her işlem çekirdeğinde kesintiler devre dışı bırakılmalıdır.
Aksi takdirde, farklı işlemlerden (farklı çekirdekler üzerinde çalışan) yönergeler keyfi bir
şekilde serpiştirilebilir. Kesintileri devre dışı bırakma
her çekirdekte zor bir görev olabilir ve performansı ciddi şekilde azaltabilir.
Bu nedenle, SMP sistemleri, wait() ve sinyal() 'in atomik olarak oluşturulmasını sağlamak
için karşılaştırma ve takas() veya döndürme kilitleri gibi alternatif teknikler sağlamalıdır.

Meşguliyeti tamamen ortadan kaldırmadığımızı kabul etmek önemlidir.


wait() ve sinyal() işlemlerinin bu tanımıyla beklemek. Yerine,
giriş bölümünden kritik bölümlere beklemekle meşgul olduk
uygulama programlarındandır. Ayrıca, beklemekle sınırlı bir meşguliyetimiz var.
wait() ve signal() işlemlerinin kritik bölümleri ve bu bölümler
kısa (doğru kodlanmışlarsa, yaklaşık on talimattan fazla olmamalıdırlar).
Böylece kritik bölüm neredeyse hiç meşgul olmaz ve yoğun bekleme meydana gelir.
Machine Translated by Google

276 Bölüm 6 Senkronizasyon Araçları

nadiren ve daha sonra sadece kısa bir süre için. Kritik bölümleri uzun (dakikalar, hatta
saatler) olabilen veya neredeyse her zaman meşgul olabilen uygulama programlarında
tamamen farklı bir durum vardır. Bu gibi durumlarda, yoğun bekleme son derece
verimsizdir.

6.7 Monitörler

Semaforlar süreç senkronizasyonu için uygun ve etkili bir mekanizma sağlasalar da,
bunların yanlış kullanılması, tespit edilmesi zor olan zamanlama hatalarına neden
olabilir, çünkü bu hatalar yalnızca belirli yürütme dizileri gerçekleşirse gerçekleşir ve
bu diziler her zaman oluşmaz.
Üretici-tüketici sorununa çözümümüzde bir sayım kullanımında bu tür hataların
bir örneğini gördük (Bölüm 6.1). Bu örnekte, zamanlama sorunu çok nadiren
meydana geldi ve o zaman bile sayım değeri makul görünüyordu - yalnızca 1 ile. Yine
de, çözüm açıkça kabul edilebilir bir çözüm değil. Bu nedenle muteks kilitleri ve
semaforlar ilk etapta tanıtıldı.

Ne yazık ki, muteks kilitleri veya semaforlar kullanıldığında bu tür zamanlama


hataları meydana gelebilir. Nasıl olduğunu göstermek için, kritik bölüm probleminin
semafor çözümünü gözden geçiriyoruz. Tüm işlemler bir ikili semafor değişkeni
mutex'i paylaşır, bu değişken 1 olarak başlatılır. Her işlem , kritik bölüme girmeden
önce wait(mutex) ve daha sonra sinyal(mutex) yürütmelidir . Bu sıraya uyulmadığı
takdirde iki işlem aynı anda kritik bölümlerinde olabilir.
Ardından, ortaya çıkabilecek birkaç zorluğu listeliyoruz. Tek bir süreç iyi yönetilmese
bile bu zorlukların ortaya çıkacağını unutmayın . Bu duruma dürüst bir programlama
hatası veya işbirliği yapmayan bir programcı neden olabilir.

• Bir programın , semafor muteksindeki wait() ve signal() işlemlerinin yürütüldüğü


sırayı değiştirdiğini ve bunun sonucunda aşağıdaki yürütmeyle sonuçlandığını
varsayalım:

sinyal(mutex);
...
kritik Bölüm
...
bekle(mutex);

Bu durumda, birkaç işlem kritik bölümlerinde aynı anda yürütülerek karşılıklı


dışlama gereksinimini ihlal ediyor olabilir. Bu hata, yalnızca kritik bölümlerinde
aynı anda birkaç işlem etkinse keşfedilebilir. Bu durumun her zaman tekrarlanabilir
olmayabileceğini unutmayın.

• Bir programın sinyal(mutex) ' i wait(mutex ) ile değiştirdiğini varsayalım . O


olduğunu, yürütür

bekle(mutex);
...
kritik Bölüm
...
bekle(mutex);
6.7 Monitörler 277
Machine Translated by Google

Bu durumda, semafor artık kullanılamadığından , süreç ikinci wait()


çağrısını kalıcı olarak engeller . • Bir işlemin wait(mutex) veya
sinyali(mutex) veya her ikisini de atladığını varsayalım . Bu durumda,
karşılıklı dışlama ihlal edilir veya süreç kalıcı olarak engellenir.

Bu örnekler, programcılar kritik bölüm problemini çözmek için semaforları


veya muteks kilitlerini yanlış kullandıklarında çeşitli hata türlerinin kolayca
üretilebileceğini göstermektedir. Bu tür hatalarla başa çıkmak için bir
strateji, basit senkronizasyon araçlarını üst düzey dil yapıları olarak dahil
etmektir. Bu bölümde, temel bir üst düzey senkronizasyon yapısını
açıklıyoruz: monitör tipi.

6.7.1 Monitör Kullanımı


Soyut bir veri türü (veya ADT), ADT'nin herhangi bir özel uygulamasından
bağımsız olarak bu veriler üzerinde çalışacak bir dizi işlevle verileri
kapsüller . Bir monitör türü , monitör içinde karşılıklı dışlama ile sağlanan
bir dizi programcı tanımlı işlemi içeren bir ADT'dir . Monitör tipi ayrıca
değerleri bir sistemin durumunu tanımlayan değişkenleri de bildirir.

monitör adı {

/* paylaşılan değişken bildirimleri */

fonksiyon P1 (...) {
...
}

fonksiyon P2 (...) {
...
}
.
.
.
fonksiyon Pn (...) {
...
}

başlatma kodu ( ...) {


...
}
}

Şekil 6.11 Bir monitörün sözde kod sözdizimi.


Machine Translated by Google

278 Bölüm 6 Senkronizasyon Araçları

bu değişkenler üzerinde çalışan işlevlerin gövdeleriyle birlikte bu türün örneği. Bir


monitör tipinin sözdizimi Şekil 6.11'de gösterilmektedir. Bir monitör tipinin temsili,
çeşitli işlemler tarafından doğrudan kullanılamaz.
Bu nedenle, bir monitör içinde tanımlanan bir işlev, yalnızca monitör içinde yerel
olarak bildirilen değişkenlere ve onun resmi parametrelerine erişebilir. Benzer
şekilde, bir monitörün yerel değişkenlerine yalnızca yerel işlevler tarafından erişilebilir.
Monitör yapısı, monitör içinde aynı anda yalnızca bir işlemin etkin olmasını
sağlar. Sonuç olarak, programcının bu senkronizasyon kısıtlamasını açıkça
kodlamasına gerek yoktur (Şekil 6.12). Ancak, şimdiye kadar tanımlandığı gibi monitör
yapısı, bazı senkronizasyon şemalarını modellemek için yeterince güçlü değildir.
Bunun için ek senkronizasyon mekanizmaları tanımlamamız gerekiyor. Bu
mekanizmalar, koşul yapısı tarafından sağlanır . Kişiye özel bir senkronizasyon
şeması yazması gereken bir programcı, bir veya daha fazla tip koşulu değişkeni
tanımlayabilir :

koşul x, y;

Bir koşul değişkeninde çağrılabilecek işlemler yalnızca wait() ve sinyal()'dir.


Operasyon

x.bekle();

bu işlemi çağıran işlemin başka bir işlem çağırana kadar askıya alındığı anlamına
gelir.

x.sinyal();

giriş kuyruğu

paylaşılan veri

...

operasyonlar

başlatma kodu

Şekil 6.12 Bir monitörün şematik görünümü.


Machine Translated by Google

6.7 Monitörler 279

x.signal () işlemi, tam olarak askıya alınmış bir işlemi sürdürür. Hiçbir işlem askıya alınmazsa,
signal() işleminin hiçbir etkisi olmaz; yani x'in durumu, işlem hiç yapılmamış gibidir (Şekil 6.13). Bu
işlemi , her zaman semaforun durumunu etkileyen semaforlarla ilişkili sinyal() işlemiyle karşılaştırın.

Şimdi, x.signal() işlemi bir P işlemi tarafından çağrıldığında , x koşuluyla ilişkili askıya alınmış
bir Q işlemi olduğunu varsayalım. Açıkça, askıya alınan Q işleminin yürütülmesine devam etmesine
izin verilirse, sinyalleme işlemi P'nin beklemesi gerekir. Aksi takdirde, monitör içinde hem P hem
de Q aynı anda etkin olacaktır. Bununla birlikte, kavramsal olarak her iki işlemin de yürütülmesine
devam edebileceğini unutmayın. İki olasılık mevcuttur:

1. Sinyal verin ve bekleyin. P ya Q monitörden ayrılana kadar bekler ya da


başka bir koşul.

2. Sinyal verin ve devam edin. Q ya P monitörden ayrılana kadar bekler ya da başka bir koşul için
bekler.

Her iki seçeneğin de benimsenmesi lehine makul argümanlar vardır. Bir yandan, P monitörde
zaten yürütülüyor olduğundan, sinyal ve devam yöntemi daha makul görünüyor. Öte yandan,
eğer P parçacığının devam etmesine izin verirsek, o zaman Q devam ettirildiğinde, Q'nun
beklediği mantıksal koşul artık geçerli olmayabilir. Bu iki seçenek arasında bir uzlaşma da
mevcuttur: P ipliği sinyal işlemini yürüttüğünde, hemen monitörden ayrılır. Bu nedenle, Q hemen
devam ettirilir.

giriş kuyruğu

paylaşılan veri

x, y koşullarıyla ilişkili kuyruklar x


y

•••

operasyonlar

başlatma kodu

Şekil 6.13 Koşul değişkenleriyle izleme.


280 Bölüm 6 Senkronizasyon Araçları
Machine Translated by Google

Java ve C# dahil olmak üzere birçok programlama dili, bu bölümde açıklandığı


gibi monitör fikrini birleştirmiştir. Erlang gibi diğer diller, benzer bir mekanizma
kullanarak eşzamanlılık desteği sağlar.

6.7.2 Semaforları Kullanarak Bir Monitör Uygulaması

Şimdi semaforlar kullanarak izleme mekanizmasının olası bir uygulamasını


düşünüyoruz. Her monitör için, karşılıklı dışlamayı sağlamak için bir ikili semafor
muteks (1 olarak başlatılır) sağlanır. Bir işlem , monitöre girmeden önce wait(mutex)
yürütmeli ve monitörden ayrıldıktan sonra sinyal(mutex) yürütmeli.

Uygulamamızda sinyal ve bekle şemasını kullanacağız. Bir sinyalleşme süreci,


devam ettirilen süreç ayrılana veya bekleyene kadar beklemek zorunda olduğundan,
daha sonra ek bir ikili semafor eklenir, 0'a başlatılır. Sinyalleme süreçleri kendilerini
askıya almak için next'i kullanabilir . Bir sonrakinde askıya alınan işlemlerin sayısını
saymak için bir sonraki sayım tamsayı değişkeni de sağlanır . Böylece, her harici
fonksiyon F ile değiştirilir
bekle(mutex);
...
F'nin gövdesi
...
if (sonraki sayı > 0)
sinyali(sonraki);
başka

sinyal(mutex);
Bir monitör içinde karşılıklı dışlama sağlanır.
Artık koşul değişkenlerinin nasıl uygulandığını da tanımlayabiliriz.
Her x koşulu için , her ikisi de 0'a ayarlanmış bir x sem ikili semaforu ve bir tamsayı
değişkeni x sayısı tanıtıyoruz. x.wait() işlemi artık şu şekilde uygulanabilir:

x sayısı++;
if (sonraki sayı > 0)
sinyali(sonraki);
başka sinyal(mutex);
bekle(x sem); x
sayısı--;

x.signal() işlemi şu şekilde uygulanabilir:

if (x sayısı > 0)
{ sonraki sayı++;
sinyal(x sem);
bekle(sonraki);
sonraki sayı--;
}

Bu uygulama, hem Hoare hem de Brinch-Hansen tarafından verilen monitör


tanımları için geçerlidir (bölümün sonundaki bibliyografik notlara bakınız). Bununla
birlikte, bazı durumlarda, uygulamanın genelliği,
Machine Translated by Google

6.7 Monitörler 281

ResourceAllocator'ı izleyin {

boole meşgul;
koşul x;

void gain(int time) { if (meşgul)


x.wait(time); meşgul = doğru;

void yayın() { meşgul


= yanlış; x.sinyal();

başlatma kodu() { meşgul =


yanlış;
}
}

Şekil 6.14 Tek bir kaynağı tahsis etmek için bir monitör.

gereksizdir ve verimlilikte önemli bir gelişme mümkündür. Bu problemi Alıştırma


6.27'de size bırakıyoruz.

6.7.3 Bir Monitörde Süreçleri Sürdürme


Şimdi bir monitörde süreç-yeniden başlatma sırası konusuna dönüyoruz. x
koşulunda birkaç işlem askıya alınırsa ve bazı işlemler tarafından bir x.signal() işlemi
yürütülürse, askıya alınan işlemlerden hangisinin daha sonra devam ettirileceğini
nasıl belirleriz? Basit bir çözüm, ilk gelen ilk hizmet alır (FCFS) siparişini kullanmaktır,
böylece en uzun süredir bekleyen işleme ilk önce devam edilir. Ancak birçok
durumda bu kadar basit bir zamanlama şeması yeterli değildir. Bu durumlarda,
koşullu bekleme yapısı kullanılabilir. Bu yapı forma sahiptir

x.bekle(c);

burada c , wait() işlemi yürütüldüğünde değerlendirilen bir tamsayı ifadesidir .


Öncelik numarası olarak adlandırılan c değeri daha sonra askıya alınan işlemin
adıyla birlikte saklanır. x.signal () yürütüldüğünde, en küçük öncelik numarasına
sahip işleme devam edilir.
Bu yeni mekanizmayı göstermek için, Şekil 6.14'te gösterilen ve rekabet eden
süreçler arasında tek bir kaynağın tahsisini kontrol eden ResourceAllocator
monitörünü düşünün. Her süreç, bu kaynağın tahsisini talep ederken, kaynağı
kullanmayı planladığı maksimum süreyi belirtir. Monitör, kaynağı en kısa zaman
tahsisine sahip prosese tahsis eder.
Machine Translated by Google

282 Bölüm 6 Senkronizasyon Araçları

rica etmek. Söz konusu kaynağa erişmesi gereken bir işlem aşağıdaki sırayı
izlemelidir:

R.acquire(t);
...
kaynağa erişin;
...
R.release();

burada R , ResourceAllocator türünün bir örneğidir .


Ne yazık ki, monitör konsepti, önceki erişim sırasının gözlemleneceğini garanti
edemez. Özellikle, aşağıdaki problemler
meydana gelmek:

• Bir işlem, önce kaynağa erişim izni almadan bir kaynağa erişebilir.

• Bir işleme, kaynağa erişim izni verildikten sonra bir kaynağı asla serbest
bırakmayabilir.

• Bir süreç, hiç talep etmediği bir kaynağı serbest bırakmaya çalışabilir. • Bir

işlem aynı kaynağı iki kez isteyebilir (ilk serbest bırakmadan


kaynak).

Semaforların kullanımında da aynı zorluklarla karşılaşılır ve bu zorluklar doğası


gereği bizi monitör yapılarını geliştirmeye teşvik edenlere benzer. Önceden,
semaforların doğru kullanımı konusunda endişelenmemiz gerekiyordu. Şimdi,
derleyicinin artık bize yardımcı olamayacağı daha yüksek seviyeli programcı tanımlı
işlemlerin doğru kullanımı konusunda endişelenmemiz gerekiyor.

Mevcut soruna olası bir çözüm, kaynak erişim işlemlerini ResourceAllocator


izleyicisine dahil etmektir. Ancak bu çözümü kullanmak, programlamanın bizim
kodladığımızdan ziyade yerleşik monitör zamanlama algoritmasına göre yapılması
anlamına gelecektir.
Süreçlerin uygun sıraları gözlemlediğinden emin olmak için, ResourceAllocator
izleyicisini ve onun yönetilen kaynağını kullanan tüm programları incelememiz
gerekir. Bu sistemin doğruluğunu belirlemek için iki koşulu kontrol etmeliyiz. İlk
olarak, kullanıcı süreçleri çağrılarını her zaman monitörde doğru sırayla yapmalıdır.
İkinci olarak, işbirlikçi olmayan bir sürecin, monitör tarafından sağlanan karşılıklı
dışlama ağ geçidini görmezden gelmediğinden ve erişim protokollerini kullanmadan
doğrudan paylaşılan kaynağa erişmeye çalışmadığından emin olmalıyız. Ancak bu
iki koşul sağlandığında zamana bağlı hiçbir hatanın olmayacağını ve çizelgeleme
algoritmasının yenilmeyeceğini garanti edebiliriz.

Bu inceleme küçük, statik bir sistem için mümkün olsa da, büyük bir sistem veya
dinamik bir sistem için makul değildir. Bu erişim denetimi sorunu, yalnızca Bölüm
17'de açıklanan ek mekanizmaların kullanılmasıyla çözülebilir.
Machine Translated by Google

6.8 Canlılık 283

6.8 Canlılık

Kritik erişime erişimi koordine etmek için senkronizasyon araçlarını kullanmanın bir sonucu
bölümler, kritik bölümüne girmeye çalışan bir sürecin olasılığıdır.
süresiz olarak bekleyecektir. Hatırlayın, Bölüm 6.2'de aşağıdaki üç kriteri özetledik:
kritik-kesit probleminin çözümleri tatmin etmelidir. Süresiz bekleme ihlalleri
bunlardan ikisi - ilerleme ve sınırlı bekleme kriterleri.
Canlılık , bir sistemin sağlamak için karşılaması gereken bir dizi özelliği ifade eder.
süreçlerin yürütme yaşam döngüleri boyunca ilerleme kaydettiğini gösterir. Az önce
açıklanan koşullar altında süresiz olarak bekleyen bir süreç, bir örnektir.
"canlılık başarısızlığı."
Canlılık yetmezliğinin birçok farklı biçimi vardır; bununla birlikte, tümü genellikle
düşük performans ve yanıt verme ile karakterize edilir. çok basit
canlılık hatası örneği sonsuz bir döngüdür. Meşgul bir bekleme döngüsü şunları sunar:
bir canlılık hatası olasılığı , özellikle bir süreç keyfi olarak döngüye giriyorsa
uzun bir süre. gibi araçları kullanarak karşılıklı dışlama sağlama çabaları
muteks kilitleri ve semaforlar genellikle eşzamanlı programlamada bu tür hatalara yol
açabilir. Bu bölümde, canlılığa yol açabilecek iki durumu araştırıyoruz.
başarısızlıklar

6.8.1 Kilitlenme
Bir bekleme kuyruğuna sahip bir semaforun uygulanması,
iki veya daha fazla sürecin bir olay için süresiz olarak beklediği durum
bu sadece bekleme süreçlerinden biri tarafından kaynaklanabilir. Söz konusu olay
bir sinyal() işleminin yürütülmesidir. Böyle bir duruma gelindiğinde, bunlar
süreçlerin kilitlendiği söyleniyor .
Bunu göstermek için, P0 ve P1 olmak üzere iki süreçten oluşan bir sistem düşünün.
her biri S ve Q olmak üzere iki semafora erişir, 1 değerine ayarlanır:

P0 P1
bekle(ler); bekle(Q);
bekle(Q); bekle(ler);
. .
. .
. .
sinyal(ler); sinyal(Q);
sinyal(Q); sinyal(ler);

P0'ın wait(S)' i ve ardından P1'in wait (Q)' u yürüttüğünü varsayalım . P0 olduğunda


wait(Q) yürütür , P1 sinyali(Q) yürütene kadar beklemelidir . Benzer şekilde, ne zaman
P1 wait(S) işlemini yürütür , P0 sinyali(S) yürütene kadar beklemelidir . Bunlardan dolayı
sinyal() işlemleri yürütülemez, P0 ve P1 kilitlenir.
Bir süreç kümesinin, her süreç her bir süreç için kilitlenme durumunda olduğunu söylüyoruz.
kümede yalnızca başka bir işlemin neden olabileceği bir olayı bekliyor.
Ayarlamak. Burada esas olarak ilgilendiğimiz “olaylar”, satın alma işlemleridir.
ve muteks kilitleri ve semaforlar gibi kaynakların serbest bırakılması. Diğer türleri
Bölüm 8'de daha ayrıntılı olarak gösterdiğimiz gibi, olaylar kilitlenmelere neden olabilir.
Machine Translated by Google

284 Bölüm 6 Senkronizasyon Araçları

bu bölümde, kilitlenme sorunuyla başa çıkmak için çeşitli mekanizmaların yanı sıra
diğer canlılık arızaları biçimlerini açıklıyoruz.

6.8.2 Öncelik Ters Çevirme

Daha yüksek öncelikli bir sürecin, şu anda daha düşük öncelikli bir süreç veya daha
düşük öncelikli bir süreç zinciri tarafından erişilmekte olan çekirdek verilerini
okuması veya değiştirmesi gerektiğinde bir zamanlama zorluğu ortaya çıkar.
Çekirdek verileri tipik olarak bir kilitle korunduğundan, yüksek öncelikli işlemin
daha düşük öncelikli olanın kaynakla bitmesini beklemesi gerekecektir. Düşük
öncelikli süreç, daha yüksek önceliğe sahip başka bir süreç lehine önlenirse durum
daha karmaşık hale gelir.
Örnek olarak, öncelikleri L < M < H sırasını izleyen üç sürecimiz (L, M ve H)
olduğunu varsayalım. H sürecinin , şu anda L süreci tarafından erişilen bir S
semaforu gerektirdiğini varsayalım . Normal olarak, H süreci L'nin S kaynağını
kullanarak bitirmesini beklerdi . Bununla birlikte, şimdi M sürecinin çalıştırılabilir
hale geldiğini ve dolayısıyla L sürecini önlediğini varsayalım . Dolaylı olarak, daha
düşük önceliğe sahip bir süreç – M süreci – H sürecinin L' nin kaynaktan vazgeçmesi
için ne kadar beklemesi gerektiğini etkilemiştir . S.
Bu canlılık sorunu önceliğin tersine çevrilmesi olarak bilinir ve yalnızca ikiden
fazla önceliği olan sistemlerde ortaya çıkabilir. Tipik olarak, bir öncelik kalıtım
protokolü uygulanarak önceliğin tersine çevrilmesi önlenir . Bu protokole göre,
daha yüksek öncelikli bir işlemin ihtiyaç duyduğu kaynaklara erişen tüm işlemler,
söz konusu kaynaklarla bitene kadar daha yüksek önceliği devralır. Bitirdiklerinde
öncelikleri orijinal değerlerine döner.
Yukarıdaki örnekte, bir öncelik devralma protokolü, L işleminin H işleminin
önceliğini geçici olarak devralmasına izin verecek ve böylece M işleminin
yürütülmesini engellemesini önleyecektir. L işlemi , S kaynağını kullanmayı
bitirdiğinde , H'den devralınan önceliğinden vazgeçecek ve orijinal önceliğini üstlenecektir.
S kaynağı artık kullanılabilir olacağından, M değil, H süreci çalışırdı.
sonraki.

6.9 Değerlendirme

Kritik bölüm problemini çözmek için kullanılabilecek birkaç farklı senkronizasyon


aracı tanımladık. Doğru uygulama ve kullanım göz önüne alındığında, bu araçlar,
canlılık sorunlarını ele almanın yanı sıra karşılıklı dışlamayı sağlamak için etkin bir
şekilde kullanılabilir. Modern çok çekirdekli bilgisayar sistemlerinin gücünden
yararlanan eşzamanlı programların büyümesiyle, senkronizasyon araçlarının
performansına artan bir ilgi gösteriliyor. Bununla birlikte, hangi aracın ne zaman
kullanılacağını belirlemeye çalışmak göz korkutucu bir zorluk olabilir. Bu bölümde,
belirli senkronizasyon araçlarının ne zaman kullanılacağını belirlemek için bazı
basit stratejiler sunuyoruz.
Bölüm 6.4'te özetlenen donanım çözümlerinin çok düşük düzeyde olduğu
kabul edilir ve genellikle muteks kilitleri gibi diğer senkronizasyon araçlarının
oluşturulması için temel olarak kullanılır. Bununla birlikte, son zamanlarda , kilitleme
ek yükü gerektirmeden yarış koşullarından koruma sağlayan kilitsiz algoritmalar
oluşturmak için CAS talimatını kullanmaya odaklanılmıştır .
Bu kilitsiz çözümler, düşük ek yük nedeniyle popülerlik kazanıyor olsa da
Machine Translated by Google

6.9 Değerlendirme 285

ÖNCELİKLİ DÖNÜŞ VE MARS PATHFINDER

Önceliğin tersine çevrilmesi, bir zamanlama sıkıntısından daha fazlası olabilir. Gerçek zamanlı
sistemler gibi sıkı zaman kısıtlamaları olan sistemlerde, önceliğin tersine çevrilmesi, bir işlemin
bir görevi tamamlaması gerekenden daha uzun sürmesine neden olabilir. Bu olduğunda, diğer
arızalar kademeli olarak sistem arızasına neden olabilir.
1997'de deneyler yapmak için bir robot olan Sojourner gezginini Mars'a indiren bir NASA uzay
sondası olan Mars Pathfinder'ı düşünün . Sojourner çalışmaya başladıktan kısa bir süre sonra,
sık sık bilgisayar sıfırlamaları yaşamaya başladı.
Her sıfırlama, iletişimler de dahil olmak üzere tüm donanım ve yazılımı yeniden başlattı. Sorun
çözülmemiş olsaydı, Sojourner görevinde başarısız olacaktı.

Sorun, yüksek öncelikli bir görev olan "bc dist"in işini tamamlamasının beklenenden uzun
sürmesinden kaynaklanıyordu. Bu görev, daha düşük öncelikli “ASI/MET” görevi tarafından
tutulan ve daha sonra birden fazla orta öncelikli görev tarafından önlenen paylaşılan bir kaynağı
beklemeye zorlanıyordu. "bc dist" görevi paylaşılan kaynağı beklemeyi durdurur ve nihayetinde
"bc sched" görevi sorunu keşfeder ve sıfırlamayı gerçekleştirir. Sojourner, tipik bir öncelikli ters
çevirme durumundan muzdaripti.

Sojourner'daki işletim sistemi, tüm semaforlarda öncelikli kalıtımı etkinleştirmek için global
bir değişkene sahip olan VxWorks gerçek zamanlı işletim sistemiydi. Testten sonra, değişken
Sojourner'a (Mars'ta!) ayarlandı ve sorun çözüldü.

Sorunun tam açıklaması, tespiti ve çözümü yazılım ekibi lideri


tarafından yazılmıştır ve http://research.microsoft.com/en-us/um/people/
mbj/mars pathfinder/ yetkili hesabında mevcuttur. .html.

ve ölçekleme yeteneği, algoritmaların kendilerinin geliştirilmesi ve test edilmesi


genellikle zordur. (Bu bölümün sonundaki alıştırmalarda, kilitsiz bir yığının doğruluğunu
değerlendirmenizi istiyoruz.)
CAS tabanlı yaklaşımlar iyimser bir yaklaşım olarak kabul edilir; önce bir değişkeni
optiistik olarak güncellersiniz ve ardından başka bir iş parçacığının değişkeni aynı anda
güncelleyip güncellemediğini görmek için çakışma algılamayı kullanırsınız. Öyleyse,
çakışma olmadan başarıyla güncellenene kadar işlemi tekrar tekrar denersiniz. Karşılıklı
dışlama kilitleme, aksine, karamsar bir strateji olarak kabul edilir; başka bir iş parçacığının
aynı anda değişkeni güncellediğini varsayarsınız, bu nedenle herhangi bir güncelleme
yapmadan önce kötümser bir şekilde kilidi alırsınız.
Aşağıdaki yönergeler , değişen çekişme yükleri altında CAS tabanlı senkronizasyon
ile geleneksel senkronizasyon (mutex kilitleri ve semaforlar gibi) arasındaki performans
farklılıklarına ilişkin genel kuralları tanımlar:

• Tartışmasız. Her iki seçenek de genellikle hızlı olsa da, CAS koruması
geleneksel senkronizasyondan biraz daha hızlı olacaktır.

• Orta düzeyde çekişme. CAS koruması, geleneksel senkronizasyondan daha hızlı,


muhtemelen çok daha hızlı olacaktır.
Machine Translated by Google

286 Bölüm 6 Senkronizasyon Araçları

• Yüksek çekişme. Çok yüksek düzeyde çekişmeli yükler altında, geleneksel


senkronizasyon, sonuçta CAS tabanlı senkronizasyondan daha hızlı olacaktır.

Ilımlı çekişme incelemek özellikle ilginçtir. Bu senaryoda, CAS işlemi çoğu


zaman başarılı olur ve başarısız olduğunda, sonuçta başarılı olmadan önce Şekil
6.8'de gösterilen döngü boyunca yalnızca birkaç kez yinelenir. Karşılaştırıldığında,
karşılıklı dışlama kilitleme ile karşılaştırıldığında, herhangi bir çekişmeli kilit elde
etme girişimi, bir iş parçacığını askıya alan ve onu bir bekleme kuyruğuna
yerleştiren ve başka bir iş parçacığına bağlam geçişi gerektiren daha karmaşık ve
zaman yoğun bir kod yolu ile sonuçlanacaktır.
Yarış koşullarına hitap eden bir mekanizmanın seçimi de sistem performansını
büyük ölçüde etkileyebilir. Örneğin, atomik tamsayılar, geleneksel kilitlerden çok
daha hafiftir ve genellikle, sayaçlar gibi paylaşılan değişkenlere yönelik tek
güncellemeler için muteks kilitlerinden veya semaforlardan daha uygundur.
Bunu, kilitler kısa süreliğine tutulduğunda çok işlemcili sistemlerde döndürme
kilitlerinin kullanıldığı işletim sistemlerinin tasarımında da görüyoruz. Genel olarak,
muteks kilitleri daha basittir ve semaforlardan daha az ek yük gerektirir ve kritik bir
bölüme erişimi korumak için ikili semaforlara tercih edilir.
Ancak, sınırlı sayıda kaynağa erişimi denetlemek gibi bazı kullanımlar için bir sayma
semaforu genellikle bir muteks kilidinden daha uygundur. Benzer şekilde, bazı
durumlarda, daha yüksek derecede eşzamanlılığa (yani, birden çok okuyucuya) izin
verdiği için, bir muteks kilidi yerine bir okuyucu-yazıcı kilidi tercih edilebilir.

Monitörler ve koşul değişkenleri gibi daha üst düzey araçların çekiciliği,


basitliklerine ve kullanım kolaylıklarına dayanmaktadır. Bununla birlikte, bu tür
araçların önemli bir ek yükü olabilir ve uygulamalarına bağlı olarak, çok çekişmeli
durumlarda ölçeklenme olasılığı daha düşük olabilir.
Neyse ki, eşzamanlı programlamanın taleplerini karşılayan ölçeklenebilir, verimli
araçlar geliştirmeye yönelik devam eden çok sayıda araştırma var. Bazı örnekler
şunları içerir:

• Daha verimli kod üreten derleyiciler tasarlamak. • Eşzamanlı


programlama için destek sağlayan diller geliştirmek. • Mevcut kitaplıkların ve
API'lerin performansının iyileştirilmesi .

Sonraki bölümde, geliştiricilere sunulan çeşitli işletim sistemlerinin ve API'lerin


bu bölümde sunulan senkronizasyon araçlarını nasıl uyguladığını inceleyeceğiz.

6.10 Özet
• Süreçler paylaşılan verilere eşzamanlı erişime sahip olduğunda ve nihai sonuç,
eşzamanlı erişimlerin gerçekleştiği belirli sıraya bağlı olduğunda bir yarış
durumu oluşur. Yarış koşulları, paylaşılan verilerin değerlerinin bozulmasına
neden olabilir.

• Kritik bölüm, paylaşılan verilerin değiştirilebileceği ve olası bir yarış


durumunun oluşabileceği bir kod bölümüdür. kritik bölüm sorunu
Machine Translated by Google

Alıştırmalar 287

süreçlerin işbirliği içinde veri paylaşmak için etkinliklerini senkronize edebileceği


bir protokol tasarlamaktır.

• Kritik bölüm sorununa bir çözüm, aşağıdaki üç gereksinimi karşılamalıdır: (1)


karşılıklı dışlama, (2) ilerleme ve (3) sınırlı bekleme.
Karşılıklı dışlama, kritik bölümünde aynı anda yalnızca bir işlemin etkin olmasını
sağlar. İlerleme, programların işbirliği içinde hangi sürecin kritik bölümüne
gireceğini belirlemesini sağlar. Sınırlı bekleme, bir programın kritik bölümüne
girmeden önce ne kadar bekleyeceğini sınırlar. • Peterson'ın çözümü gibi kritik

bölüm sorununa yönelik yazılım çözümleri, modern bilgisayar mimarilerinde iyi


çalışmaz.

• Kritik bölüm sorunu için donanım desteği, bellek engellerini içerir; karşılaştır ve
değiştir talimatı gibi donanım talimatları; ve atomik değişkenler.

• Bir muteks kilidi, bir işlemin kritik bir bölüme girmeden önce bir kilit almasını ve
kritik bölümden çıkarken kilidi serbest bırakmasını gerektirerek karşılıklı dışlama
sağlar.

• Mutex kilitleri gibi semaforlar, karşılıklı dışlama sağlamak için kullanılabilir.


Bununla birlikte, bir muteks kilidi, kilidin mevcut olup olmadığını gösteren ikili
bir değere sahipken, bir semaforun bir tamsayı değeri vardır ve bu nedenle
çeşitli senkronizasyon problemlerini çözmek için kullanılabilir.

• Monitör, yüksek düzeyde bir süreç senkronizasyonu sağlayan soyut bir veri
türüdür. Bir monitör, süreçlerin belirli koşulların gerçekleşmesini beklemesine ve
koşullar doğru olarak ayarlandığında birbirlerine sinyal vermesine izin veren
koşul değişkenlerini kullanır.

• Kritik bölüm sorununun çözümleri, canlılık probleminden zarar görebilir.


kilitlenme dahil lemler.

• Kritik bölüm problemini çözmenin yanı sıra süreçlerin aktivitesini senkronize etmek
için kullanılabilecek çeşitli araçlar, farklı çekişme seviyeleri altında
değerlendirilebilir. Bazı araçlar, belirli çekişme yükleri altında diğerlerinden
daha iyi çalışır.

Alıştırmalar

6.1 Bölüm 6.4'te, kesintileri sık sık devre dışı bırakmanın sistem saatini
etkileyebileceğini belirtmiştik. Bunun neden olabileceğini ve bu etkilerin nasıl
en aza indirilebileceğini açıklayın.

6.2 Meşgul beklemek deyiminin anlamı nedir ? Bir işletim sisteminde başka ne tür
beklemeler vardır? Meşgul beklemekten tamamen kaçınılabilir mi? Cevabını
açıkla.

6.3 Spinlock'ların neden tek işlemcili sistemler için uygun olmadığını, ancak çok
işlemcili sistemlerde sıklıkla kullanıldığını açıklayın.

6.4 Wait() ve signal() semafor işlemleri atomik olarak yürütülmezse, karşılıklı


dışlamanın ihlal edilebileceğini gösterin .
Machine Translated by Google

288 Bölüm 6 Senkronizasyon Araçları

6.5 n süreç arasında karşılıklı dışlamayı uygulamak için ikili bir semaforun nasıl
kullanılabileceğini gösterin .
6.6 Yarış koşulları birçok bilgisayar sisteminde mümkündür. İki işlevi olan bir
hesap bakiyesini koruyan bir bankacılık sistemi düşünün: yatırma(tutar) ve
çekme(tutar). Bu iki işlev , banka hesap bakiyesinden yatırılacak veya çekilecek
tutar iletilir. Bir karı kocanın bir banka hesabını paylaştığını varsayalım.

Eşzamanlı olarak, koca geri çekme() işlevini çağırır ve kadın depozito() işlevini
çağırır. Bir yarış koşulunun nasıl mümkün olduğunu ve yarış koşulunun
oluşmasını önlemek için neler yapılabileceğini açıklayın.

Daha fazla okuma

Karşılıklı dışlama sorunu ilk olarak [Dijk stra (1965)] tarafından klasik bir makalede
tartışıldı. Semafor kavramı [Dijkstra (1965)] tarafından önerildi. Monitör konsepti
[Brinch-Hansen (1973)] tarafından geliştirilmiştir. [Hoare (1974)] monitörün tam bir
tanımını verdi.
Mars Pathfinder sorunu hakkında daha fazla bilgi için bkz. http://research.microsoft.co
m/en-us/um/people/mbj/mars yol bulucu/yetkili hesap.html
Bellek engelleri ve önbellek hakkında kapsamlı bir tartışma [Mckenney (2010)]'de
sunulmuştur. [Herlihy ve Shavit (2012)], bellek modelleri ve karşılaştır ve değiştir
yönergeleri dahil olmak üzere çok işlemcili programlamayla ilgili çeşitli konular
hakkında ayrıntılar sunar. [Bahra (2013)] modern çok çekirdekli sistemlerde bloksuz
algoritmaları inceliyor.

bibliyografya

[Bahra (2013)] SA Bahra, “Engellemeyen Algoritmalar ve Ölçeklenebilir Çok Çekirdekli


Programlama”, ACM kuyruğu, Cilt 11, Sayı 5 (2013).

[Brinch-Hansen (1973)] P. Brinch-Hansen, İşletim Sistemi İlkeleri, Prentice


Hall (1973).

[Dijkstra (1965)] EW Dijkstra, “Cooperating Sequential Processes”, Teknik rapor,


Technological University, Eindhoven, Hollanda (1965).

[Herlihy ve Shavit (2012)] M. Herlihy ve N. Shavit, The Art of Multiprocessor Programming,


Revised First Edition, Morgan Kaufmann Publishers Inc. (2012).

[Hoare (1974)] CAR Hoare, “Monitörler: Bir İşletim Sistemi Yapılandırma Kavramı”,
Communications of the ACM, Cilt 17, Sayı 10 (1974), sayfa 549–557.

[Mckenney (2010)] PE Mckenney, “Bellek Engelleri: Yazılım Hackerları için Donanım


Görünümü” (2010).
Machine Translated by Google

EX-17

Bölüm 6 Alıştırmalar

6.7 Şekil 6.15'teki sözde kod, dizi tabanlı bir yığının temel push() ve pop()
işlemlerini gösterir. Bu algoritmanın eşzamanlı bir ortamda
kullanılabileceğini varsayarak aşağıdaki soruları yanıtlayın:
a. Hangi verilerin bir yarış durumu var?

b. Yarış durumu nasıl düzeltilebilir?

6.8 Yarış koşulları birçok bilgisayar sisteminde mümkündür. Her bir ürün
için mevcut en yüksek teklifin muhafaza edilmesi gereken bir
çevrimiçi müzayede sistemi düşünün. Bir öğeye teklif vermek
isteyen bir kişi, teklif edilen tutarı mevcut en yüksek teklifle
karşılaştıran teklif(tutar) işlevini çağırır. Tutar mevcut en yüksek
teklifi aşarsa, en yüksek teklif yeni tutara ayarlanır. Bu, aşağıda gösterilmiştir:
geçersiz teklif(çift tutar) {
if (tutar > en yüksek Teklif) en
yüksek Teklif = miktar;
}

push(item) { if
(üst < SIZE) { stack[top]
= item; üst++;

}
başka
HATA
}

pop() { if
(!is boş()) { üst--; yığını
döndür[üst];

}
başka
HATA
}

is empty() { if
(üst == 0)
true döndür; aksi
takdirde false
döndürür;
}

Şekil 6.16 Alıştırma 6.12 için dizi tabanlı yığın.


Machine Translated by Google

Egzersizler EX-18

5 10 15 20 3025 35 40
0 1234 5 67

+ + + +
5 15 15 35 25 55 35 75
0 1234 5 67

+ +
5 15 15 50 25 55 35 130
0 1234 5 67

+
5 15 15 50 25 55 35 180
0 1234 5 67

Şekil 6.17 Alıştırma 6.14 için bir diziyi kısmi toplamlar dizisi olarak toplamak.

Bu durumda bir yarış koşulunun nasıl mümkün olduğunu ve yarış


koşulunun oluşmasını önlemek için neler yapılabileceğini açıklayın.
6.9 Aşağıdaki program örneği, N bilgisayar çekirdeği içeren bir sistemde
paralel olarak N boyutlu öğelerin dizi değerlerini toplamak için
kullanılabilir (her dizi öğesi için ayrı bir işlemci vardır):
j = 1 için log 2(N) { for k =
1 ila N { if ((k + 1) %
pow(2,j) == 0) { değerler[k] +=
değerler[k - pow(2 ,(j-1))]
}
}
}

Bu, Şekil 6.16'da gösterildiği gibi dizideki öğeleri bir dizi kısmi toplam
olarak toplama etkisine sahiptir. Kod yürütüldükten sonra dizideki tüm
öğelerin toplamı son dizi konumunda saklanır.
Yukarıdaki kod örneğinde herhangi bir yarış koşulu var mı? Eğer öyleyse, nerede
meydana geldiklerini belirleyin ve bir örnekle açıklayın. Değilse, bu algoritmanın
neden yarış koşullarından bağımsız olduğunu gösterin.

6.10 Karşılaştırma ve takas() talimatı, yığınlar, kuyruklar ve listeler gibi kilitsiz


veri yapılarını tasarlamak için kullanılabilir. Şekil 6.17'de gösterilen
program örneği, yığının, üst yığının tepesini temsil eden Düğüm
öğelerinin bağlantılı bir listesi olarak temsil edildiği, CAS talimatlarını
kullanan kilitsiz bir yığın için olası bir çözüm sunar . Bu uygulama yarış
koşullarından bağımsız mı?
Machine Translated by Google

EX-19

typedef yapı düğümü { değer t


veri; yapı düğümü *sonraki;

} Düğüm;

Düğüm *üst; // yığının üstü

void push(değer t öğesi) {


Düğüm *eski düğüm;
Düğüm *yeni düğüm;

yeni düğüm = malloc(sizeof(Düğüm)); yeni


düğüm->veri = öğe;

do
{ eski düğüm = üst;
yeni düğüm->sonraki = eski düğüm;
}
while (karşılaştır ve değiştir(üst, eski düğüm, yeni düğüm) != eski düğüm);
}

değer t pop() {
Düğüm *eski düğüm;
Düğüm *yeni düğüm;

do
{ eski düğüm = üst; if
(eski düğüm == NULL) NULL
döndürür;
yeni düğüm = eski düğüm->sonraki;
}
while (karşılaştır ve değiştir(üst, eski düğüm, yeni düğüm) != eski düğüm);

eski düğüm-> verileri döndür;


}

Şekil 6.18 Alıştırma 6.15 için kilitsiz yığın.

6.11 Bir döndürme kilidi uygulamak için karşılaştırma ve takas() kullanımına yönelik bir
yaklaşım aşağıdaki gibidir:

void lock spinlock(int *lock) { while (karşılaştır ve


değiştir(lock, 0, 1) != 0)
; /* döndürmek */
}

Önerilen alternatif bir yaklaşım, kilidi çağırmadan önce kilidin durumunu


kontrol eden "karşılaştır ve karşılaştır ve değiştir" deyimini kullanmaktır.
Machine Translated by Google

Egzersizler EX-20

karşılaştır ve takas () işlemi. (Bu yaklaşımın arkasındaki mantık, yalnızca


kilit mevcutsa, karşılaştırma ve takas() işlevini çağırmaktır.)
Bu strateji aşağıda gösterilmiştir:

void kilit döndürme kilidi(int *kilit) { {

while (true) { if
(*lock == 0) {
/* kilit mevcut görünüyor */

if (!compare and swap(lock, 0, 1)) break;

}
}
}

Bu "karşılaştır ve karşılaştır ve değiştir" deyimi, döndürme kilitlerini uygulamak


için uygun şekilde çalışıyor mu? Eğer öyleyse, açıklayın. Değilse, kilidin
bütünlüğünün nasıl tehlikeye atıldığını gösterin.

6.12 Bazı semafor uygulamaları , bir semaforun geçerli değerini döndüren bir getValue()
işlevi sağlar. Bu işlev, örneğin, wait() işlevini çağırmadan önce çağrılabilir,
böylece bir işlem yalnızca semaforun değeri > 0 ise wait()' i çağırır ve böylece
semaforu beklerken engellemeyi önler. Örneğin:

if (getValue(&sem) > 0)
wait(&sem);

Birçok geliştirici böyle bir işleve karşı çıkar ve kullanımını caydırır.


Bu senaryoda getValue() işlevini kullanırken oluşabilecek olası bir sorunu
tanımlayın.

6.13 İki proses için kritik bölüm problemine bilinen ilk doğru yazılım çözümü Dekker
tarafından geliştirilmiştir. İki süreç, P0 ve P1, aşağıdaki değişkenleri paylaşır:

boole bayrağı[2]; /* başlangıçta false */ int


dönüş;
Pi işleminin yapısı (i == 0 veya 1) Şekil 6.18'de gösterilmektedir. Diğer süreç Pj'dir
(j == 1 veya 0). Algoritmanın kritik bölüm problemi için üç gereksinimi de
karşıladığını kanıtlayın.

6.14 n 1 dönüş beklemede alt sınırı olan n proses için kritik bölüm problemine bilinen
ilk doğru yazılım çözümü Eisenberg ve McGuire tarafından sunuldu. İşlemler
aşağıdaki değişkenleri paylaşır:

enum pstate {boşta, cs'de istiyor }; pstate


flag[n]; int dönüş;
Machine Translated by Google

EX-21

while (true)
{ flag[i] = true;

while (bayrak[j]) {
if (dönüş == j) {
bayrak[i] = yanlış;
while (dönüş == j) ; /
* hiçbir şey yapma */
flag[i] = true;
}
}

/* kritik Bölüm */

dönüş = j;
bayrak[i] = yanlış;

/* kalan kısım */
}

Şekil 6.19 Dekker algoritmasındaki Pi işleminin yapısı .

Bayrağın tüm öğeleri başlangıçta boştadır. Dönüşün ilk değeri önemsizdir


(0 ile n-1 arasında). Pi işleminin yapısı Şekil 6.19'da gösterilmektedir.
Algoritmanın kritik bölüm problemi için üç gereksinimi de karşıladığını
kanıtlayın.
6.15 Senkronizasyon temel öğeleri kullanıcı düzeyindeki programlarda kullanılacaksa,
tek işlemcili bir sistemde kesintileri devre dışı bırakarak eşitleme temel
öğelerinin uygulanmasının neden uygun olmadığını açıklayın.
6.16 Com pare ve swap() komutunu kullanarak bir muteks kilidinin nasıl
uygulanacağını düşünün . Mutex kilidini tanımlayan aşağıdaki yapının
mevcut olduğunu varsayalım:

typedef struct { int


kullanılabilir; }
kilitle;

Değer (mevcut == 0) , kilidin mevcut olduğunu ve 1 değeri, kilidin


kullanılamadığını gösterir. Bu yapıyı kullanarak, karşılaştırma ve takas()
talimatı kullanılarak aşağıdaki işlevlerin nasıl uygulanabileceğini gösterin:

• geçersiz edinme(kilit *mutex)


• geçersiz serbest bırakma(kilit *mutex)

Gerekli olabilecek herhangi bir başlatmayı eklediğinizden emin olun.


Machine Translated by Google

Egzersizler EX-22

while (true) { while


(true) { flag[i] =
istiyor; j = dönüş;

while (j != i) { if (flag[j] !
= boşta) { j = dönüş; başka

j = (j + 1) %n;
}

flag[i] = cs'de; j = 0;

while ( (j < n) && (j == i || flag[j] != cs'de))


j++;

if ( (j >= n) && (dönüş == i || bayrak[dönüş] == boşta))


kırmak;
}

/* kritik Bölüm */

j = (dönüş + 1) % n;

while (işaret[j] == boşta) j = (j


+ 1) % n;

dönüş = j;
bayrak[i] = boşta;

/* kalan kısım */
}

Şekil 6.20 Eisenberg ve McGuire algoritmasında Pi sürecinin yapısı .

6.17 Kesintilerin neden çok işlemcili sistemlerde senkronizasyon temel öğelerini


uygulamak için uygun olmadığını açıklayın.
6.18 Bölüm 6.5'te sağlanan muteks kilitlerinin uygulanması, yoğun beklemeden
muzdariptir. Bir muteks kilidi edinmeyi bekleyen bir işlemin bloke edilmesi
ve kilit kullanılabilir hale gelene kadar bekleyen bir kuyruğa yerleştirilmesi
için hangi değişikliklerin gerekli olacağını açıklayın.
6.19 Bir sistemin birden fazla işlem çekirdeğine sahip olduğunu varsayın. Aşağıdaki
senaryoların her biri için hangisinin daha iyi bir kilitleme mekanizması olduğunu açıklayın—a
Machine Translated by Google

EX-23

kilidin kullanılabilir hale gelmesini beklerken bekleme işlemlerinin uyuduğu


spinlock veya bir muteks kilidi:

• Kilit kısa bir süre tutulacaktır.

• Kilit uzun süre tutulmalıdır. • Kilidi tutarken bir

iplik uyku moduna geçebilir.

6.20 Bir bağlam anahtarının T zamanını aldığını varsayalım . Bir döndürme kilidini tutmak
için bir üst sınır (T cinsinden) önerin . Döndürme kilidi daha uzun süre tutulursa,
bir muteks kilidi (bekleyen iş parçacıklarının uyku moduna geçirildiği yer) daha iyi
bir alternatiftir.

6.21 Çok iş parçacıklı bir web sunucusu, hizmet verdiği isteklerin sayısını ( isabet olarak
bilinir) takip etmek ister. Değişken vuruşlarda bir yarış koşulunu önlemek için
aşağıdaki iki stratejiyi göz önünde bulundurun . İlk strateji, isabetleri güncellerken
temel bir muteks kilidi kullanmaktır :

int isabetleri;
muteks kilit vuruş kilidi;

lock.acquire()'a basın;
hit++; lock.release()'e
basın;

İkinci bir strateji, bir atomik tamsayı kullanmaktır:

atomik t vuruşları;
atomic inc(&hits);

Bu iki stratejiden hangisinin daha verimli olduğunu açıklayın.

6.22 Şekil 6.20'de gösterilen tahsis ve serbest bırakma işlemleri için kod örneğini düşünün.

a. Yarış koşullarını tanımlayın. b. Edinme

() ve bırakma () işlemleriyle mutex adında bir muteks kilidiniz olduğunu


varsayalım . Yarış koşullarını önlemek için kilitlemenin nereye yerleştirilmesi
gerektiğini belirtin.

c. Tamsayı değişkenini değiştirebilir miyiz?

int işlem sayısı = 0

atomik tamsayı ile

atomik t işlem sayısı = 0 yarış koşul(lar)ını

önlemek için?

6.23 Sunucular, açık bağlantıların sayısını sınırlayacak şekilde tasarlanabilir. Örneğin, bir
sunucu herhangi bir zamanda yalnızca N soket bağlantısına sahip olmak isteyebilir.
N bağlantı yapılır yapılmaz, sunucu mevcut bir bağlantı kurulana kadar başka bir
gelen bağlantıyı kabul etmeyecektir.
Machine Translated by Google

Egzersizler EX-24

#define MAKS SÜREÇ 255 int işlem


sayısı = 0;

/* fork() uygulaması bu işlevi çağırıyor */ int allocate process() { int yeni pid;

if (işlem sayısı == MAKS SÜREÇ) -1 döndürür; else { /* gerekli


süreç kaynaklarını tahsis edin */ ++işlem sayısı;

yeni pid döndür;


}
}

/* çıkış() uygulaması bu işlevi çağırır */ void yayın süreci() { /* süreç kaynaklarını


serbest bırak */ --süreç sayısı;

Şekil 6.21 Alıştırma 6.27 için tahsis ve serbest bırakma süreçleri.

piyasaya sürülmüş. Eşzamanlı bağlantıların sayısını sınırlamak için bir sunucu tarafından
semaforların nasıl kullanılabileceğini gösterin.

6.24 Bölüm 6.7'de, kritik bölüm problemini çözmek için semaforların yanlış kullanımı
olarak aşağıdaki çizimi kullanıyoruz:

bekle(mutex);
...
kritik Bölüm
...
bekle(mutex);

Bunun neden bir canlılık hatası örneği olduğunu açıklayın.

6.25 Monitörlerin ve semaforların, aynı tip senkronizasyon problemlerine çözümler


uygulamak için kullanılabilecekleri dereceye eşdeğer olduklarını gösterin.

6.26 Monitörlerle ilişkili sinyal() işleminin semaforlar için tanımlanan karşılık gelen
işlemden nasıl farklı olduğunu açıklayın.

6.27 Signal() ifadesinin bir monitör işlevinde yalnızca son ifade olarak görünebileceğini
varsayalım . Bu durumda Bölüm 6.7'de açıklanan uygulamanın nasıl
basitleştirilebileceğini önerin.
EX-25
Machine Translated by Google

6.28 Her biri benzersiz bir öncelik numarasına sahip olan P1, P2, ..., Pn süreçlerinden
oluşan bir sistem düşünün . Tahsis sırasına karar vermek için öncelik
numaralarını kullanarak bu işlemlere üç özdeş yazıcı tahsis eden bir monitör
yazın.

6.29 Bir dosya, her biri benzersiz bir numaraya sahip olan farklı işlemler arasında
paylaşılacaktır. Dosyaya, aşağıdaki kısıtlamaya tabi olarak birkaç işlem
tarafından aynı anda erişilebilir: Dosyaya erişmekte olan tüm işlemlerle ilişkili
tüm benzersiz sayıların toplamı n'den küçük olmalıdır. Dosyaya erişimi
koordine etmek için bir monitör yazın.

6.30 Bir monitör içindeki bir koşul üzerinde bir sinyal gerçekleştirildiğinde,
sinyalleşme süreci ya yürütmeye devam edebilir ya da kontrolü sinyal verilen
sürece aktarabilir. Önceki alıştırmanın çözümü, sinyallemenin
gerçekleştirilebileceği bu iki farklı yolla nasıl farklı olabilir?
6.31 Çağıran programın belirli sayıda zaman birimi (tik) boyunca kendisini
geciktirmesini sağlayan bir alarm saati uygulayan bir monitör için bir
algoritma tasarlayın . Monitörünüzde düzenli aralıklarla tik() işlevini çağıran
gerçek bir donanım saatinin varlığını varsayabilirsiniz .
6.32 Gerçek zamanlı bir sistemde öncelikli ters çevirme sorununun ele alınabileceği
yolları tartışın. Çözümlerin orantılı bir paylaşım planlayıcısı bağlamında
uygulanıp uygulanamayacağını da tartışın.
Machine Translated by Google

P-32 Bölüm 6 Senkronizasyon Araçları

Programlama Sorunları

6.33 Tek bir kaynak türünden sınırlı sayıda kaynağın yönetilmesi gerektiğini
varsayın. Süreçler bu kaynaklardan birkaçını isteyebilir ve bittiğinde geri
verir. Örnek olarak, birçok ticari yazılım paketi , aynı anda çalışabilecek
uygulamaların sayısını gösteren belirli sayıda lisans sağlar. Uygulama
başlatıldığında lisans sayısı düşürülür. Uygulama sonlandırıldığında lisans
sayısı artırılır. Tüm lisanslar kullanımdaysa, uygulamayı başlatma istekleri
reddedilir. Böyle bir talep, yalnızca mevcut bir lisans sahibinin başvuruyu
feshetmesi ve bir lisans iade edilmesi durumunda kabul edilecektir.

Aşağıdaki program bölümü, kullanılabilir bir kaynağın sınırlı sayıda


örneğini yönetmek için kullanılır. Maksimum kaynak sayısı ve kullanılabilir
kaynak sayısı aşağıdaki gibi bildirilir:

#define MAKS KAYNAK 5 int


kullanılabilir kaynak = MAKS KAYNAK;

Bir işlem bir dizi kaynak elde etmek istediğinde, count() işlevini azaltmayı
çağırır:

/* mevcut kaynakları, kaynakları sayarak azalt */ /* yeterli kaynak varsa


0 döndür, */ /* aksi takdirde -1 döndür */ int sayıyı azalt(int sayısı) {

if (mevcut kaynaklar < sayı) -1 döndürür; else


{ mevcut kaynaklar -= sayım;

0 döndür;
}
}

Bir işlem bir dizi kaynak döndürmek istediğinde, artırma sayısı() işlevini
çağırır:

/* mevcut kaynakları sayıca artır */ int sayıyı artır(int sayısı)


{ kullanılabilir kaynakları += sayıyı;

0 döndür;
}

Önceki program bölümü bir yarış koşulu üretir. Aşağıdakileri yapın:

a. Yarış koşuluyla ilgili verileri tanımlayın.


Programlama Sorunları P-33
Machine Translated by Google
b. Yarış koşulunun oluştuğu koddaki konumu (veya konumları) tanımlayın.

c. Bir semafor veya muteks kilidi kullanarak yarış durumunu düzeltin.


Çağırma işleminin, yeterli kaynak bulunana kadar bloke edilmesi için,
count() işlevinin azaltılmasına izin verilir .

6.34 Bir önceki alıştırmada bulunan count() işlevi, yeterli kaynak mevcutsa 0, aksi
takdirde -1 döndürür. Bu, bir dizi kaynak elde etmek isteyen bir süreç için
garip programlamaya yol açar:

while (sayıyı azalt(sayım) == -1)


;

Bir izleme ve koşul değişkenlerini kullanarak kaynak yöneticisi kod bölümünü


yeniden yazın, böylece sayıyı azalt() işlevi yeterli kaynak bulunana kadar süreci
askıya alır. Bu, bir işlemin yalnızca çağırarak eksil sayımı () başlatmasını
sağlar.

sayıyı azalt(say);

İşlem, yalnızca yeterli kaynak mevcut olduğunda bu işlev çağrısından


dönecektir.
Machine Translated by Google

7 BÖLÜM
senkronizasyon
Örnekler

Bölüm 6'da kritik bölüm problemini sunduk ve birden fazla eşzamanlı süreç
veri paylaştığında yarış koşullarının nasıl oluşabileceğine odaklandık. Yarış
koşullarının oluşmasını engelleyerek kritik bölüm sorununu ele alan birkaç
aracı incelemeye devam ettik. Bu araçlar, düşük seviyeli donanım çözümlerinden
(bellek bariyerleri ve karşılaştır ve değiştir işlemi gibi) giderek daha yüksek
seviyeli araçlara (mutex kilitlerinden semaforlara ve monitörlere) kadar
uzanıyordu. Ayrıca kilitlenmeler gibi canlılık tehlikeleri de dahil olmak üzere
yarış koşullarından bağımsız uygulamalar tasarlamanın çeşitli zorluklarını tartıştık.
Bu bölümde, Bölüm 6'da sunulan araçları birkaç klasik senkronizasyon
problemine uyguluyoruz. Ayrıca Linux, UNIX ve Windows işletim sistemleri
tarafından kullanılan senkronizasyon mekanizmalarını araştırıyoruz ve hem Java
hem de POSIX sistemleri için API ayrıntılarını açıklıyoruz.

BÖLÜM HEDEFLERİ

• Sınırlı arabelleği, okuyucuları – yazarları ve yemek – filozofları açıklayın


senkronizasyon sorunları.
• Süreci çözmek için Linux ve Windows tarafından kullanılan belirli araçları tanımlayın
senkronizasyon sorunları.
• Süreç senkronizasyonunu çözmek için POSIX ve Java'nın nasıl kullanılabileceğini gösterin
problemler.
• Kullanarak süreç senkronizasyon sorunlarına çözümler tasarlayın ve geliştirin
POSIX ve Java API'leri.

7.1 Klasik Senkronizasyon Sorunları

Bu bölümde, geniş bir eşzamanlılık-kontrol problemi sınıfının örnekleri olarak


bir dizi senkronizasyon problemini sunuyoruz. Bu problemler, yeni önerilen
hemen hemen her senkronizasyon şemasını test etmek için kullanılır. Sorunlara
yönelik çözümlerimizde, senkronizasyon için semaforlar kullanıyoruz, çünkü bu
289
Machine Translated by Google

290
Bölüm 7 Senkronizasyon Örnekleri

while (doğru) {
...
/* sonraki üretimde bir ürün üret */
...
bekle(boş);
bekle(mutex);
...
/* üretilen sonrakini tampona ekle */
...
sinyal(mutex);
sinyal(dolu);
}

Şekil 7.1 Üretici sürecinin yapısı.

Bu tür çözümleri sunmanın geleneksel yolu. Ancak, bu çözümlerin gerçek


uygulamaları, ikili semaforlar yerine muteks kilitleri kullanabilir.

7.1.1 Sınırlı Tampon Problemi

Sınırlı arabellek sorunu Bölüm 6.1'de tanıtıldı; yaygın olarak senkronizasyon


ilkellerinin gücünü göstermek için kullanılır. Burada, herhangi bir özel uygulamaya
kendimizi adamadan bu şemanın genel yapısını sunuyoruz. Bölümün sonundaki
alıştırmalarda ilgili bir programlama projesi sunuyoruz.

Problemimizde, üretici ve tüketici süreçleri aşağıdaki veri yapılarını paylaşır:

int n;
semafor muteks = 1;
semafor boş = n; semafor
dolu = 0

Havuzun , her biri bir öğe tutabilen n tampondan oluştuğunu varsayıyoruz .


Muteks ikili semaforu, arabellek havuzuna erişimler için karşılıklı dışlama sağlar ve
1 değerine başlatılır. Boş ve dolu semaforlar , boş ve dolu arabelleklerin sayısını
sayar. Boş semafor , n değerine başlatılır ; semafor dolu 0 değerine başlatılır.

Üretici sürecinin kodu Şekil 7.1'de, tüketici sürecinin kodu ise Şekil 7.2'de
gösterilmiştir. Üretici ve tüketici arasındaki simetriye dikkat edin. Bu kodu üreticinin
tüketici için dolu tampon ürettiği veya tüketicinin üretici için boş tampon ürettiği
şeklinde yorumlayabiliriz.

7.1.2 Okur-Yazar Problemi

Bir veritabanının birkaç eşzamanlı süreç arasında paylaşılacağını varsayalım.


Bu süreçlerin bazıları yalnızca veritabanını okumak isteyebilirken, diğerleri
veritabanını güncellemek (yani, okumak ve yazmak) isteyebilir. ayırt ediyoruz
7.1 Klasik Senkronizasyon Sorunları 291
Machine Translated by Google

while (true)
{ wait(dolu);
bekle(mutex);
...
/* bir öğeyi tampondan sonraki tüketilene kadar kaldır */
...
sinyal(mutex);
sinyal(boş);
...
/* sonraki tüketilen öğeyi tüket */
...
}

Şekil 7.2 Tüketici sürecinin yapısı.

birincisine okuyucu , ikincisine yazar olarak atıfta bulunarak bu iki tür süreç arasında
Açıktır ki, iki okuyucu aynı anda paylaşılan verilere erişirse, herhangi bir olumsuz etki
ortaya çıkmayacaktır. Ancak, bir yazar ve başka bir süreç (bir okuyucu veya bir yazar)
veritabanına aynı anda erişirse, kaos ortaya çıkabilir.

Bu zorlukların ortaya çıkmamasını sağlamak için, yazarların veritabanına


yazarken paylaşılan veritabanına özel erişime sahip olmalarını şart koşuyoruz. Bu
senkronizasyon sorununa okuyucu-yazar sorunu denir . Başlangıçta belirtildiğinden
beri, neredeyse her yeni senkronizasyon ilkelini test etmek için kullanılmıştır.

Okur-yazar sorununun, tümü öncelik bağlarını içeren çeşitli varyasyonları


vardır. İlk okuyucu-yazar problemi olarak adlandırılan en basit problem, bir yazar
paylaşılan nesneyi kullanmak için zaten izin almadıkça hiçbir okuyucunun
bekletilmemesini gerektirir. Başka bir deyişle, hiçbir okuyucu, bir yazar bekliyor diye
diğer okuyucuların bitirmesini beklememelidir. İkinci okuyucu-yazar sorunu, bir
yazar hazır olduğunda, o yazarın yazısını bir an önce gerçekleştirmesini gerektirir .
Başka bir deyişle, bir yazar nesneye erişmeyi bekliyorsa, hiçbir yeni okuyucu okumaya
başlayamaz.
Her iki soruna da bir çözüm açlıkla sonuçlanabilir. İlk durumda, yazarlar
açlıktan ölebilir; ikinci durumda, okuyucular aç kalabilir. Bu nedenle, sorunun başka
varyantları önerilmiştir. Ardından, ilk okuyucu-yazar sorununa bir çözüm sunuyoruz.
İkinci okuyucu-yazar sorununa açlıksız çözümleri açıklayan referanslar için
bölümün sonundaki bibliyografik notlara bakın.

İlk okur-yazar sorununun çözümünde okuyucu,


aşağıdaki veri yapılarını paylaşın:
semafor rw muteks = 1;
semafor muteks = 1; int
okuma sayısı = 0;

Mutex ve rw mutex ikili semaforları 1 olarak başlatılır; okuma sayısı ,


0 olarak başlatılan bir sayma semaforudur. Semafor rw mutex
Machine Translated by Google

292 Bölüm 7 Senkronizasyon Örnekleri

while (true)
{ wait(rw mutex);
...
/* yazma yapılır */
...
sinyal(rw muteks);
}

Şekil 7.3 Bir yazar sürecinin yapısı.

hem okuyucu hem de yazar süreçlerinde ortaktır. Değişken okuma sayısı


güncellendiğinde karşılıklı dışlamayı sağlamak için muteks semaforu kullanılır.
Okuma sayısı değişkeni , nesneyi şu anda kaç işlemin okuduğunu takip eder.
Semafor rw mutex , yazarlar için karşılıklı bir dışlama semaforu olarak işlev görür.
Kritik bölüme giren veya çıkan ilk veya son okuyucu tarafından da kullanılır.
Diğer okuyucular kritik bölümlerindeyken giren veya çıkan okuyucular tarafından
kullanılmaz.
Bir yazma işleminin kodu Şekil 7.3'te gösterilmiştir; bir okuyucu işlemi için
kod Şekil 7.4'te gösterilmiştir. Bir yazar kritik bölümdeyse ve n okuyucu bekliyorsa,
rw muteksinde bir okuyucunun sıraya alındığını ve muteks üzerinde n 1
okuyucunun sıraya alındığını unutmayın. Ayrıca, bir yazar signal(rw mutex)
yürüttüğünde , bekleyen okuyucuların veya tek bir bekleyen yazarın yürütülmesine
devam edebileceğimize dikkat edin. Seçim, zamanlayıcı tarafından yapılır.
Okur-yazar sorunu ve çözümleri , bazı sistemlerde okuyucu-yazar kilitleri
sağlamak için genelleştirilmiştir. Bir okuyucu-yazıcı kilidi edinmek, kilidin
modunun belirtilmesini gerektirir: ya okuma ya da yazma erişimi. Zaman

while (true)
{ wait(mutex);
sayıyı oku++; if
(sayıyı oku == 1) wait(rw
mutex); sinyal(mutex);

...
/* okuma yapılır */
...
bekle(mutex);
okuma sayısı--;
if (sayıyı oku == 0)
sinyali(rw muteks);
sinyal(mutex);
}

Şekil 7.4 Bir okuyucu sürecinin yapısı.


Machine Translated by Google

293
7.1 Klasik Senkronizasyon Sorunları

süreç sadece paylaşılan verileri okumak istiyor, okuma modunda okuyucu-yazıcı kilidini talep
ediyor. Paylaşılan verileri değiştirmek isteyen bir işlem, yazma modunda kilidi talep
etmelidir. Birden çok işlemin okuma modunda aynı anda bir okuyucu-yazar kilidi almasına
izin verilir, ancak yazarlar için özel erişim gerektiğinden yalnızca bir işlem yazma için kilidi
alabilir.
Okuyucu-yazıcı kilitleri en çok aşağıdaki durumlarda kullanışlıdır:

• Hangi işlemlerin yalnızca okunduğunu belirlemenin kolay olduğu uygulamalarda


paylaşılan veriler ve hangi işlemler yalnızca paylaşılan verileri yazar.

• Yazardan çok okuyucusu olan uygulamalarda. Bunun nedeni, okuyucu-yazar kilitlerinin


oluşturulması için genellikle semaforlardan veya karşılıklı dışlama kilitlerinden daha
fazla ek yük gerektirmesidir. Birden çok okuyucuya izin vermenin artan eşzamanlılığı,
okuyucu-yazar kilidinin ayarlanmasıyla ilgili ek yükü telafi eder.

7.1.3 Yemek-Filozof Problemi


Hayatlarını düşünerek ve yemek yiyerek geçiren beş filozof düşünün. Filozoflar, her biri bir
filozofa ait olan beş sandalyeyle çevrili dairesel bir masayı paylaşırlar. Masanın ortasında bir
kase pirinç vardır ve masa beş adet tekli çubukla döşenmiştir (Şekil 7.5). Bir filozof
düşündüğünde meslektaşlarıyla etkileşime girmez. Zaman zaman bir filozof acıkarak
kendisine en yakın olan iki çubuğu (kendisi ile sol ve sağ komşuları arasındaki çubukları)
almaya çalışır. Bir filozof aynı anda yalnızca bir çubuk alabilir. Belli ki, zaten bir komşunun
elinde olan bir yemek çubuğunu alamaz. Aç bir filozof iki yemek çubuğunu aynı anda
aldığında, yemek çubuklarını bırakmadan yer. Yemeğini bitirdiğinde iki yemek çubuğunu
da bırakır ve tekrar düşünmeye başlar.

Yemek -filozofları problemi , ne pratik öneminden ne de bilgisayar bilimcilerinin


filozoflardan hoşlanmadıkları için değil, geniş bir eşzamanlılık-kontrol problemleri sınıfının
bir örneği olduğu için klasik bir senkronizasyon problemi olarak kabul edilir. ihtiyacın basit
bir temsilidir.

PİLAV

Şekil 7.5 Yemek filozoflarının durumu.


Machine Translated by Google

294 Bölüm 7 Senkronizasyon Örnekleri

while (true)
{ wait(chopstick[i]);
bekle(çubuk[(i+1) % 5]);
...
/* bir süre yemek ye */
...
sinyal(çubuk[i]);
sinyal(çubuk[(i+1) % 5]);
...
/* bir süre düşün */
...
}

Şekil 7.6 Filozofun yapısı i.

kilitlenme ve açlıktan uzak bir şekilde çeşitli işlemler arasında birkaç


kaynağı tahsis etmek.

7.1.3.1 Semafor Çözümü


Basit bir çözüm, her bir çubuğu bir semaforla temsil etmektir. Bir filozof ,
o semafor üzerinde bir wait() işlemi yürüterek bir çubuk yakalamaya çalışır .
Uygun semaforlarda sinyal() işlemini yürüterek yemek çubuklarını serbest
bırakır . Böylece paylaşılan veriler
semafor çubuk[5];
burada çubuktaki tüm elemanlar 1'e sıfırlanır. Filozof i'nin yapısı Şekil 7.6'da
gösterilmektedir.
Bu çözüm, iki komşunun aynı anda yemek yememesini garanti etse de,
yine de bir kilitlenme yaratabileceğinden reddedilmelidir.
Beş filozofun hepsinin aynı anda acıktığını ve her birinin sol yemek
çubuğunu tuttuğunu varsayalım. Çubuğun tüm öğeleri şimdi 0'a eşit
olacaktır. Her filozof sağ çubuk çubuğunu almaya çalıştığında, sonsuza
kadar ertelenecektir.
Kilitlenme sorununa birkaç olası çözüm aşağıdaki gibidir:
• Masada aynı anda en fazla dört filozofun oturmasına izin verin. • Bir
filozofun yemek çubuklarını yalnızca her iki çubuk da mevcutsa almasına
izin verin (bunu yapmak için onları kritik bir bölümden alması gerekir).
• Asimetrik bir çözüm kullanın—yani, tek numaralı bir filozof önce sol
çubuk çubuğunu ve sonra sağ çubuk çubuğunu alırken, çift numaralı
bir filozof sağ çubuk çubuğunu ve sonra sol çubuk çubuğunu alır.

Bölüm 6.7'de, kilitlenmelerden kurtulmayı sağlayan yemek-filozofları


sorununa bir çözüm sunuyoruz. Bununla birlikte, yemek-filozofları sorununa
tatmin edici herhangi bir çözümün,
Machine Translated by Google

7.2 Çekirdek İçinde Senkronizasyon 295

filozoflardan birinin açlıktan öleceğini. Kilitlenmeyen bir çözüm, açlık olasılığını mutlaka
ortadan kaldırmaz.

7.1.3.2 Monitör Çözümü

Ardından, yemek filozofları sorununa kilitlenmeyen bir çözüm sunarak monitör kavramlarını
gösteriyoruz. Bu çözüm, bir filozofun yemek çubuklarını ancak her ikisi de mevcut olduğunda
alabileceği kısıtlamasını dayatır. Bu çözümü kodlamak için bir filozof bulabileceğimiz üç
durumu ayırt etmemiz gerekir. Bu amaçla, aşağıdaki veri yapısını tanıtıyoruz:

enum {DÜŞÜNMEK, AÇ, YEMEK} durumu[5];

Filozof i durumu[i] = YEMEK değişkenini ancak iki komşusu yemek yemiyorsa ayarlayabilirim :
(durum[(i+4) % 5] != YEMEK) ve (durum[(i+1) % 5] ! = YEMEK).

ayrıca beyan etmemiz gerekiyor

koşul öz[5];

Bu, filozof i'nin aç olduğu, ancak ihtiyaç duyduğu yemek çubuklarını alamadığı zaman kendini
geciktirmesine izin verir.
Artık yemek felsefecileri sorununa çözümümüzü anlatabilecek durumdayız. Çubukların
dağılımı , tanımı Şekil 7.7'de gösterilen DiningPhilosophers monitörü tarafından kontrol edilir .

Her filozof yemeye başlamadan önce pikap() işlemini başlatmalıdır.


Bu eylem, filozof sürecinin askıya alınmasına neden olabilir. Operasyonun başarıyla
tamamlanmasından sonra filozof yemek yiyebilir. Bunu takiben, filozof putdown() işlemini
başlatır. Bu nedenle, filozof , aşağıdaki sırayla pickup() ve putdown () işlemlerini çağırmalıyım:

YemekPhilosophers.pickup(i);
...
yemek

...
YemekPhilosophers.putdown(i);

Bu çözümün, iki komşunun aynı anda yemek yememesini ve kilitlenme olmamasını


sağladığını göstermek kolaydır. Ancak daha önce de belirttiğimiz gibi, bir filozofun açlıktan
ölmesi mümkündür. Bu soruna bir çözüm sunmuyoruz, sizin için bir alıştırma olarak bırakıyoruz.

7.2 Çekirdek İçinde Senkronizasyon

Daha sonra Windows ve Linux işletim sistemleri tarafından sağlanan senkronizasyon


mekanizmalarını açıklayacağız. Bu iki işletim sistemi, çekirdeği senkronize etmek için farklı
yaklaşımların iyi örneklerini sağlar ve sizin de yapacağınız gibi
296 Bölüm 7 Senkronizasyon Örnekleri
Machine Translated by Google

DiningPhilosophers'ı izleyin {

enum {DÜŞÜNMEK, AÇ, YEMEK} durumu[5]; koşul öz[5];

geçersiz başlatma(int i)
{ durum[i] = AÇ; test(i); if
(durum[i] != YEMEK)
self[i].wait();

void putdown(int i) {
durum[i] = DÜŞÜNMEK; test((i
+ 4) % 5); test((i + 1) % 5);

void testi(int i) {
if ((durum[(i + 4) % 5] != YEMEK) && (durum[i] == AÇ) &&
(durum[(i + 1) % 5] != YEMEK)) { durum[i] = YEMEK
YİYOR; self[i].signal();

}
}

başlatma kodu() { for (int i = 0; i <


5; i++) durum[i] = DÜŞÜNME;

}
}

Şekil 7.7 Yemek-filozofları sorununa bir monitör çözümü.

bakın, bu sistemlerde mevcut olan senkronizasyon mekanizmaları, ince ancak önemli


şekillerde farklılık gösterir.

7.2.1 Windows'ta Senkronizasyon

Windows işletim sistemi, gerçek zamanlı uygulamalar ve birden çok işlemci


için destek sağlayan çok iş parçacıklı bir çekirdektir. Windows çekirdeği
tek işlemcili bir sistemde global bir kaynağa eriştiğinde, aynı zamanda
global kaynağa da erişebilen tüm kesme işleyicileri için kesintileri geçici
olarak maskeler. Çok işlemcili bir sistemde Windows, döndürme kilitlerini
kullanarak küresel kaynaklara erişimi korur, ancak çekirdek yalnızca kısa kod
parçalarını korumak için döndürme kilitlerini kullanır. Ayrıca, verimlilik
nedenleriyle, çekirdek, bir spinlock tutarken bir ipliğin asla önlenmemesini sağla
Machine Translated by Google

7.2 Çekirdek İçinde Senkronizasyon 297

Çekirdek dışında iş parçacığı senkronizasyonu için Windows, dis patcher nesneleri


sağlar. Bir gönderici nesnesi kullanarak iş parçacıkları, muteks kilitleri, semaforlar,
olaylar ve zamanlayıcılar dahil olmak üzere birkaç farklı mekanizmaya göre senkronize
edilir. Sistem, bir iş parçacığının verilere erişmek ve bittiğinde sahipliğini serbest
bırakmak için bir muteksin sahipliğini kazanmasını gerektirerek paylaşılan verileri korur.
Semaforlar Bölüm 6.6'da açıklandığı gibi davranır. Olaylar , koşul değişkenlerine
benzer; yani, istenen bir durum oluştuğunda bekleyen bir iş parçacığına haber
verebilirler. Son olarak, bir (veya birden fazla) iş parçacığına belirli bir sürenin
dolduğunu bildirmek için zamanlayıcılar kullanılır.
Gönderici nesneleri, sinyalli durumda veya sinyalsiz durumda olabilir.
Sinyal durumundaki bir nesne mevcuttur ve nesneyi alırken bir iş parçacığı bloke
olmaz. Sinyalsiz durumdaki bir nesne mevcut değildir ve nesneyi almaya çalışırken bir
iş parçacığı engellenir. Bir muteks kilit gönderici nesnesinin durum geçişlerini Şekil
7.8'de gösteriyoruz.
Bir gönderici nesnesinin durumu ile bir iş parçacığının durumu arasında bir ilişki
vardır. Bir iş parçacığı sinyalsiz bir gönderici nesnesini engellediğinde, durumu
hazırdan beklemeye değişir ve iş parçacığı o nesne için bekleyen bir kuyruğa
yerleştirilir. Dispeçer nesnesinin durumu sinyallendi durumuna geçtiğinde, çekirdek
nesnede bekleyen herhangi bir iş parçacığının olup olmadığını kontrol eder. Eğer
öyleyse, çekirdek bir iş parçacığını veya muhtemelen daha fazlasını bekleme
durumundan çalışmaya devam edebilecekleri hazır duruma taşır. Çekirdeğin bekleyen
kuyruğundan seçtiği iş parçacıklarının sayısı, her bir iş parçacığının beklediği
gönderici nesnesinin türüne bağlıdır. Çekirdek, bir muteks için bekleme kuyruğundan
yalnızca bir iş parçacığı seçecektir, çünkü bir muteks nesnesi yalnızca tek bir iş
parçacığına "sahip olabilir". Bir olay nesnesi için çekirdek, olayı bekleyen tüm iş
parçacıklarını seçecektir.
Dağıtıcı nesnelerinin ve iş parçacığı durumlarının bir örneği olarak bir muteks
kilidi kullanabiliriz. Bir iş parçacığı, sinyalsiz durumda olan bir muteks dağıtıcı nesnesi
almaya çalışırsa, bu iş parçacığı askıya alınır ve muteks nesnesi için bekleyen bir
kuyruğa yerleştirilir. Muteks sinyallenmiş duruma geçtiğinde (başka bir iş parçacığı
muteks üzerindeki kilidi serbest bıraktığından), kuyruğun önünde bekleyen iş
parçacığı bekleme durumundan hazır duruma geçecek ve muteks kilidini alacaktır.

Bir kritik bölüm nesnesi , genellikle çekirdek müdahalesi olmadan alınabilen ve


serbest bırakılabilen bir kullanıcı modu muteksidir. Çok işlemcili bir sistemde, kritik
bölüm nesnesi önce diğer iş parçacığının nesneyi serbest bırakmasını beklerken bir
döndürme kilidi kullanır. Çok uzun dönerse, elde eden iş parçacığı daha sonra bir
çekirdek muteks tahsis edecek ve CPU'sunu verecektir. Kritik bölüm nesneleri özellikle
verimlidir, çünkü çekirdek muteksi yalnızca nesne için çekişme olduğunda tahsis
edilir. Uygulamada, çok az çekişme vardır, bu nedenle tasarruf önemlidir.

sahibi iş parçacığı muteks kilidini serbest bırakır

sinyalsiz işaretli

iş parçacığı mutex kilidi alır

Şekil 7.8 Mutex gönderici nesnesi.


298 Bölüm 7 Senkronizasyon Örnekleri
Machine Translated by Google

Bu bölümün sonunda aşağıdakileri kullanan bir programlama projesi sunuyoruz:


Windows API'sinde muteks kilitleri ve semaforlar .

7.2.2 Linux'ta Senkronizasyon

Sürüm 2.6'dan önce Linux, önleyici olmayan bir çekirdekti; bu, çekirdek modunda
çalışan bir işlemin önceden engellenemeyeceği anlamına geliyordu - daha yüksek
öncelikli bir işlem çalıştırılabilir hale gelse bile. Ancak şimdi, Linux çekirdeği tamamen
önleyicidir, bu nedenle çekirdekte çalışırken bir görev önceden alınabilir.
Linux, çekirdekte senkronizasyon için birkaç farklı mekanizma sağlar. Çoğu
bilgisayar mimarisi, basit matematik işlemlerinin atomik sürümleri için talimatlar
sağladığından, Linux çekirdeği içindeki en basit senkronizasyon tekniği, opak veri
türü atomik t kullanılarak temsil edilen bir atomik tamsayıdır . Adından da anlaşılacağı
gibi, atomik tamsayıların kullanıldığı tüm matematik işlemleri kesintisiz olarak
gerçekleştirilir. Örneklemek için, bir atomik tamsayı sayacından ve bir tamsayı
değerinden oluşan bir program düşünün .

atomik t sayacı; int değeri;

Aşağıdaki kod, çeşitli atomik işlemleri gerçekleştirmenin etkisini gösterir:

Atomik İşlem atom Etki


seti(&counter,5); atomik sayaç = 5

toplama(10,&sayaç); atomik sayaç = sayaç + 10 sayaç = sayaç - 4

alt(4,&counter); atom sayaç = sayaç + 1

inc(&counter); değer = atomik


okuma(&sayaç); değer = 12

Atomik tamsayılar, bir tamsayı değişkeninin (sayaç gibi) güncellenmesi gereken


durumlarda özellikle etkilidir, çünkü atomik işlemler kilitleme mekanizmalarının ek
yükünü gerektirmez. Ancak, kullanımları bu tür senaryolarla sınırlıdır. Muhtemel bir yarış
durumuna katkıda bulunan birkaç değişkenin olduğu durumlarda, daha karmaşık
kilitleme araçları kullanılmalıdır.

Mutex kilitleri, çekirdek içindeki kritik bölümleri korumak için Linux'ta mevcuttur.
Burada, bir görev kritik bir bölüme girmeden önce mutex lock() işlevini ve kritik
bölümden çıktıktan sonra mutex unlock() işlevini çağırmalıdır. Mutex kilidi
kullanılamıyorsa, mutex lock() işlevini çağıran bir görev uyku durumuna alınır ve kilidin
sahibi mutex unlock() işlevini çağırdığında uyandırılır .
Linux ayrıca çekirdeğe kilitlemek için döndürme kilitleri ve semaforlar (ve bu iki
kilidin okuyucu-yazıcı versiyonları) sağlar. SMP makinelerinde , temel kilitleme
mekanizması bir döndürme kilididir ve çekirdek, döndürme kilidi yalnızca kısa süreler
için tutulacak şekilde tasarlanmıştır. Yalnızca tek bir işlem çekirdeğine sahip gömülü
sistemler gibi tek işlemcili makinelerde, döndürme kilitleri kullanım için uygun değildir
ve çekirdek önceliğini etkinleştirme ve devre dışı bırakma ile değiştirilir. Diğer bir
deyişle, tek bir işlem çekirdeğine sahip sistemlerde, bir spinlock tutmak yerine, çekirdek,
çekirdek önceliğini devre dışı bırakır; ve döndürme kilidini serbest bırakmak yerine,
çekirdeğin önceden alınmasını sağlar. Bu aşağıda özetlenmiştir:
7.3 POSIX Senkronizasyonu 299
Machine Translated by Google

Tek İşlemci Çoklu İşlemciler

Çekirdek önceliğini devre dışı bırak Döndürme kilidi edinin

Çekirdek önceliğini etkinleştir Döndürme kilidini serbest bırakın

Linux çekirdeğinde, hem döndürme kilitleri hem de muteks kilitleri özyinelemeli


değildir, yani bir iş parçacığı bu kilitlerden birini aldıysa, ilk önce kilidi serbest
bırakmadan aynı kilidi ikinci kez alamaz. Aksi takdirde, kilidi elde etmeye yönelik
ikinci girişim engellenecektir.
Linux, çekirdek ön alımını devre dışı bırakmak ve etkinleştirmek için ilginç bir
yaklaşım kullanır. Çekirdek önceliğini devre dışı bırakmak ve etkinleştirmek için iki
basit sistem çağrısı (preempt disable() ve preempt enable()) sağlar. Bununla birlikte,
çekirdekte çalışan bir görev bir kilit tutuyorsa, çekirdek öncelikli değildir. Bu kuralı
uygulamak için, sistemdeki her görevin, görev tarafından tutulan kilitlerin sayısını
belirtmek için bir sayaç, öncelik sayımı içeren bir iş parçacığı bilgisi yapısı vardır.
Bir kilit alındığında, önceden alma sayısı artırılır. Bir kilit açıldığında karar verilir. Şu
anda çekirdekte çalışmakta olan görev için önceden alma sayımının değeri 0'dan
büyükse, bu görev şu anda bir kilit içerdiğinden, çekirdeği önceden ayırmak
güvenli değildir. Sayı 0 ise, çekirdek güvenli bir şekilde kesintiye uğrayabilir
( preempt disable() için bekleyen çağrı olmadığı varsayılarak ).
Spinlock'lar (çekirdek önalımını etkinleştirme ve devre dışı bırakmayla birlikte)
yalnızca bir kilit (veya çekirdek önceliğini devre dışı bırakan) kısa bir süre
tutulduğunda çekirdekte kullanılır. Bir kilidin daha uzun süre tutulması gerektiğinde,
semaforlar veya muteks kilitler kullanıma uygundur.

7.3 POSIX Senkronizasyonu

Önceki bölümde tartışılan senkronizasyon yöntemleri, çekirdek içindeki


senkronizasyonla ilgilidir ve bu nedenle yalnızca çekirdek geliştiricileri tarafından
kullanılabilir. Buna karşılık, POSIX API , programcılar için kullanıcı düzeyinde
mevcuttur ve herhangi bir işletim sistemi çekirdeğinin parçası değildir. (Tabii ki,
sonuçta ana bilgisayar işletim sistemi tarafından sağlanan araçlar kullanılarak
uygulanmalıdır.)
Bu bölümde, Pthreads ve POSIX API'lerinde bulunan muteks kilitlerini, semaforları
ve koşul değişkenlerini ele alıyoruz . Bu API'ler , UNIX, Linux ve macOS sistemlerinde
geliştiriciler tarafından iş parçacığı oluşturma ve senkronizasyon için yaygın olarak
kullanılır .

7.3.1 POSIX Mutex Kilitleri


Mutex kilitleri, Pthreads ile kullanılan temel senkronizasyon tekniğini temsil eder.
Kodun kritik bölümlerini korumak için bir muteks kilidi kullanılır - yani bir iş parçacığı
kritik bölüme girmeden önce kilidi alır ve kritik bölümden çıktıktan sonra serbest
bırakır. Pthreads, muteks kilitleri için pthread mutex t veri türünü kullanır. pthread
mutex init() işleviyle bir muteks oluşturulur .
İlk parametre muteks için bir işaretçidir. NULL'u ikinci bir parametre olarak ileterek ,
mutex'i varsayılan niteliklerine başlatırız. Bu, aşağıda gösterilmiştir:
300 Bölüm 7 Senkronizasyon Örnekleri
Machine Translated by Google

#include <pthread.h>

pthread muteks t muteks;

/* muteks kilidini oluştur ve başlat */ pthread mutex


init(&mutex,NULL);

Mutex, pthread mutex lock() ve pthread mutex unlock() işlevleriyle elde edilir ve
serbest bırakılır . pthread mutex lock() çağrıldığında muteks kilidi kullanılamıyorsa ,
çağıran iş parçacığı, sahibi pthread mutex unlock()'ı çağırana kadar engellenir.
Aşağıdaki kod, muteks kilitleri ile kritik bir bölümü korumayı gösterir:

/* mutex kilidini al */ pthread mutex


lock(&mutex);

/* kritik Bölüm */

/* mutex kilidini serbest bırak */


pthread mutex unlock(&mutex);

Tüm muteks işlevleri, doğru işlemle 0 değerini döndürür; bir hata oluşursa, bu
işlevler sıfırdan farklı bir hata kodu döndürür.

7.3.2 POSIX Semaforları Pthreads

uygulayan birçok sistem, semaforlar POSIX standardının bir parçası olmamasına ve


bunun yerine POSIX SEM uzantısına ait olmasına rağmen semaforlar da sağlar .
POSIX , adlandırılmış ve adsız olmak üzere iki tür semafor belirtir . Temel olarak, ikisi
oldukça benzerdir, ancak süreçler arasında nasıl oluşturuldukları ve paylaşıldıkları
açısından farklılık gösterirler. Her iki teknik de yaygın olduğu için burada ikisini de
tartışıyoruz. Çekirdeğin 2.6 Sürümünden başlayarak, Linux sistemleri hem
adlandırılmış hem de adsız semaforlar için destek sağlar.

7.3.2.1 POSIX Adlandırılmış Semaforlar

sem open() işlevi , sempahor adlı bir POSIX oluşturmak ve açmak için kullanılır :

#include <semaphore.h> sem


t *sem;

/* Semaforu oluşturun ve onu 1 olarak başlatın */ sem = sem


open("SEM", O CREAT, 0666, 1);
Bu örnekte, semaforu SEM olarak adlandırıyoruz. O CREAT bayrağı, zaten mevcut
değilse semaforun oluşturulacağını belirtir. Ek olarak, semafor diğer işlemler için
( 0666 parametresi aracılığıyla) okuma ve yazma erişimine sahiptir ve 1 olarak
başlatılır.
Adlandırılmış semaforların avantajı, birbiriyle ilişkili olmayan birden çok işlemin,
ortak bir semaforu bir senkronizasyon mekanizması olarak kolayca kullanabilmesidir.
Machine Translated by Google

7.3 POSIX Senkronizasyonu 301

sadece semaforun adına atıfta bulunarak. Yukarıdaki örnekte, SEM semaforu


oluşturulduktan sonra, diğer işlemler tarafından sem open() 'e (aynı
parametrelerle) yapılan sonraki çağrılar, mevcut semafora bir tanımlayıcı
döndürür.
Bölüm 6.6'da klasik wait() ve sinyal() semafor işlemlerini tanımladık. POSIX ,
bu işlemleri sırasıyla sem wait() ve sem post() olarak bildirir . Aşağıdaki kod
örneği, yukarıda oluşturulan adlandırılmış semaforu kullanarak kritik bir
bölümü korumayı gösterir:

/* semaforu al */ sem wait(sem);

/* kritik Bölüm */

/* semaforu serbest bırak */ sem


post(sem);

Hem Linux hem de macOS sistemleri, POSIX adlı semaforlar sağlar.

7.3.2.2 POSIX Adsız Semaforlar Adsız bir


semafor oluşturulur ve üç parametre iletilen sem init() işlevi kullanılarak
başlatılır :

1. Semafor için bir işaretçi 2.


Paylaşım düzeyini gösteren bir bayrak
3. Semaforun başlangıç değeri

ve aşağıdaki programlama örneğinde gösterilmiştir:

#include <semaphore.h> sem


t sem;

/* Semaforu yarat ve onu 1 olarak başlat */ sem init(&sem, 0, 1);

Bu örnekte 0 bayrağını geçerek bu semaforun sadece semaforu oluşturan


işleme ait threadler tarafından paylaşılabileceğini belirtiyoruz.
(Sıfırdan farklı bir değer vermiş olsaydık, semaforu paylaşılan belleğin bir
bölgesine yerleştirerek ayrı süreçler arasında paylaşılmasına izin verebilirdik.)
Ayrıca semaforu 1 değerine başlatıyoruz.
POSIX adsız semaforları, adlandırılmış semaforlarla aynı sem wait() ve sem
post() işlemlerini kullanır. Aşağıdaki kod örneği, yukarıda oluşturulan adsız
semafor kullanılarak kritik bir bölümün korunmasını gösterir:
Machine Translated by Google

302 Bölüm 7 Senkronizasyon Örnekleri

/* semaforu al */ sem wait(&sem);

/* kritik Bölüm */

/* semaforu serbest bırak */ sem


post(&sem);

Muteks kilitleri gibi, tüm semafor işlevleri başarılı olduğunda 0, bir hata durumu
oluştuğunda sıfır dışında döner.

7.3.3 POSIX Koşul Değişkenleri

Pthreads'deki koşul değişkenleri, Bölüm 6.7'de açıklananlara benzer şekilde


davranır. Ancak bu bölümde, veri bütünlüğünü sağlamak için bir kilitleme
mekanizması sağlayan bir monitör bağlamında koşul değişkenleri kullanılır.
Pthreads tipik olarak C programlarında kullanıldığından ve C'nin bir monitörü
olmadığından, bir koşul değişkenini bir muteks kilidiyle ilişkilendirerek kilitlemeyi
gerçekleştiririz.
Pthreads'deki koşul değişkenleri, pthread cond t veri türünü kullanır ve
pthread cond init() işlevi kullanılarak başlatılır. Aşağıdaki kod, bir koşul değişkeni
ile ilişkili muteks kilidini oluşturur ve başlatır:

pthread muteks t muteks;


pthread koşul t koşul var;

pthread mutex init(&mutex,NULL); pthread


koşul init(&cond var,NULL);

pthread cond wait() işlevi, bir koşul değişkenini beklemek için kullanılır .
Aşağıdaki kod, bir iş parçacığının bir Pthread koşul değişkeni kullanarak a == b
koşulunun gerçekleşmesini nasıl bekleyebileceğini gösterir:

pthread mutex kilidi(&mutex); while


(a != b) pthread cond wait(&cond
var, &mutex);

pthread mutex kilidini aç(&mutex);

Koşul değişkeniyle ilişkili muteks kilidi , koşullu yan tümcedeki verileri olası bir
yarış koşulundan korumak için kullanıldığından, pthread cond wait() işlevi
çağrılmadan önce kilitlenmelidir . Bu kilit elde edildiğinde, iplik durumu kontrol
edebilir. Koşul doğru değilse, iş parçacığı daha sonra muteks kilidini ve koşul
değişkenini parametre olarak geçirerek pthread cond wait()' i çağırır. pthread
cond wait() işlevinin çağrılması muteks kilidini serbest bırakır, böylece başka bir
iş parçacığının paylaşılan verilere erişmesine ve muhtemelen koşul yan tümcesinin
doğru olarak değerlendirilmesi için değerini güncellemesine izin verir. (Program
hatalarına karşı koruma sağlamak için koşul cümlesini bir döngü içine yerleştirmek
önemlidir, böylece koşul sinyal verildikten sonra yeniden kontrol edilir.)
Machine Translated by Google

7.4 Java'da Senkronizasyon 303

Paylaşılan verileri değiştiren bir iş parçacığı, pthread cond sinyalini () çağırabilir.


fonksiyon, böylece koşul değişkeninde bekleyen bir iş parçacığının sinyalini verir. Bu,
aşağıda gösterilmiştir:

pthread mutex kilidi(&mutex);


a = b; pthread koşul
sinyali(&cond var); pthread mutex
kilidini aç(&mutex);

pthread cond signal() çağrısının muteks kilidini serbest bırakmadığına dikkat


etmek önemlidir . Muteksi serbest bırakan, sonraki pthread mutex unlock() çağrısıdır.
Mutex kilidi serbest bırakıldığında, sinyal verilen iş parçacığı muteks kilidinin sahibi
olur ve çağrıdan kontrolü pthread cond wait()'e döndürür.

Bu bölümün sonunda Pthreads muteks kilitleri ve koşul değişkenlerinin yanı sıra


POSIX semaforlarını kullanan birkaç programlama problemi ve projesi sunuyoruz.

7.4 Java'da Senkronizasyon

Java dili ve API'si , dilin başlangıcından bu yana iş parçacığı senkronizasyonu için


zengin destek sağlamıştır. Bu bölümde ilk olarak Java'nın orijinal senkronizasyon
mekanizması olan Java monitörlerini ele alıyoruz. Ardından, Sürüm 1.5'te tanıtılan üç ek
mekanizmayı ele alıyoruz: yeniden girişli kilitler, semaforlar ve koşul değişkenleri.
Bunları dahil ediyoruz çünkü bunlar en yaygın kilitleme ve senkronizasyon
mekanizmalarını temsil ediyor. Ancak Java API , bu metinde ele almadığımız pek çok
özellik sağlar - örneğin, atomik değişkenler için destek ve CAS talimatı - ve ilgili
okuyucuları daha fazla bilgi için kaynakçaya başvurmaya teşvik ediyoruz.

7.4.1 Java Monitörleri

Java, iş parçacığı senkronizasyonu için monitör benzeri bir eşzamanlılık mekanizması


sağlar. Bu mekanizmayı, üreticinin ve tüketicinin sırasıyla insert() ve remove()
yöntemlerini çağırdığı sınırlı arabellek sorununa bir çözüm uygulayan BoundedBuffer
sınıfıyla (Şekil 7.9) gösteriyoruz.

Java'daki her nesne onunla tek bir kilit ilişkilendirilmiştir. Bir yöntemin eşitleneceği
bildirildiğinde , yöntemin çağrılması, nesnenin kilidine sahip olmayı gerektirir.
BoundedBuffer sınıfındaki insert() ve remove() yöntemlerinde olduğu gibi, yöntem
tanımına synchronized anahtar sözcüğünü yerleştirerek bir eşitlenmiş yöntem bildiririz.

Senkronize bir yöntemi çağırmak , BoundedBuffer nesne örneğinde kilide sahip


olmayı gerektirir. Kilit zaten başka bir iş parçacığına aitse, senkronize yöntemi çağıran
iş parçacığı engeller ve nesnenin kilidi için giriş kümesine yerleştirilir. Giriş kümesi,
kilidin kullanılabilir hale gelmesini bekleyen iş parçacıkları kümesini temsil eder.
Senkronize bir yöntem çağrıldığında kilit mevcutsa , çağıran iş parçacığı nesnenin
kilidinin sahibi olur ve yönteme girebilir. İş parçacığı yöntemden çıktığında kilit
serbest bırakılır.
Kilit serbest bırakıldığında kilit için ayarlanan giriş boş değilse, JVM
Machine Translated by Google

304 Bölüm 7 Senkronizasyon Örnekleri

genel sınıf SınırlıBuffer<E> {

private static final int BUFFER SIZE = 5;

özel int sayısı, içeri, dışarı; özel E[]


arabelleği;

public BoundedBuffer() { sayı =


0; = 0; dışarı = 0; arabellek =
(E[]) yeni Nesne[TAMPON
BOYUTU];

/* Üreticiler bu yöntemi çağırır */ public


synchronized void insert(E item) {
/* Bkz. Şekil 7.11 */
}

/* Tüketiciler bu yöntemi çağırır */ public


synchronized E remove() { /* Bkz. Şekil 7.11
*/
}
}

Şekil 7.9 Java senkronizasyonunu kullanan sınırlı tampon.

kilidin sahibi olmak için bu kümeden keyfi olarak bir iş parçacığı seçer. (“Keyfi
olarak” dediğimizde, spesifikasyonun bu kümedeki iş parçacıklarının belirli bir sırada
düzenlenmesini gerektirmediğini kastediyoruz. Bununla birlikte, pratikte çoğu sanal
makine, giriş kümesindeki iş parçacıklarını bir FIFO ilkesine göre sipariş eder.) Şekil
7.10, giriş kümesinin nasıl çalıştığını gösterir.
Bir kilide sahip olmanın yanı sıra, her nesne aynı zamanda bir dizi iş parçacığından
oluşan bir bekleme kümesiyle de ilişkilendirilmiştir. Bu bekleme seti başlangıçta
boştur. Bir iş parçacığı senkronize bir yönteme girdiğinde, nesnenin kilidine sahip
olur. Ancak, bu iş parçacığı belirli bir koşul nedeniyle devam edemediğini belirleyebilir.

kilit almak
nesne
kilidi

sahip

giriş seti

Şekil 7.10 Bir kilit için giriş seti.


Machine Translated by Google

7.4 Java'da Senkronizasyon 305

BLOK SENKRONİZASYONU

Bir kilidin alınması ile serbest bırakılması arasındaki süre , kilidin kapsamı
olarak tanımlanır . Paylaşılan verileri manipüle eden kodunun yalnızca
küçük bir yüzdesine sahip senkronize bir yöntem, çok büyük bir kapsam
verebilir. Böyle bir durumda, tüm yöntemi senkronize etmektense, yalnızca
paylaşılan verileri işleyen kod bloğunu senkronize etmek daha iyi olabilir.
Böyle bir tasarım, daha küçük bir kilit kapsamı ile sonuçlanır. Bu nedenle,
senkronize yöntemlerin bildirilmesine ek olarak, Java ayrıca aşağıda
gösterildiği gibi blok senkronizasyonuna da izin verir. Yalnızca kritik bölüm
koduna erişim, bu nesne için nesne kilidinin sahipliğini gerektirir . public
void someMethod() {
/* kritik olmayan bölüm */

synchronized(this) { /* kritik
bölüm */
}

/* kalan kısım */
}

karşılanamamıştır. Örneğin, üretici insert() yöntemini çağırırsa ve arabellek doluysa bu


gerçekleşir. İplik daha sonra kilidi serbest bırakacak ve devam etmesine izin verecek koşul
karşılanana kadar bekleyecektir.
Bir iş parçacığı wait() yöntemini çağırdığında aşağıdakiler gerçekleşir:

1. İplik, nesnenin kilidini serbest bırakır.


2. İş parçacığının durumu bloke olarak ayarlanmıştır.

3. İplik, nesne için bekleme kümesine yerleştirilir.

Şekil 7.11'deki örneği inceleyin. Üretici, insert() yöntemini çağırır ve arabelleğin


dolduğunu görürse, wait() yöntemini çağırır. Bu çağrı kilidi serbest bırakır, üreticiyi engeller
ve üreticiyi nesne için bekleme kümesine sokar. Üretici kilidi serbest bıraktığından, tüketici en
sonunda, üretici için arabellekte alan boşalttığı remove() yöntemine girer .

Şekil 7.12, bir kilit için giriş ve bekleme setlerini göstermektedir. ( wait() bir InterruptedException
oluşturabilse de, kodun netliği ve basitliği için onu yok saymayı seçtiğimizi unutmayın.)

Tüketici ipliği, üreticinin artık devam edebileceğinin sinyalini nasıl veriyor?


Normal olarak, bir iş parçacığı senkronize bir yöntemden çıktığında , ayrılan
iş parçacığı yalnızca nesneyle ilişkili kilidi serbest bırakır, muhtemelen bir iş
parçacığını giriş kümesinden çıkarır ve ona kilidin sahipliğini verir. Ancak,
insert() ve remove() yöntemlerinin sonunda, notify() yöntemine bir çağrımız var .
Bildirim çağrısı ():

1. Bekleme kümesindeki iş parçacıkları listesinden rastgele bir iş parçacığı T seçer


306 Bölüm 7 Senkronizasyon Örnekleri
Machine Translated by Google

/* Üreticiler bu yöntemi çağırırlar */ public


synchronized void insert(E item) { while (count ==
BUFFER SIZE) { try { wait();

} yakalama (InterruptedException yani) { }


}

arabellek[içinde] = öğe;
in = (+1 olarak) % TAMPON BOYUTU;
say++;

bildir();
}

/* Tüketiciler bu yöntemi çağırır */ public


synchronized E remove() {
E öğesi;

while (sayım == 0) { dene


{ bekle();

} yakalama (InterruptedException yani) { }


}

item = arabellek[çıkış]; çıkış


= (çıkış + 1) % TAMPON BOYUTU; saymak--;

bildir();

ürünü geri vermek;


}

Şekil 7.11 wait() ve notify() kullanan insert() ve remove() yöntemleri .

2. T'yi bekleme kümesinden giriş kümesine taşır


3. T'nin durumunu bloke durumundan çalıştırılabilir duruma ayarlar

T artık diğer ipliklerle kilit için rekabet etmeye uygundur. T kilidin kontrolünü tekrar
ele geçirdiğinde, count değerini tekrar kontrol edebileceği wait() çağrısından
döner . (Yine, rastgele bir iş parçacığı seçimi Java belirtimine göre yapılır; pratikte,
çoğu Java sanal makinesi, bir FIFO ilkesine göre bekleme kümesinde iş parçacığı
sipariş eder.)
Machine Translated by Google

7.4 Java'da Senkronizasyon 307

kilit almak Bekle


nesne
kilidi

sahip

giriş seti bekleme seti

Şekil 7.12 Giriş ve bekleme setleri.

Ardından, wait() ve notify() yöntemlerini Şekil 7.11'de gösterilen yöntemler


açısından tanımlıyoruz. Tamponun dolu olduğunu ve nesnenin kilidinin mevcut
olduğunu varsayıyoruz.

• Üretici, insert() yöntemini çağırır, kilidin kullanılabilir olduğunu görür ve


yönteme girer. Yönteme girdikten sonra, üretici ara belleğin dolu olduğunu
belirler ve wait()'i çağırır. wait() çağrısı nesnenin kilidini serbest bırakır,
üreticinin durumunu bloke olarak ayarlar ve üreticiyi nesne için bekleme
kümesine koyar.
• Tüketici , nesnenin kilidi artık kullanılabilir olduğundan, en sonunda remove()
yöntemini çağırır ve girer. Tüketici arabellekten bir öğeyi kaldırır ve notify()'ı
çağırır. Tüketicinin hala nesnenin kilidine sahip olduğunu unutmayın.

• notify() çağrısı , üreticiyi nesne için bekleme kümesinden kaldırır, üreticiyi giriş
kümesine taşır ve üreticinin durumunu çalıştırılabilir olarak ayarlar.

• Tüketici, remove() yönteminden çıkar. Bu yöntemden çıkmak,


nesne için kilitleyin.
• Yapımcı kilidi geri almaya çalışır ve başarılı olur. Wait() çağrısından yürütmeyi
sürdürür . Üretici while döngüsünü test eder, arabellekte yer olup olmadığını
belirler ve insert() yönteminin geri kalanıyla devam eder . Nesne için bekleme
kümesinde hiçbir iş parçacığı yoksa, notify() çağrısı yok sayılır. Üretici
yöntemden çıktığında, nesnenin kilidini serbest bırakır.

Senkronize, wait () ve notify() mekanizmaları, başlangıcından beri Java'nın bir


parçası olmuştur. Ancak, Java API'sinin sonraki revizyonları , bazılarını aşağıdaki
bölümlerde inceleyeceğimiz çok daha esnek ve sağlam kilitleme mekanizmalarını
tanıttı.

7.4.2 Reentrant Kilitleri

Belki de API'de bulunan en basit kilitleme mekanizması Reentrant Lock'tur. Birçok


yönden, bir ReentrantLock , Bölüm 7.4.1'de açıklanan senkronize ifade gibi davranır :
ReentrantLock , tek bir iş parçacığına aittir ve paylaşılan bir kaynağa karşılıklı
olarak özel erişim sağlamak için kullanılır. Bununla birlikte, ReentrantLock , kilidin
en uzun bekleyen iş parçacığına verilmesini tercih eden bir adalet parametresi
ayarlamak gibi birkaç ek özellik sağlar . (Hatırlamak
Machine Translated by Google

308 Bölüm 7 Senkronizasyon Örnekleri

JVM belirtiminin, bir nesne kilidi için bekleme kümesindeki iş parçacıklarının


herhangi bir özel biçimde sıralanması gerektiğini belirtmediğini.)
Bir iş parçacığı , lock() yöntemini çağırarak bir ReentrantLock kilidi alır.
Kilit kullanılabilir durumdaysa veya iş parçacığını çağıran lock() zaten ona
sahipse, bu nedenle yeniden girişli olarak adlandırılırsa -lock() , çağrılan iş
parçacığı kilidi sahipliğini atar ve denetimi döndürür. Kilit kullanılamıyorsa,
çağıran iş parçacığı, sahibi unlock()'ı çağırdığında nihai olarak kilit atanana
kadar bloke eder. ReentrantLock , Kilit arabirimini uygular ; şu şekilde kullanılır:
Kilit tuşu = yeni ReentrantLock();

Tuş kilidi(); { /
* kritik
bölümü deneyin */

} nihayet
{ key.unlock();
}

try ve nihayet kullanmanın programlama deyimi biraz açıklama gerektirir.


Kilit, lock() yöntemiyle alınırsa, kilidin benzer şekilde serbest bırakılması önemlidir.
Unlock () 'u bir nihayet yan tümcesine dahil ederek, kritik bölüm tamamlandığında
veya try bloğu içinde bir istisna meydana geldiğinde kilidin serbest bırakılmasını
sağlarız . Lock() herhangi bir kontrol edilmiş istisna atmadığından , try yan
tümcesi içine lock() çağrısını yerleştirmediğimize dikkat edin . try yan tümcesine
lock() öğesini yerleştirirsek ve lock() çağrıldığında ( OutofMemoryError gibi )
denetlenmeyen bir özel durum oluşursa ne olacağını düşünün : nihayet yan
tümcesi unlock() çağrısını tetikler ve ardından denetlenmeyen
IllegalMonitorStateException'ı atar . kilit asla alınmadı. Bu Ille
galMonitorStateException , lock() çağrıldığında meydana gelen denetlenmeyen
istisnanın yerini alır ve böylece programın başlangıçta başarısız olmasının
nedenini gizler.
Bir ReentrantLock karşılıklı dışlama sağlarken, birden çok iş parçacığı
paylaşılan verileri yalnızca okuyor, ancak yazmıyorsa, çok tutucu bir strateji
olabilir. (Bu senaryoyu Bölüm 7.1.2'de tanımladık.) Bu ihtiyacı karşılamak için Java
API ayrıca, birden çok eşzamanlı okuyucuya ancak yalnızca bir yazara izin veren
bir kilit olan bir ReentrantReadWriteLock sağlar.

7.4.3 Semaforlar

Java API ayrıca Bölüm 6.6'da açıklandığı gibi bir sayma semaforu sağlar.
Semaforun yapıcısı şu şekilde görünür:
Semafor(int değeri);

değer, semaforun başlangıç değerini belirtir (negatif bir değere izin verilir).
Edinen iş parçacığı kesintiye uğrarsa, gain ( ) yöntemi bir InterruptedException
oluşturur. Aşağıdaki örnek, karşılıklı dışlama için bir semafor kullanmayı
göstermektedir:
Machine Translated by Google

7.4 Java'da Senkronizasyon 309

Semafor sem = yeni Semafor(1);

{ sem.acquire()'ı
deneyin ; /* kritik Bölüm */

} catch (InterruptedException yani) { } nihayet


{ sem.release();

Semaforun serbest bırakılmasını sağlamak için nihayet yan tümcesine release() çağrısını
yerleştirdiğimize dikkat edin .

7.4.4 Koşul Değişkenleri

Java API'sinde ele aldığımız son yardımcı program , koşul değişkenidir. ReentrantLock ,
Java'nın eşitlenmiş ifadesine benzer olduğu gibi , koşul değişkenleri de wait() ve notify()
yöntemlerine benzer işlevsellik sağlar.
Bu nedenle, karşılıklı dışlama sağlamak için bir koşul değişkeni, bir yeniden giriş kilidi ile
ilişkilendirilmelidir.
Önce bir ReentrantLock oluşturarak ve ilişkili ReentrantLock için koşul değişkenini
temsil eden bir Condition nesnesi döndüren newCondition() yöntemini çağırarak bir
koşul değişkeni yaratırız. Bu, aşağıdaki ifadelerde gösterilmektedir:

Kilit tuşu = yeni ReentrantLock(); Koşul


condVar = key.newCondition();

Koşul değişkeni elde edildikten sonra, Bölüm 6.7'de açıklanan wait() ve sinyal()
komutlarıyla aynı şekilde işlev gören wait( ) ve signal() yöntemlerini çağırabiliriz.

Bölüm 6.7'de açıklanan monitörlerde, wait() ve sinyal() işlemlerinin adlandırılmış


koşul değişkenlerine uygulanabileceğini ve bir iş parçacığının belirli bir koşul için
beklemesine veya belirli bir koşul karşılandığında bildirilmesine izin verdiğini hatırlayın.
Dil düzeyinde Java, adlandırılmış koşul değişkenleri için destek sağlamaz. Her Java
monitörü yalnızca bir adsız koşul değişkeni ile ilişkilendirilir ve Bölüm 7.4.1'de açıklanan
wait() ve notify() işlemleri yalnızca bu tek koşul değişkeni için geçerlidir. Bir Java iş
parçacığı notify() yoluyla uyandırıldığında, neden uyandırıldığına dair hiçbir bilgi almaz;
beklediği koşulun karşılanıp karşılanmadığını kontrol etmek yeniden etkinleştirilen iş
parçacığına bağlıdır. Koşul değişkenleri, belirli bir iş parçacığının bildirilmesine izin
vererek bunu düzeltir.

Aşağıdaki örnekle açıklıyoruz: Diyelim ki 0'dan 4'e kadar numaralandırılmış beş


ipliğimiz ve hangi ipliğin sırasını gösterdiğini gösteren paylaşılan bir değişken dönüş .
Bir iş parçacığı iş yapmak istediğinde, iş parçacığı numarasını ileterek Şekil 7.13'teki
doWork() yöntemini çağırır. Yalnızca threadNumber değeri turn değeriyle eşleşen iş
parçacığı devam edebilir; diğer iplikler sıralarını beklemelidir.
310 Bölüm 7 Senkronizasyon Örnekleri
Machine Translated by Google

/* threadNumber bazı işler yapmak isteyen iş parçacığıdır */ public void doWork(int


threadNumber) {

kilit.kilit();

{ /** *

deneyin , sıra bende değilse, işaret edilene


kadar * bekleyin. */ if (threadNumber !=
dönüş) condVars[threadNumber].await();

/**
* Bir süre biraz çalış... */

/**
* Şimdi bir sonraki iş parçacığına sinyal verin.
*/
dönüş = (dönüş + 1) % 5;
condVars[dönüş].signal();

} catch (InterruptedException yani) { } nihayet


{ lock.unlock();

}
}

Şekil 7.13 Java koşul değişkenlerini kullanma örneği.

Ayrıca sıradaki iş parçacığına sinyal vermek için bir ReentrantLock ve beş koşul
değişkeni (iş parçacığının beklediği koşulları temsil eden) oluşturmamız gerekir. Bu
aşağıda gösterilmiştir:
Kilit kilidi = yeni ReentrantLock();
Koşul[] koşulVars = yeni Koşul[5];

for (int i = 0; i < 5; i++) condVars[i] =


lock.newCondition();

Bir iş parçacığı doWork()' a girdiğinde, threadNumber'ı dönüşe eşit değilse ,


yalnızca başka bir iş parçacığı tarafından sinyal verildiğinde devam etmek için ilişkili
koşul değişkeninde wait () yöntemini çağırır . Bir iplik işini tamamladıktan sonra,
sırası gelen iplikle ilişkili koşul değişkenine sinyal verir.

ReentrantLock karşılıklı dışlama sağladığından doWork () öğesinin senkronize


olarak bildirilmesi gerekmediğine dikkat etmek önemlidir . ne zaman bir iş parçacığı
7.5 Alternatif Yaklaşımlar 311
Machine Translated by Google
koşul değişkeninde wait () öğesini çağırır , ilişkili Reen trantLock'u serbest
bırakarak başka bir iş parçacığının karşılıklı dışlama kilidini almasına izin verir.
Benzer şekilde, sinyal() çağrıldığında, yalnızca koşul değişkeni sinyallenir; kilit,
unlock() çağrılarak serbest bırakılır.

7.5 Alternatif Yaklaşımlar

Çok çekirdekli sistemlerin ortaya çıkmasıyla birlikte, birden çok işlem çekirdeğinden
yararlanan eşzamanlı uygulamalar geliştirmek için artan baskı geldi. Bununla birlikte,
eşzamanlı uygulamalar, yarış koşulları ve kilitlenme gibi canlılık tehlikeleri açısından
artan bir risk sunar. Geleneksel olarak, muteks kilitleri, semaforlar ve monitörler gibi
teknikler bu sorunları çözmek için kullanılmıştır, ancak işlem çekirdeklerinin sayısı
arttıkça, yarış koşullarından ve kilitlenmeden arınmış çok iş parçacıklı uygulamalar
tasarlamak giderek zorlaşır. Bu bölümde, iş parçacığı güvenli eşzamanlı
uygulamaların tasarımını destekleyen hem programlama dillerinde hem de
donanımda sağlanan çeşitli özellikleri keşfediyoruz.

7.5.1 İşlem Belleği

Bilgisayar biliminde oldukça sık olarak, bir çalışma alanındaki fikirler diğer
alanlardaki sorunları çözmek için kullanılabilir. Örneğin, veritabanı teorisinde
ortaya çıkan işlemsel bellek kavramı , ancak süreç senkronizasyonu için bir strateji
sağlar. Bir bellek işlemi , atomik olan bir bellek okuma-yazma işlemleri dizisidir. Bir
işlemdeki tüm işlemler tamamlanırsa, bellek işlemi tamamlanır. Aksi takdirde,
işlemler durdurulmalı ve geri alınmalıdır. İşlemsel belleğin faydaları, bir
programlama diline eklenen özellikler aracılığıyla elde edilebilir.

Bir örnek düşünün. Paylaşılan verileri değiştiren bir update() fonksiyonumuz


olduğunu varsayalım . Geleneksel olarak, bu işlev, aşağıdaki gibi muteks kilitleri
(veya semaforlar) kullanılarak yazılırdı: void update () {

elde etmek();

/* paylaşılan verileri değiştir */

serbest bırakmak();

Bununla birlikte, muteks kilitleri ve semaforlar gibi senkronizasyon mekanizmalarını


kullanmak, kilitlenme de dahil olmak üzere birçok potansiyel problemi içerir.
Ek olarak, iş parçacığı sayısı arttıkça, geleneksel kilitleme de ölçeklenmez, çünkü
kilit sahipliği için iş parçacıkları arasındaki çekişme seviyesi çok yüksek olur.

Geleneksel kilitleme yöntemlerine alternatif olarak, bir programlama diline


işlem belleğinden yararlanan yeni özellikler eklenebilir.
Örneğimizde, şunu sağlayan atomic{S} yapısını eklediğimizi varsayalım.
Machine Translated by Google

312 Bölüm 7 Senkronizasyon Örnekleri

S'deki işlemler bir işlem olarak yürütülür. Bu, update() işlevini aşağıdaki gibi yeniden
yazmamızı sağlar : void update() {

atom { /*
paylaşılan verileri değiştir */
}
}

Kilitler yerine böyle bir mekanizma kullanmanın avantajı, atomikliği önceden


garanti etmekten geliştiricinin değil, işlemsel bellek sisteminin sorumlu olmasıdır.
Ek olarak, hiçbir kilit dahil olmadığı için kilitlenme mümkün değildir. Ayrıca, bir
işlemsel bellek sistemi, paylaşılan bir değişkene eşzamanlı okuma erişimi gibi,
atomik bloklardaki hangi ifadelerin eşzamanlı olarak yürütülebileceğini belirleyebilir.
Elbette, bir programcının bu durumları tanımlaması ve okuyucu-yazıcı kilitlerini
kullanması mümkündür, ancak bir uygulama içindeki iş parçacığı sayısı arttıkça
görev giderek zorlaşır.
İşlemsel bellek, yazılım veya donanım olarak uygulanabilir.
Yazılım işlem belleği (STM), adından da anlaşılacağı gibi, işlem belleğini yalnızca
yazılımda uygular; özel bir donanıma gerek yoktur.
STM , işlem bloklarının içine enstrümantasyon kodu ekleyerek çalışır. Kod, bir
derleyici tarafından eklenir ve her işlemi, ifadelerin eşzamanlı olarak nerede
çalışabileceğini ve belirli düşük seviyeli kilitlemenin nerede gerekli olduğunu
inceleyerek yönetir. Donanım işlem belleği (HTM) , ayrı işlemcilerin önbelleklerinde
bulunan paylaşılan verileri içeren çakışmaları yönetmek ve çözmek için donanım
önbellek hiyerarşilerini ve önbellek tutarlılık protokollerini kullanır. HTM , özel bir
kod enstrümantasyonu gerektirmez ve bu nedenle STM'den daha az ek yüke sahiptir .
Ancak HTM , mevcut önbellek hiyerarşilerinin ve önbellek tutarlılık protokollerinin
işlem belleğini desteklemek için değiştirilmesini gerektirir.
İşlemsel bellek, yaygın bir uygulama olmaksızın birkaç yıldır varlığını
sürdürmektedir. Bununla birlikte, çok çekirdekli sistemlerin büyümesi ve eşzamanlı
ve paralel programlamaya ilişkin vurgu, hem akademisyenler hem de ticari yazılım
ve donanım satıcıları tarafından bu alanda önemli miktarda araştırma yapılmasına
neden oldu.

7.5.2 Açık MP

Bölüm 4.5.2'de, OpenMP'ye ve paylaşılan bellek ortamında paralel programlama


desteğine genel bir bakış sağladık. OpenMP'nin bir dizi derleyici yönergesi ve bir
API içerdiğini hatırlayın. #pragma omp parallel derleyici yönergesini izleyen
herhangi bir kod, paralel bir bölge olarak tanımlanır ve sistemdeki işlem çekirdeği
sayısına eşit sayıda iş parçacığı tarafından gerçekleştirilir.
OpenMP'nin (ve benzer araçların) avantajı, iş parçacığı oluşturma ve yönetiminin
OpenMP kitaplığı tarafından yapılması ve uygulama geliştiricilerin sorumluluğunda
olmamasıdır.
OpenMP , #pragma omp paralel derleyici yönergesiyle birlikte , yönergeyi takip
eden kod bölgesini aynı anda yalnızca bir iş parçacığının etkin olabileceği kritik bir
bölüm olarak belirten #pragma omp kritik derleyici yönergesini sağlar. Bu şekilde
OpenMP , iş parçacıklarının yarış koşulları oluşturmamasını sağlamak için destek
sağlar.
7.5 Alternatif Yaklaşımlar 313
Machine Translated by Google

Kritik bölüm derleyici yönergesinin kullanımına bir örnek olarak, önce paylaşılan
değişken sayacının update() işlevinde aşağıdaki gibi değiştirilebileceğini
varsayalım :
geçersiz güncelleme(int değeri)
{
sayaç += değer;
}

update() işlevi paralel bir bölgenin parçası olabilir veya buradan çağrılabilirse,
değişken sayacında bir yarış durumu mümkündür .
Bu yarışı düzeltmek için kritik bölüm derleyici yönergesi kullanılabilir
durum ve aşağıdaki gibi kodlanmıştır:

geçersiz güncelleme(int değeri)


{
#pragma omp kritik {

sayaç += değer;
}
}

Kritik bölüm derleyici yönergesi, bir ikili semafor veya muteks kilidi gibi davranır ve
kritik bölümde bir seferde yalnızca bir iş parçacığının etkin olmasını sağlar. Bir iş
parçacığı, o bölümde başka bir iş parçacığı etkinken (yani bölümün sahibiyken)
kritik bir bölüme girmeye çalışırsa , çağıran iş parçacığı, sahibi iş parçacığı çıkana
kadar engellenir. Birden fazla kritik bölüm kullanılması gerekiyorsa, her kritik
bölüme ayrı bir ad atanabilir ve bir kural, aynı adı taşıyan kritik bir bölümde aynı
anda birden fazla iş parçacığının etkin olamayacağını belirtebilir.

OpenMP'de kritik bölüm derleyici yönergesini kullanmanın bir avantajı,


kullanımının genellikle standart muteks kilitlerinden daha kolay kabul edilmesidir.
Bununla birlikte, bir dezavantaj, uygulama geliştiricilerinin yine de olası yarış
koşullarını belirlemesi ve derleyici yönergesini kullanarak paylaşılan verileri yeterince
koruması gerektiğidir. Ek olarak, kritik bölüm derleyici yönergesi bir muteks kilidi
gibi davrandığından, iki veya daha fazla kritik bölüm tanımlandığında kilitlenme
hala mümkündür.

7.5.3 İşlevsel Programlama Dilleri C, C++, Java ve C# gibi en

iyi bilinen programlama dilleri, zorunlu (veya prosedürel) diller olarak bilinir. Durum
tabanlı algoritmaları uygulamak için zorunlu diller kullanılır. Bu dillerde, algoritmanın
akışı, doğru çalışması için çok önemlidir ve durum, değişkenler ve diğer veri
yapılarıyla temsil edilir. Elbette program durumu değişkendir, çünkü değişkenlere
zaman içinde farklı değerler atanabilir.

Çok çekirdekli sistemler için eşzamanlı ve paralel programlamaya yapılan


mevcut vurgu ile , zorunlu dillerin sunduğundan çok farklı bir programlama
paradigmasını izleyen işlevsel programlama dillerine daha fazla odaklanılmıştır .
Zorunlu ve işlevsel diller arasındaki temel fark, işlevsel dillerin durumu korumamasıdır.
Yani, bir değişken tanımlanıp bir değer atandığında, değeri
Machine Translated by Google

314 Bölüm 7 Senkronizasyon Örnekleri

değişmezdir - değişemez. İşlevsel diller değişken duruma izin vermediğinden, ırk


koşulları ve
kilitlenmeler. Esasen, bu bölümde ele alınan sorunların çoğu,
fonksiyonel dillerde yoktur.
Şu anda kullanımda olan birkaç işlevsel dil vardır ve kısaca bahsedeceğiz.
ikisi burada: Erlang ve Scala. Erlang dili önemli bir değer kazanmıştır.
eşzamanlılık desteği ve kolaylıkla yapabilmesi nedeniyle dikkat
paralel sistemlerde çalışan uygulamalar geliştirmek için kullanılabilir. Scala, aynı
zamanda nesne yönelimli olan işlevsel bir dildir. Aslında, Scala'nın sözdiziminin çoğu
popüler nesne yönelimli diller Java ve C#'a benzer. Okuyucular, Erlang ve Scala ile ve
ayrıca işlevsel diller hakkında daha fazla ayrıntıyla ilgileniyor.
genel olarak, bu bölümün sonundaki kaynakçaya başvurmaları teşvik edilir.
ek referanslar için.

7.6 Özet

• İşlem senkronizasyonunun klasik sorunları arasında sınırlı arabellek,


okuyucu-yazar ve yemek-filozof sorunları. Bunlara çözümler
problemler, Mutex kilitleri, semaforlar, monitörler ve koşul değişkenleri dahil
olmak üzere Bölüm 6'da sunulan araçlar kullanılarak geliştirilebilir.

• Windows, süreci uygulamak için gönderici nesnelerinin yanı sıra olayları kullanır
senkronizasyon araçları.

• Linux, yarış koşullarına karşı koruma sağlamak için çeşitli yaklaşımlar kullanır,
atomik değişkenler, döndürme kilitleri ve muteks kilitleri dahil.

• POSIX API , muteks kilitleri, semaforlar ve koşul değişkenleri sağlar.


POSIX , iki tür semafor sağlar: adlandırılmış ve adsız. Birçok
alakasız süreçler aynı isimli semafora sadece ismine başvurarak kolayca erişebilir.
Adsız semaforlar bu kadar kolay paylaşılamaz,
ve semaforun paylaşılan hafızanın bir bölgesine yerleştirilmesini gerektirir.

• Java, senkronizasyon için zengin bir kütüphaneye ve API'ye sahiptir. Kullanılabilir araçlar şunları içerir:
monitörler (dil düzeyinde sağlanır) ve reentrant
kilitler, semaforlar ve koşul değişkenleri (bunlar
API).
• Kritik bölüm problemini çözmeye yönelik alternatif yaklaşımlar şunları içerir:
işlem belleği, OpenMP ve işlevsel diller. İşlevsel diller, farklı bir programlama
sundukları için özellikle ilgi çekicidir.
prosedürel dillerden paradigma. Yordamsal dillerin aksine, işlevsel diller
durumlarını korumazlar ve bu nedenle genellikle bağışıktırlar.
yarış koşullarından ve kritik bölümlerden.

Alıştırmalar

7.1 Windows ve Linux'un neden birden çok kilitleme mekanizması uyguladığını


açıklayın. Spinlock kullandıkları koşulları tanımlayın,
muteks kilitleri, semaforlar ve koşul değişkenleri. Her durumda, açıklayın
mekanizmaya neden ihtiyaç duyulur.
Machine Translated by Google

bibliyografya 315

7.2 Windows, ince okuyucu-yazıcı kilitleri adı verilen hafif bir eşitleme aracı sağlar .
Okuyucu-yazar kilitlerinin çoğu uygulaması ya okuyucuları ya da yazarları
tercih ederken ya da belki bir FIFO politikası kullanarak bekleyen dizileri
sipariş ederken, ince okuyucu-yazar kilitleri ne okuyucuları ne de yazarları
destekler ve bekleyen diziler bir FIFO kuyruğunda sıralanmaz. Böyle bir
senkronizasyon aracı sağlamanın faydalarını açıklayın.
7.3 İkili bir semafor yerine bir muteks kilidinin kullanılabilmesi için, Şekil 7.1 ve
Şekil 7.2'de üretici ve tüketici süreçlerinde hangi değişikliklerin gerekli
olacağını açıklayın.
7.4 Yemek-filozofları probuyla kilitlenmenin nasıl mümkün olduğunu açıklayın
lem.

7.5 Windows gönderici nesneleri ile sinyalli ve sinyalsiz durumlar arasındaki farkı
açıklayın.
7.6 Val'in bir Linux sistemindeki atomik bir tam sayı olduğunu varsayın . Aşağıdaki
işlemler tamamlandıktan sonra val değeri nedir ?

atomik küme(&val,10);
atomik alt(8,&val); atom
inc(&val); atom inc(&val);
atomik toplama(6,&val);
atom alt(3,&val);

Daha fazla okuma

Windows senkronizasyonunun ayrıntıları [Solomon ve Russi novich (2000)]'de


bulunabilir. [Love (2010)], Linux çekirdeğindeki senkronizasyonu açıklar.
[Hart (2005)], Windows kullanılarak iş parçacığı senkronizasyonunu açıklar.
[Breshears (2009)] ve [Pacheco (2011)], paralel programlamayla ilgili senkronizasyon
konularının ayrıntılı kapsamını sağlar. OpenMP kullanımına ilişkin ayrıntılar http://
openmp.org adresinde bulunabilir . Hem [Oaks (2014)] hem de [Goetz et al. (2006)]
Java'daki geleneksel senkronizasyon ve CAS tabanlı stratejilerin zıttıdır.

bibliyografya

[Breshears (2009)] C. Breshears, The Art of Concurrency, O'Reilly & Associates


(2009).

[Goetz et al. (2006)] B. Goetz, T. Peirls, J. Bloch, J. Bowbeer, D. Holmes ve D. Lea, Java
Concurrency in Practice, Addison-Wesley (2006).

[Hart (2005)] JM Hart, Windows Sistem Programlama, Üçüncü Baskı, Addison


Wesley (2005).

[Love (2010)] R. Love, Linux Kernel Development, Third Edition, Developer's


Kütüphane (2010).
Machine Translated by Google

316 Bölüm 7 Senkronizasyon Örnekleri

[Oaks (2014)] S. Oaks, Java Performance—The Definitive Guide, O'Reilly & Asso
alıntılar (2014).

[Pacheco (2011)] PS Pacheco, Paralel Programlamaya Giriş, Morgan


Kaufmann (2011).

[Solomon ve Russinovich (2000)] DA Solomon ve ME Russinovich,


Microsoft Windows 2000, Üçüncü Sürüm, Microsoft Press (2000) içinde.
Machine Translated by Google

Egzersizler EX-26

Bölüm 7 Alıştırmalar

7.7 Yarış koşullarının mümkün olduğu iki çekirdek veri yapısını tanımlayın. Bir yarış
durumunun nasıl oluşabileceğine dair bir açıklama eklediğinizden emin olun.

7.8 Linux çekirdeği, bir sürecin bir semafor elde etmeye çalışırken bir döndürme kilidi
tutamayacağına dair bir ilkeye sahiptir. Bu politikanın neden yürürlükte olduğunu açıklayın.

7.9 Tamponların (kısımların) monitörün içinde gömülü olduğu bir sınırlı arabellek
monitörü için bir algoritma tasarlayın.
7.10 Bir monitördeki katı karşılıklı dışlama, sınırlı arabelleği yapar
Alıştırma 7.14'ün monitörü esas olarak küçük porsiyonlar için uygundur.

a. Bunun neden doğru olduğunu açıklayın.

b. Daha büyük porsiyonlar için uygun yeni bir şema tasarlayın.

7.11 Okur-yazar sorununda adillik ve işlem hacmi arasındaki dengeyi tartışın. Okur-yazar
sorununu açlığa neden olmadan çözmek için bir yöntem önerin.

7.12 Java ReentrantLock'taki lock() yöntemine yapılan çağrının neden istisna işleme için
try yan tümcesine yerleştirilmediğini , ancak unlock() yöntemine yapılan çağrının
neden bir nihayet yan tümcesine yerleştirildiğini açıklayın.

7.13 Yazılım ve donanım işlemleri arasındaki farkı açıklayın


hafıza.
Machine Translated by Google

P-34 Bölüm 7 Senkronizasyon Örnekleri

Programlama Sorunları

7.14 Alıştırma 3.20 , her sürece benzersiz bir süreç tanımlayıcısı tahsis eden bir PID yöneticisi
tasarlamanızı gerektiriyordu . Alıştırma 4.28, süreç tanımlayıcılarını talep eden ve
serbest bırakan bir dizi iş parçacığı yaratan bir program yazarak çözümünüzü Alıştırma
3.20'ye göre değiştirmenizi gerektiriyordu. Mutex kilitlerini kullanarak, süreç
tanımlayıcılarının kullanılabilirliğini temsil etmek için kullanılan veri yapısının yarış
koşullarından güvenli olmasını sağlayarak çözümünüzü Alıştırma 4.28'e göre değiştirin.

7.15 Alıştırma 4.27'de Fibonacci dizisini oluşturmak için bir program yazdınız. Program,
hesaplanan değerleri yazdırmadan önce ana iş parçacığının alt iş parçacığının
yürütmesini bitirmesini beklemesini gerektiriyordu.
Ana iş parçacığının, alt iş parçacığı tarafından hesaplandığı anda Fibonacci sayılarına
erişmesine izin verirsek - alt iş parçacığının sona ermesini beklemek yerine - bu
alıştırmanın çözümünde ne gibi değişiklikler gerekli olur? Değiştirilmiş çözümünüzü
uygulayın.

7.16 C programı stack-ptr.c (kaynak kodu indirme dosyasında mevcuttur), bağlantılı bir liste
kullanan bir yığın uygulamasını içerir. Kullanımının bir örneği aşağıdaki gibidir:

StackNode *üst = NULL;


itme(5, &üst); itme(10,
&üst); bas(15, &üst);

int değeri = pop(&top);


değer = açılır(&üst);
değer = açılır(&üst);
Bu program şu anda bir yarış koşuluna sahiptir ve eşzamanlı bir ortam için uygun
değildir. Pthreads muteks kilitlerini kullanarak (Bölüm 7.3.1'de açıklanmıştır), yarış
durumunu düzeltin.

7.17 Alıştırma 4.24, Monte Carlo tekniğini kullanarak π'yi tahmin eden çok iş parçacıklı bir
program tasarlamanızı istedi. Bu alıştırmada, sonucu global bir değişkende saklayarak
rastgele noktalar oluşturan tek bir iş parçacığı oluşturmanız istendi. Bu iş parçacığı
çıktıktan sonra, ana iş parçacığı π değerini tahmin eden hesaplamayı gerçekleştirdi.
Bu programı, her biri rastgele noktalar oluşturan ve noktaların daire içine girip
girmediğini belirleyen birkaç iş parçacığı oluşturacak şekilde değiştirin. Her iş
parçacığı, daire içine giren tüm noktaların genel sayısını güncellemek zorunda kalacak.

Mutex kilitlerini kullanarak paylaşılan global değişken güncellemelerinde yarış


koşullarına karşı koruma sağlayın.

7.18 Alıştırma 4.25 , Monte Carlo tekniğini kullanarak π tahmin eden OpenMP kullanarak bir
program tasarlamanızı istedi . Olası yarış koşullarını arayan o programa yönelik
çözümünüzü inceleyin. Bir yarış durumu belirlerseniz, Bölüm 7.5.2'de özetlenen
stratejiyi kullanarak buna karşı koruyun.

7.19 Bir bariyer , bir dizi iş parçacığının aktivitesini senkronize etmek için bir araçtır.
Bir iplik bir engel noktasına ulaştığında, diğer tüm iplikler geçene kadar ilerleyemez.
Machine Translated by Google

Programlama Projeleri P-35

Konular da bu noktaya geldi. Son iplik engel noktasına ulaştığında, tüm iplikler
serbest bırakılır ve eşzamanlı olarak devam edebilir.
uygulamak.
Bariyerin N olarak başlatıldığını varsayalım - iş parçacığı sayısı
bariyer noktasında beklemesi gereken:
init(N);

Her iplik daha sonra bariyer noktasına ulaşana kadar bir miktar iş yapar:
/* bir süreliğine biraz çalış */

bariyer noktası();

/* bir süreliğine biraz çalış */

Bu bölümde açıklanan POSIX veya Java senkronizasyon araçlarını kullanma


bölümünde, aşağıdaki API'yi uygulayan bir bariyer oluşturun :

• int init(int n)— Engeli belirtilen boyutta başlatır. • int bariyer noktası(void)

— Engel noktasını tanımlar. Son iplik bu noktaya ulaştığında tüm iplikler


bariyerden serbest bırakılır.

Her işlevin dönüş değeri, hata koşullarını belirlemek için kullanılır.


Normal çalışma sırasında her işlev 0 döndürür ve bir hata oluşursa -1 döndürür.
Bariyer uygulamanızı test etmek için kaynak kodu indirmesinde bir test donanımı
sağlanmıştır.

Programlama Projeleri

Proje 1—Bir İplik Havuzu Tasarlamak


İplik havuzları Bölüm 4.5.1'de tanıtılmıştır. İş parçacığı havuzları kullanıldığında,
havuza bir görev gönderilir ve havuzdan bir iş parçacığı tarafından yürütülür. İş, bir
kuyruk kullanılarak havuza gönderilir ve kullanılabilir bir iş parçacığı, işi kuyruktan
kaldırır. Kullanılabilir iş parçacığı yoksa, iş biri kullanılabilir hale gelene kadar kuyruğa
alınır. İş yoksa, bir görev kullanılabilir hale gelene kadar iş parçacıkları bildirim bekler.

Bu proje, bir iş parçacığı havuzu oluşturmayı ve yönetmeyi içerir ve Pthreds ve


POSIX senkronizasyonu veya Java kullanılarak tamamlanabilir. Aşağıda her bir özel
teknolojiyle ilgili ayrıntıları sunuyoruz.

I. POSIX

Bu projenin POSIX sürümü, senkronizasyon için POSIX mutex kilitleri ve semaforlarının


yanı sıra Pthreads API'sini kullanarak bir dizi iş parçacığı oluşturmayı içerecektir .
Machine Translated by Google

P-36 Bölüm 7 Senkronizasyon Örnekleri

Müşteri

İş parçacığı havuzunun kullanıcıları aşağıdaki API'yi kullanır:

• void pool init()— İş parçacığı havuzunu başlatır. • int


pool send(void (*somefunction)(void *p), void *p)—
burada bir işlev, havuzdan bir iş parçacığı tarafından yürütülecek işlevin bir göstergesidir
ve p , işleve iletilen bir parametredir. • void pool shutdown(void)—Tüm görevler

tamamlandığında iş parçacığı havuzunu kapatır.

Kaynak kodu indirmesinde, bu işlevleri kullanarak iş parçacığı havuzunun nasıl kullanılacağını


gösteren örnek bir client.c programı sunuyoruz.

Konu Havuzunun Uygulanması

Kaynak kodu indirmesinde , thread havuzunun kısmi bir uygulaması olarak threadpool.c C kaynak
dosyasını sağlıyoruz . İstemci kullanıcıları tarafından çağrılan işlevlerin yanı sıra iş parçacığı
havuzunun iç kısımlarını destekleyen birkaç ek işlevi uygulamanız gerekecektir. Uygulama
aşağıdaki faaliyetleri içerecektir:

1. pool init() işlevi, başlangıçta olduğu kadar, iş parçacıklarını da oluşturur .


karşılıklı dışlama kilitlerini ve semaforları başlatın.

2. pool send() işlevi kısmen uygulanır ve şu anda yürütülecek işlevi ve verilerini bir görev
yapısına yerleştirir. Görev yapısı, havuzdaki bir iş parçacığı tarafından tamamlanacak işi
temsil eder . havuz gönderme() , enqueue() işlevini çağırarak bu görevleri kuyruğa ekler
ve işçi iş parçacıkları, işi kuyruktan almak için dequeue () 'yi çağırır . Kuyruk, statik olarak
(diziler kullanılarak) veya dinamik olarak (bağlantılı bir liste kullanılarak) uygulanabilir.

pool init() işlevi, görevin havuza başarıyla gönderilip gönderilmediğini belirtmek için
kullanılan bir int dönüş değerine sahiptir (0 başarıyı, 1 başarısızlığı belirtir) . Kuyruk
diziler kullanılarak uygulanırsa, iş gönderme girişimi varsa ve kuyruk doluysa pool init() 1
değerini döndürür. Kuyruk bağlantılı bir liste olarak uygulanırsa, bir bellek ayırma hatası
oluşmadığı sürece pool init() her zaman 0 döndürmelidir.

3. işçi() işlevi , havuzdaki her bir iş parçacığı tarafından yürütülür, burada her iş parçacığı
kullanılabilir çalışmayı bekleyecektir. İş kullanılabilir hale geldiğinde, iş parçacığı onu
kuyruktan kaldırır ve belirtilen işlevi çalıştırmak için execute() öğesini çağırır.

İş parçacığı havuzuna gönderildiğinde bekleyen bir iş parçacığını bildirmek için


bir semafor kullanılabilir. Adlandırılmış veya adsız semaforlar kullanılabilir. POSIX
semaforlarını kullanma hakkında daha fazla ayrıntı için Bölüm 7.3.2'ye bakın .
Machine Translated by Google

Programlama Projeleri P-37

4. Kuyruğa erişirken veya sırayı değiştirirken yarış koşullarından kaçınmak için bir
muteks kilidi gereklidir. (Bölüm 7.3.1, Pthreads muteks kilitleriyle ilgili ayrıntıları
sağlar.)

5. Havuz kapatma() işlevi, her çalışan iş parçacığını iptal edecek ve ardından her iş
parçacığının pthread birleştirme()' yi çağırarak sonlandırılmasını bekleyecektir .
POSIX iş parçacığı iptaliyle ilgili ayrıntılar için Bölüm 4.6.3'e bakın . (Semafor
işlemi sem wait() , bir semaforda bekleyen bir iş parçacığının iptal edilmesini
sağlayan bir iptal noktasıdır.)

Bu projeyle ilgili ek ayrıntılar için kaynak kodu indirmesine bakın. Özellikle,


BENİOKU dosyası, kaynak ve başlık dosyalarının yanı sıra projeyi oluşturmak için
Makefile'ı açıklar.

II. Java

Bu projenin Java sürümü, Bölüm 7.4'te açıklandığı gibi Java senkronizasyon araçları
kullanılarak tamamlanabilir. Senkronizasyon, (a) synchronized/wait()/notify() (Bölüm
7.4.1) kullanan monitörlere veya (b) semaforlara ve yeniden giriş kilitlerine (Bölüm 7.4.2
ve Bölüm 7.4.3) bağlı olabilir. Java iş parçacıkları Bölüm 4.4.3'te açıklanmıştır.

Konu Havuzunun Uygulanması

İş parçacığı havuzunuz aşağıdaki API'yi uygulayacaktır:

• ThreadPool()— Varsayılan boyutlu bir iş parçacığı havuzu oluşturun.

• ThreadPool(int size)—Boyut boyutunda bir iş parçacığı havuzu oluşturun . • void

add(Çalıştırılabilir görev)—İçindeki bir iş parçacığı tarafından gerçekleştirilecek bir görev ekleyin.


havuz.

• void shutdown()— Havuzdaki tüm dizileri durdurur.

Java kaynak dosyasını ThreadPool.java kaynak kodu indirme işleminde iş parçacığı


havuzunun kısmi bir uygulaması olarak sunuyoruz. İstemci kullanıcıları tarafından
çağrılan yöntemlerin yanı sıra iş parçacığı havuzunun iç kısımlarını destekleyen birkaç
ek yöntemi uygulamanız gerekecektir. Uygulama aşağıdaki faaliyetleri içerecektir:

1. Yapıcı önce çalışmayı bekleyen bir dizi boşta iş parçacığı oluşturacaktır.

2. Çalışma, Runnable arabirimini uygulayan bir görev ekleyen add() yöntemi


aracılığıyla havuza gönderilir . add() yöntemi, Runnable görevini bir kuyruğa
yerleştirecektir ( Java API'sinden java.util.List gibi kullanılabilir bir yapı
kullanabilirsiniz ).

3. Havuzdaki bir iş parçacığı iş için uygun olduğunda, herhangi bir Çalıştırılabilir


görev için kuyruğu kontrol eder. Böyle bir görev varsa, boştaki iş parçacığı
görevi kuyruktan kaldırır ve run() yöntemini çağırır. Kuyruk boşsa, boşta iş
parçacığı çalışırken bilgilendirilmek için bekler
Machine Translated by Google

P-38 Bölüm 7 Senkronizasyon Örnekleri

kullanılabilir hale gelir. ( add() yöntemi, çalışmayı bekleyen boşta bir iş parçacığını
uyandırmak için bir Çalıştırılabilir görevi kuyruğa yerleştirdiğinde, notify() veya semafor
işlemlerini kullanarak bildirim uygulayabilir .)

4. Kapatma () yöntemi, kesme() yöntemini çağırarak havuzdaki tüm iş parçacıklarını


durduracaktır . Bu, elbette, iş parçacığı havuzu tarafından yürütülen Çalıştırılabilir görevlerin
kesinti durumlarını kontrol etmesini gerektirir ( Bölüm 4.6.3).

Bu projeyle ilgili ek ayrıntılar için kaynak kodu indirmesine bakın. Özellikle, BENİOKU dosyası
Java kaynak dosyalarını ve ayrıca Java iş parçacığı kesintisi hakkında daha fazla ayrıntıyı açıklar.

Proje 2—Uyuyan Eğitim Asistanı


Bir üniversitenin bilgisayar bilimleri bölümünde, lisans öğrencilerine normal mesai saatleri içinde
programlama ödevlerinde yardımcı olan bir öğretim asistanı (TA) bulunur . TA'nın ofisi oldukça
küçüktür ve içinde sandalye ve bilgisayar bulunan tek bir masa için yer vardır. Ofisin dışındaki
koridorda, TA şu anda başka bir öğrenciye yardım ediyorsa öğrencilerin oturup bekleyebilecekleri
üç sandalye vardır . Mesai saatleri içinde yardıma ihtiyacı olan öğrenci olmadığında, asistan
masaya oturur ve şekerleme yapar. Bir öğrenci mesai saatleri içinde gelir ve TA'yı uyurken bulursa,
öğrenci yardım istemek için ÖA'yı uyandırmalıdır. Bir öğrenci gelir ve TA'nın başka bir öğrenciye
yardım ettiğini görürse, öğrenci koridordaki sandalyelerden birine oturur ve bekler. Sandalye
yoksa, öğrenci daha sonra geri gelecektir.

POSIX iş parçacıklarını, muteks kilitlerini ve semaforları kullanarak , TA ve öğrencilerin


aktivitelerini koordine eden bir çözüm uygulayın . Bu ödevin detayları aşağıda verilmiştir.

Öğrenciler ve TA

Pthreads'i (Bölüm 4.4.1) kullanarak, her öğrencinin ayrı bir iş parçacığı olarak çalışacağı n
öğrenci oluşturarak başlayın. TA , ayrı bir iş parçacığı olarak da çalışacaktır.
Öğrenci konuları, belirli bir süre için programlama ve TA'dan yardım isteme arasında değişecektir .
TA mevcutsa , yardım alacaklardır. Aksi takdirde, ya koridorda bir sandalyeye oturacaklar ya da hiç
sandalye yoksa, programlamaya devam edecekler ve daha sonra yardım isteyeceklerdir. Bir
öğrenci gelir ve TA'nın uyuduğunu fark ederse, semafor kullanarak TA'ya haber vermelidir. TA bir
öğrenciye yardım etmeyi bitirdiğinde , öğretim görevlisi koridorda yardım bekleyen öğrencilerin
olup olmadığını kontrol etmelidir. Eğer öyleyse, TA sırayla bu öğrencilerin her birine yardım
etmelidir. Öğrenci yoksa, TA uykuya dönebilir.

Öğrenci programlamasının simülasyonunun yanı sıra bir öğrenciye yardım sağlayan TA'nın
simülasyonu için belki de en iyi seçenek , uygun iş parçacıklarının rastgele bir süre boyunca
uyumasını sağlamaktır.
POSIX muteks kilitlerinin ve semaforlarının kapsamı Bölüm 7.3'te verilmiştir.
Ayrıntılar için o bölüme bakın.
Machine Translated by Google

Programlama Projeleri P-39

Proje 3—Yemek-Filozoflar Sorunu


Bölüm 7.1.3'te, monitörleri kullanarak yemek filozofları sorununa bir çözüm
taslağı sunuyoruz. Bu proje, POSIX muteks kilitleri ve koşul değişkenleri veya
Java koşul değişkenleri kullanılarak bu soruna bir çözüm uygulanmasını içerir .
Çözümler, Şekil 7.7'de gösterilen algoritmaya dayalı olacaktır.

Her iki uygulama da her biri 0 sayısı ile tanımlanan beş filozofun oluşturulmasını
gerektirecektir. . 4. Her filozof ayrı bir iş parçacığı olarak çalışacaktır. Felsefeciler
düşünmek ve yemek arasında gidip gelirler. Her iki aktiviteyi de simüle etmek için, her
bir iş parçacığının bir ile üç saniye arasında rastgele bir süre boyunca uyumasını sağlayın.

I. POSIX

Pthreads kullanarak iplik oluşturma Bölüm 4.4.1'de anlatılmaktadır. Bir filozof


yemek yemek istediğinde, işlevi çağırır.

pikap çatalları(int filozof numarası)

burada filozof sayısı yemek yemek isteyen filozof sayısını tanımlar. Bir filozof
yemeyi bitirdiğinde,

dönüş çatalları(int filozof numarası)

Uygulamanız, Bölüm 7.3'te ele alınan POSIX koşul değişkenlerinin kullanılmasını


gerektirecektir .

II. Java

Bir filozof yemek yemek istediğinde, take Forks(filozoferNumber)


yöntemini çağırır; burada filozofNumber yemek isteyen filozofun sayısını
tanımlar. Bir filozof yemeyi bitirdiğinde, returnForks(philosopherNumber)
işlevini çağırır.
Çözümünüz aşağıdaki arayüzü uygulayacaktır:

genel arayüz DiningServer {

/* Bir filozof yemek yemek istediğinde onu çağırır */ public


void takeForks(int filozofNumber);

/* Yemeyi bitirdiğinde bir filozof tarafından çağrılır */ public void


returnForks(int filozofNumber);
}

Bölüm 7.4.4'te ele alınan Java koşul değişkenlerinin kullanımını gerektirecektir.


Machine Translated by Google

P-40 Bölüm 7 Senkronizasyon Örnekleri

Proje 4—Üretici-Tüketici Problemi


Bölüm 7.1.1'de, sınırlı bir tampon kullanarak üretici-tüketici sorununa semafor tabanlı bir çözüm
sunduk. Bu projede, Şekil 5.9 ve 5.10'da gösterilen üretici ve tüketici süreçlerini kullanarak sınırlı
arabellek sorununa bir programlama çözümü tasarlayacaksınız. Bölüm 7.1.1'de sunulan çözüm
üç semafor kullanır: arabellekteki boş ve dolu yuvaların sayısını sayan boş ve dolu ve fiili ekleme
veya çıkarmayı koruyan ikili (veya karşılıklı dışlama) bir semafor olan muteks . arabellekteki öğeler.
Bu proje için, boş ve dolu için standart sayma semaforlarını ve muteksi temsil etmek için ikili bir
semafor yerine bir muteks kilidi kullanacaksınız . Üretici ve tüketici - ayrı iş parçacıkları olarak çalışır
- öğeleri boş, dolu ve muteks yapılarıyla senkronize edilmiş bir arabelleğe ve ara bellekten taşır .
Bu sorunu Pthreads veya Windows API kullanarak çözebilirsiniz.

Tampon

Dahili olarak, arabellek sabit boyutlu bir tür arabellek öğesi dizisinden oluşacaktır (bir typedef
kullanılarak tanımlanacaktır ). Arabellek öğesi nesneleri dizisi dairesel bir kuyruk olarak işlenecektir.
Arabellek öğesinin tanımı, arabelleğin boyutuyla birlikte aşağıdaki gibi bir başlık dosyasında
saklanabilir:

/* arabellek.h */
typedef int arabellek öğesi;
#define TAMPON BOYUTU 5

Tampon , sırasıyla üretici ve tüketici iş parçacıkları tarafından çağrılan item () ekleme ve item()
kaldırma olmak üzere iki fonksiyonla manipüle edilecektir . Bu işlevleri özetleyen bir iskelet Şekil
7.14'te görülmektedir.
item() ekleme ve item() kaldırma işlevleri , Şekil 7.1 ve Şekil 7.2'de özetlenen algoritmaları
kullanarak üretici ve tüketiciyi senkronize edecektir. Tampon ayrıca, boş ve dolu semaforlarla
birlikte karşılıklı dışlama nesne muteksini başlatan bir başlatma işlevi gerektirecektir .

main() işlevi , arabelleği başlatacak ve ayrı üretici ve tüketici iş parçacıklarını yaratacaktır.


Üretici ve tüketici iş parçacıklarını oluşturduktan sonra, main() işlevi bir süre uyur ve uyandıktan
sonra uygulamayı sonlandırır. main() işlevine komut satırında üç parametre iletilecektir:

1. Sonlandırmadan önce ne kadar uyumalı 2. Üretici

iş parçacığı sayısı
3. Tüketici iş parçacığı sayısı

Bu fonksiyon için bir iskelet Şekil 7.15'te görülmektedir.


Machine Translated by Google

Programlama Projeleri P-41

#include "buffer.h"

/* arabellek */
arabellek öğesi arabellek[BUFFER SIZE];

int öğe ekle(arabellek öğesi öğesi) { /* öğeyi


arabelleğe ekle başarılıysa 0 döndür, aksi
takdirde bir hata durumunu belirten -1 döndür
*/
}

int öğeyi kaldır(arabellek öğesi *item) { /* bir


nesneyi arabellekten kaldır, öğeyi öğeye
yerleştirerek başarılı olursa 0, aksi takdirde
bir hata durumunu belirten -1 döndür */

Şekil 7.14 Tampon işlemlerinin ana hatları.

Üretici ve Tüketici Konuları

Üretici iş parçacığı, rastgele bir süre uyuma ve arabelleğe rastgele bir tamsayı ekleme
arasında geçiş yapacak. Rastgele sayılar, 0 ile RAND MAX arasında rasgele tamsayılar
üreten Rand() işlevi kullanılarak üretilecektir . Tüketici ayrıca rastgele bir süre uyuyacak ve
uyandıktan sonra arabellekteki bir öğeyi çıkarmaya çalışacaktır.

Üretici ve tüketici konularına ilişkin bir taslak Şekil 7.16'da görülmektedir.

#include "buffer.h"

int main(int argc, char *argv[]) { /* 1. Komut


satırı argümanlarını al argv[1],argv[2],argv[3] */ /* 2. Tamponu başlat */ /* 3.
Oluştur üretici ileti dizileri */ /* 4. Tüketici ileti dizileri oluştur */ /* 5. Uyku */ /* 6.
Çıkış */ }

Şekil 7.15 İskelet programının ana hatları.


Machine Translated by Google

P-42 Bölüm 7 Senkronizasyon Örnekleri

#include <stdlib.h> /* rand() için gerekli */


#include "buffer.h"

void *prodüktör(void *param) { arabellek


öğesi öğesi;

while (true) { /*
rastgele bir süre uyku */ sleep(...); /* rastgele bir sayı
üret */ item = rand(); if (öğe ekle(öğe)) fprintf("hata
durumunu bildir"); else printf("üretici %d n üretti",item);

void *consumer(void *param) { arabellek


öğesi öğesi;

while (true) { /*
rastgele bir süre uyku */ sleep(...); if (öğeyi
kaldır(&item)) fprintf("hata durumunu bildir");

başka

printf("tüketici %d n tüketti",item);
}

Şekil 7.16 Üretici ve tüketici konularının ana hatları.

Daha önce belirtildiği gibi, bu sorunu Pthreads veya Windows API kullanarak
çözebilirsiniz. Aşağıdaki bölümlerde, bu seçeneklerin her biri hakkında daha fazla
bilgi veriyoruz.

Pthreads Konu Oluşturma ve Senkronizasyon

Pthreads API'sini kullanarak iş parçacıkları oluşturma , Bölüm 4.4.1'de tartışılmaktadır.


Pthreads kullanan muteks kilitleri ve semaforların kapsamı Bölüm 7.3'te verilmiştir.
Pthreads iş parçacığı oluşturma ve senkronizasyonla ilgili özel talimatlar için bu
bölümlere bakın.

Windows Konuları

Bölüm 4.4.2, Windows API kullanarak iş parçacığı oluşturmayı tartışır . Konu


oluşturmaya ilişkin özel talimatlar için bu bölüme bakın.
Machine Translated by Google

Programlama Projeleri P-43

Windows Mutex Kilitleri

Mutex kilitleri, Bölüm 7.2.1'de açıklandığı gibi bir tür dağıtıcı nesnesidir. Aşağıda,
CreateMutex() işlevi kullanılarak bir muteks kilidinin nasıl oluşturulacağı
gösterilmektedir:

#include <windows.h>

KOL Mutex;
Mutex = CreateMutex(BOŞ, YANLIŞ, BOŞ);

İlk parametre, muteks kilidi için bir güvenlik özniteliğine başvurur. Bu özniteliği
NULL olarak ayarlayarak , işlemin herhangi bir alt öğesinin kilidin tutamağını
devralmak için bu muteks kilidini oluşturmasını engelleriz. İkinci parametre, muteks
kilidinin yaratıcısının kilidin ilk sahibi olup olmadığını gösterir. YANLIŞ değeri
iletmek, mutex'i oluşturan iş parçacığının ilk sahip olmadığını gösterir.
(Muteks kilitlerinin nasıl elde edildiğini yakında göreceğiz.) Üçüncü parametre,
mutekse isim vermemizi sağlar. Ancak, bir NULL değeri sağladığımız için mutekse
isim vermeyiz. Başarılı olursa, CreateMutex() muteks kilidine bir HANDLE döndürür ;
aksi halde NULL döndürür.
Bölüm 7.2.1'de, gönderici nesnelerini sinyalli veya sinyalsiz olarak tanımladık .
Sahiplik için bir sinyal gönderici nesnesi (bir muteks kilidi gibi) mevcuttur.
Edinildiğinde, sinyalsiz duruma geçer. Serbest bırakıldığında sinyalli duruma döner.

Mutex kilitleri, WaitForSingleObject() işlevi çağrılarak elde edilir. İşlev, ne


kadar süre bekleneceğini gösteren bir bayrakla birlikte HANDLE'dan kilide geçirilir.
Aşağıdaki kod, yukarıda oluşturulan muteks kilidinin nasıl elde edilebileceğini
gösterir:

WaitForSingleObject(Mutex, INFINITE);

INFINITE parametre değeri , kilidin kullanılabilir hale gelmesi için sonsuz bir süre
bekleyeceğimizi belirtir. Kilit belirli bir süre içinde kullanılabilir hale gelmezse,
çağıran iş parçacığının zaman aşımına uğramasına izin verecek başka değerler
kullanılabilir. Kilit sinyal durumundaysa, WaitForSingleObject() hemen döner ve kilit
sinyalsiz hale gelir. ReleaseMutex()' i çağırarak bir kilit serbest bırakılır (sinyal edilen
duruma geçer )— örneğin, aşağıdaki gibi:

ReleaseMutex(Mutex);

Windows Semaforları

Windows API'sindeki semaforlar , dağıtıcı nesnelerdir ve bu nedenle muteks


kilitleriyle aynı sinyal mekanizmasını kullanır. Semaforlar şu şekilde oluşturulur:

#include <windows.h>

KULP Sem;
Sem = CreateSemaphore(NULL, 1, 5, NULL);
Machine Translated by Google

P-44 Bölüm 7 Senkronizasyon Örnekleri

İlk ve son parametreler, muteks kilitleri için tanımladığımıza benzer şekilde, bir
güvenlik özniteliği ve semafor için bir isim tanımlar. İkinci ve üçüncü parametreler,
semaforun başlangıç değerini ve maksimum değerini gösterir. Bu örnekte,
semaforun başlangıç değeri 1 ve maksimum değeri 5'tir. Başarılı olursa,
CreateSemaphore() muteks kilidine bir HANDLE döndürür ; aksi halde NULL döndürür.

Semaforlar, muteks kilitleriyle aynı WaitForSingleObject() işleviyle elde edilir. Bu


örnekte oluşturulan Sem semaforunu aşağıdaki ifadeyi kullanarak elde ederiz :

WaitForSingleObject(Sem, SONSUZ);

Semaforun değeri > 0 ise, semafor sinyal durumundadır ve böylece çağıran iş


parçacığı tarafından edinilir. Aksi takdirde, semafor sinyallenmiş duruma dönene
kadar - INFINITE'i belirttiğimiz gibi - çağıran iş parçacığı süresiz olarak bloklar .

Windows semaforları için sinyal() işleminin eşdeğeri şudur:


ReleaseSemaphore() işlevi. Bu fonksiyona üç parametre iletilir:

1. Semaforun KOLU 2. Semaforun


değeri ne kadar artırılır 3. Semaforun önceki değerine
bir işaretçi

Sem'i 1 artırmak için aşağıdaki ifadeyi kullanabiliriz :

ReleaseSemaphore(Sem, 1, NULL);

Hem ReleaseSemaphore() hem de ReleaseMutex() başarılıysa sıfırdan farklı bir


değer, aksi takdirde 0 döndürür.
Machine Translated by Google

8 BÖLÜM

kilitlenmeler

Çoklu programlama ortamında, birkaç iş parçacığı sınırlı sayıda kaynak için


rekabet edebilir. Bir iş parçacığı kaynakları ister; kaynaklar o anda mevcut
değilse, iş parçacığı bekleme durumuna girer. Bazen, bekleyen bir iş parçacığı,
talep ettiği kaynaklar diğer bekleyen iş parçacıkları tarafından tutulduğundan,
durumu bir daha asla değiştiremez. Bu duruma kilitlenme denir . Bu konuyu
Bölüm 6'da canlılık başarısızlığının bir biçimi olarak kısaca tartıştık. Orada,
kilitlenmeyi, bir süreç kümesindeki her işlemin, yalnızca kümedeki başka bir
işlemin neden olabileceği bir olayı beklediği bir durum olarak tanımladık .
Belki de bir çıkmazın en iyi örneği, 20. yüzyılın başlarında Kansas yasama
organı tarafından kabul edilen bir yasadan alınabilir. Kısmen şunları söyledi: "Bir
geçişte iki tren birbirine yaklaştığında, ikisi de tam olarak duracak ve diğeri
gidene kadar hiçbiri yeniden çalışmayacaktır."
Bu bölümde, uygulama geliştiricilerin yanı sıra işletim sistemi programcılarının
kilitlenmeleri önlemek veya bunlarla başa çıkmak için kullanabileceği yöntemleri
açıklıyoruz. Bazı uygulamalar kilitlenebilecek programları tanımlayabilse de,
işletim sistemleri tipik olarak kilitlenme önleme olanakları sağlamaz ve kilitlenme
içermeyen programlar tasarlamalarını sağlamak programcıların
sorumluluğundadır. Çok çekirdekli sistemlerde artan eşzamanlılık ve paralellik
için talep devam ettikçe, kilitlenme sorunları ve diğer canlılık hataları daha zorlu
hale geliyor.

BÖLÜM HEDEFLERİ

• Mutex kilitleri kullanıldığında kilitlenmenin nasıl oluşabileceğini gösterin.

• Kilitlenmeyi karakterize eden dört gerekli koşulu tanımlayın. • Bir kaynak tahsisi

grafiğinde bir kilitlenme durumu tanımlayın. • Kilitlenmeleri önlemek için dört farklı

yaklaşımı değerlendirin. • Kilitlenmeden kaçınmak için bankacının algoritmasını

uygulayın. • Kilitlenme algılama algoritmasını uygulayın. • Kilitlenmeden kurtarma

yaklaşımlarını değerlendirin.

317
Machine Translated by Google

318 Bölüm 8 Kilitlenmeler

8.1 Sistem Modeli


Bir sistem, bir dizi rekabet eden iş parçacığı arasında dağıtılacak sınırlı sayıda kaynaktan
oluşur. Kaynaklar, her biri belirli sayıda özdeş örnekten oluşan çeşitli türlere (veya
sınıflara) bölünebilir. CPU döngüleri, dosyalar ve G/Ç aygıtları (ağ arabirimleri ve DVD
sürücüleri gibi) kaynak türlerine örnektir. Bir sistemin dört CPU'su varsa, kaynak türü
CPU'nun dört örneği vardır. Benzer şekilde, kaynak türü ağının iki örneği olabilir. Bir
iş parçacığı bir kaynak türünün örneğini isterse, türün herhangi bir örneğinin tahsisi
isteği karşılamalıdır. Olmazsa, örnekler aynı değildir ve kaynak türü sınıfları düzgün
tanımlanmamıştır.

Mutex kilitleri ve semaforlar gibi Bölüm 6'da tartışılan çeşitli senkronizasyon araçları
da sistem kaynaklarıdır; ve çağdaş bilgisayar sistemlerinde en yaygın kilitlenme
kaynaklarıdır. Ancak, tanımlama burada bir sorun değildir. Bir kilit tipik olarak belirli bir
veri yapısıyla ilişkilendirilir; yani, bir kilit bir kuyruğa erişimi korumak için, diğeri
bağlantılı bir listeye erişimi korumak için kullanılabilir ve benzerleri. Bu nedenle, bir
kilidin her örneğine tipik olarak kendi kaynak sınıfı atanır.

Bu bölüm boyunca çekirdek kaynaklarını tartıştığımızı, ancak iş parçacıklarının


diğer işlemlerden (örneğin, işlemler arası iletişim yoluyla) kaynakları kullanabileceğini
ve bu kaynak kullanımlarının da kilitlenmeye yol açabileceğini unutmayın. Bu tür
kilitlenmeler, çekirdeğin sorunu değildir ve bu nedenle burada açıklanmamıştır.
Bir iş parçacığı, kullanmadan önce bir kaynak talep etmeli ve onu kullandıktan sonra
kaynağı serbest bırakmalıdır. Bir iş parçacığı, belirlenmiş görevini yerine getirmek için
ihtiyaç duyduğu kadar kaynak talep edebilir. Açıktır ki, talep edilen kaynak sayısı,
sistemde mevcut olan toplam kaynak sayısını aşamaz. Başka bir deyişle, sistemde yalnızca
varsa, bir iş parçacığı iki ağ arabirimi talep edemez.
bir.

Normal çalışma modunda, bir iş parçacığı bir kaynağı yalnızca aşağıdaki sırayla
kullanabilir:

1. İstek. İş parçacığı kaynağı ister. İstek hemen verilemiyorsa (örneğin, bir


muteks kilidi şu anda başka bir iş parçacığı tarafından tutuluyorsa), istekte bulunan
iş parçacığı, kaynağı elde edene kadar beklemelidir.

2. Kullanın. İş parçacığı kaynak üzerinde çalışabilir (örneğin, kaynak bir muteks


kilidiyse, iş parçacığı kritik bölümüne erişebilir).
3. Serbest bırakın. İş parçacığı kaynağı serbest bırakır.

Kaynakların isteği ve serbest bırakılması, Bölüm 2'de açıklandığı gibi sistem


çağrıları olabilir. Örnekler, bir aygıtın request() ve release() , bir dosyanın open() ve close()
ve allocate() ve free()' dir. bellek sistemi çağrıları.
Benzer şekilde, Bölüm 6'da gördüğümüz gibi, istek ve serbest bırakma, semaforlar
üzerindeki wait() ve sinyal() işlemleri ve bir muteks kilidinin elde() ve bırakma() yoluyla
gerçekleştirilebilir. Bir iş parçacığı tarafından çekirdek tarafından yönetilen bir kaynağın
her kullanımı için, işletim sistemi, iş parçacığının kaynak isteyip istemediğini ve tahsis
edildiğinden emin olmak için kontrol eder. Bir sistem tablosu, her kaynağın ücretsiz mi
yoksa tahsisli mi olduğunu kaydeder. Tahsis edilen her kaynak için,
Machine Translated by Google

8.2 Çok Yönlü Uygulamalarda Kilitlenme 319

tablo ayrıca tahsis edildiği iş parçacığını da kaydeder. Bir iş parçacığı, şu anda başka bir iş
parçacığına tahsis edilmiş bir kaynak isterse, bu kaynağı bekleyen bir iş parçacığı
kuyruğuna eklenebilir.
Bir dizi iş parçacığı, kümedeki her iş parçacığı, yalnızca kümedeki başka bir iş
parçacığının neden olabileceği bir olayı beklerken kilitlenmiş durumda. Burada esas olarak
ilgilendiğimiz olaylar, kaynak edinimi ve serbest bırakılmasıdır.
Kaynaklar tipik olarak mantıksaldır (örneğin, muteks kilitleri, semaforlar ve dosyalar); ancak,
Bölüm 3'te tartışılan bir ağ arabiriminden veya IPC (işlemler arası iletişim) olanaklarından
okuma da dahil olmak üzere diğer olay türleri kilitlenmelere neden olabilir .

Bir çıkmaz durumu göstermek için, Bölüm 7.1.3'teki yemek-filozofları sorununa geri
dönüyoruz. Bu durumda, kaynaklar yemek çubukları ile temsil edilir. Bütün filozoflar aynı
anda acıkırsa ve her filozof solundaki yemek çubuğunu tutarsa, artık kullanılabilir yemek
çubuğu yoktur. Daha sonra her filozof, sağ çubuğunun kullanılabilir olmasını beklerken
engellenir.

Çok iş parçacıklı uygulamaların geliştiricileri, kilitlenme olasılığının farkında olmalıdır.


Bölüm 6'da sunulan kilitleme araçları, yarış koşullarından kaçınmak için tasarlanmıştır.
Ancak, bu araçları kullanırken geliştiriciler, kilitlerin nasıl elde edildiğine ve serbest
bırakıldığına çok dikkat etmelidir. Aksi takdirde, aşağıda açıklandığı gibi kilitlenme
meydana gelebilir.

8.2 Çok Yönlü Uygulamalarda Kilitlenme

Kilitlenme sorunlarının nasıl tanımlanıp yönetilebileceğini incelemeden önce, ilk olarak


POSIX muteks kilitlerini kullanan çok iş parçacıklı bir Pthread programında kilitlenmenin
nasıl oluşabileceğini gösteriyoruz. pthread mutex init() işlevi , kilidi açılmış bir muteks
başlatır. Mutex kilitleri, sırasıyla pthread mutex lock() ve pthread mutex unlock() kullanılarak
elde edilir ve serbest bırakılır . Bir iş parçacığı kilitli bir muteks elde etmeye çalışırsa, pthread
mutex lock() çağrısı, muteks kilidinin sahibi pthread mutex unlock()' ı çağırana kadar iş
parçacığını bloke eder .

Aşağıdaki kod örneğinde iki muteks kilidi oluşturulur ve başlatılır:

pthread muteks t birinci muteks;


pthread muteks t ikinci muteks;

pthread mutex init(&first mutex,NULL); pthread


mutex init(&ikinci mutex,NULL);

Ardından, birinci iş parçacığı ve ikinci iş parçacığı olmak üzere iki iş parçacığı oluşturulur
ve bu iş parçacıklarının her ikisinin de her iki muteks kilidine erişimi vardır. bir iplik ve iki iplik
Şekil 8.1'de gösterildiği gibi sırasıyla do work one() ve do work work () fonksiyonlarında
çalıştırın .
Bu örnekte, iplik bir muteks kilitlerini (1) birinci muteks, (2) ikinci muteks sırasına göre
elde etmeye çalışır . Aynı zamanda, (1) ikinci muteks, (2) birinci muteks sırasına göre muteks
kilitlerini elde etmek için iki girişimde bulunun. Bir iş parçacığı birinci muteks alırken, ikinci
iş parçacığı ikinci muteks alırsa kilitlenme mümkündür .
320
Bölüm 8 Kilitlenmeler
Machine Translated by Google

/* thread one bu fonksiyonda çalışır */ void *do work


one(void *param) {

pthread muteks kilidi(&ilk muteks); pthread


muteks kilidi(&ikinci muteks); /**

* Biraz iş yapın */
pthread mutex
unlock(&second mutex); pthread mutex kilidini(&ilk
mutex);

pthread çıkış (0);


}

/* bu fonksiyonda thread iki çalışır */ void *do work


two(void *param) {

pthread muteks kilidi(&ikinci muteks); pthread


muteks kilidi(&ilk muteks); /**

* Biraz iş yap */

pthread mutex kilidini(&ilk mutex); pthread


muteks kilidini aç(&ikinci muteks);

pthread çıkış (0);


}

Şekil 8.1 Kilitlenme örneği.

Kilitlenmenin mümkün olmasına rağmen, birinci iş parçacığı, birinci muteks


ve ikinci muteks için muteks kilitlerini elde edip serbest bırakabilirse, iş parçacığı
iki kilitleri elde etmeye çalışmadan önce bunun gerçekleşmeyeceğini unutmayın.
Ve elbette, iş parçacıklarının çalışma sırası, CPU zamanlayıcısı tarafından nasıl
planlandığına bağlıdır . Bu örnek, kilitlenmelerin ele alınmasıyla ilgili bir sorunu
göstermektedir: Yalnızca belirli zamanlama koşullarında meydana gelebilecek
kilitlenmeleri belirlemek ve test etmek zordur.

8.2.1 Canlı kilit


Livelock , canlılık başarısızlığının başka bir şeklidir. Kilitlenmeye benzer; her ikisi de
iki veya daha fazla iş parçacığının ilerlemesini engeller, ancak iş parçacıkları farklı
nedenlerle ilerleyemez. Kilitlenme, yalnızca kümedeki başka bir iş parçacığının
neden olabileceği bir olayı beklerken bir kümedeki her iş parçacığı engellendiğinde
meydana gelirken, bir iş parçacığı sürekli olarak başarısız olan bir eylemi
denediğinde canlı kilit oluşur. Livelock, bazen iki kişi bir koridordan geçmeye
çalıştığında meydana gelene benzer: Biri onun sağına, diğeri soluna doğru
hareket eder, yine de birbirlerinin ilerlemesini engeller. Sonra soluna hareket eder ve o ha
Machine Translated by Google

8.3 Kilitlenme Karakterizasyonu 321

onun sağında, vb. Engellenmiyorlar, ancak herhangi bir ilerleme kaydedemiyorlar.

Canlı kilit, bloke etmeden bir muteks kilidi elde etmeye çalışan Pthreads pthread mutex
trylock() işleviyle gösterilebilir. Şekil 8.2'deki kod örneği, Şekil 8.1'deki örneği şimdi pthread
mutex trylock() kullanacak şekilde yeniden yazar. Bu durum, birinci iş parçacığı ilk muteks,
ardından ikinci iş parçacığı ikinci muteks ediniyorsa , canlı kilitlenmeye yol açabilir .

Her iş parçacığı daha sonra başarısız olan, ilgili kilitlerini serbest bırakan ve aynı eylemleri süresiz
olarak tekrarlayan pthread mutex trylock()'u çağırır.
Livelock, tipik olarak, iş parçacıkları aynı anda başarısız işlemleri yeniden denediğinde ortaya
çıkar. Bu nedenle, her bir iş parçacığının başarısız işlemi rastgele zamanlarda yeniden denemesini
sağlayarak genellikle önlenebilir. Bu, bir ağ çakışması meydana geldiğinde Ethernet ağları
tarafından alınan yaklaşımdır. Bir çarpışma meydana geldikten hemen sonra bir paketi yeniden
iletmeye çalışmak yerine, bir çarpışmaya karışan bir ana bilgisayar, tekrar iletmeyi denemeden
önce rastgele bir süre geri çekilecektir.
Canlı kilitlenme, kilitlenmeden daha az yaygındır, ancak yine de eşzamanlı uygulamaların
tasarlanmasında zorlu bir konudur ve kilitlenme gibi, yalnızca belirli zamanlama koşullarında ortaya
çıkabilir.

8.3 Kilitlenme Karakterizasyonu

Önceki bölümde, muteks kilitleri kullanan çok iş parçacıklı programlamada kilitlenmenin nasıl
oluşabileceğini gösterdik. Şimdi kilitlenmeyi karakterize eden koşullara daha yakından bakıyoruz.

8.3.1 Gerekli Koşullar

Aşağıdaki dört koşul bir sistemde aynı anda geçerliyse bir kilitlenme durumu ortaya çıkabilir:

1. Karşılıklı dışlama. En az bir kaynak paylaşılamaz modda tutulmalıdır; yani, bir seferde yalnızca
bir iş parçacığı kaynağı kullanabilir. Başka bir iş parçacığı bu kaynağı talep ederse, istekte
bulunan iş parçacığı, kaynak serbest bırakılıncaya kadar ertelenmelidir.

2. Bekleyin ve bekleyin. Bir iş parçacığının en az bir kaynağı tutması ve şu anda diğer iş


parçacıkları tarafından tutulan ek kaynakları almayı beklemesi gerekir.

3. Önlem yok. Kaynaklar engellenemez; yani, bir kaynak yalnızca onu tutan iş parçacığı
tarafından, o iş parçacığı görevini tamamladıktan sonra gönüllü olarak serbest bırakılabilir.

4. Dairesel bekleme. Bir dizi {T0, T1, ..., Tn} bekleyen iş parçacığı mevcut olmalıdır, öyle ki T0 ,
T1 tarafından tutulan bir kaynağı bekliyor , T1 , T2 tarafından tutulan bir kaynağı
bekliyor , ..., Tn 1 bekliyor Tn tarafından tutulan bir kaynak ve Tn , T0 tarafından tutulan bir
kaynağı bekliyor .

Bir kilitlenmenin oluşması için dört koşulun hepsinin geçerli olması gerektiğini vurguluyoruz.
Dairesel bekleme koşulu, bekle ve bekle koşulunu ifade eder, bu nedenle dört
322 Bölüm 8 Kilitlenmeler
Machine Translated by Google

/* thread one bu fonksiyonda çalışır */ void *do work


one(void *param) {

int yapıldı = 0;

while (!done) { pthread


mutex lock(&first mutex); if (pthread mutex
trylock(&ikinci mutex)) {
/**
* Biraz iş yap */

pthread muteks kilidini aç(&ikinci muteks); pthread


mutex kilidini(&ilk mutex); yapıldı = 1;

} else
pthread mutex unlock(&first mutex);
}

pthread çıkış (0);


}
/* bu fonksiyonda thread iki çalışır */ void *do work
two(void *param) {

int yapıldı = 0;

while (!done) { pthread


muteks kilidi(&ikinci muteks); if (pthread mutex
trylock(&first mutex)) {
/**
* Biraz iş yap */

pthread mutex kilidini(&ilk mutex); pthread muteks


kilidini aç(&ikinci muteks); yapıldı = 1;

} else
pthread mutex unlock(&ikinci mutex);
}

pthread çıkış (0);


}

Şekil 8.2 Canlı kilit örneği.


Machine Translated by Google

8.3 Kilitlenme Karakterizasyonu 323

.
first_mutex
.
ikinci_mutex

thread_one thread_two

Şekil 8.3 Şekil 8.1'deki program için kaynak tahsisi grafiği.

koşullar tamamen bağımsız değildir. Bununla birlikte, her koşulu ayrı ayrı ele
almanın yararlı olduğunu Bölüm 8.5'te göreceğiz.

8.3.2 Kaynak Tahsis Grafiği

Kilitlenmeler, sistem kaynak tahsisi grafiği adı verilen yönlendirilmiş bir grafik
açısından daha kesin olarak tanımlanabilir . Bu grafik, bir V köşe kümesinden ve bir E
kenar kümesinden oluşur. V köşe kümesi, iki farklı düğüm tipine bölünür: T = {T1,
T2, ..., Tn}, tüm düğümlerden oluşan küme. sistemdeki aktif iş parçacıkları ve R = {R1,
R2, ..., Rm}, sistemdeki tüm kaynak türlerinden oluşan küme.

Ti parçacığından Rj kaynak türüne yönlendirilmiş bir kenar Ti Rj ile gösterilir ;


Ti iş parçacığının Rj kaynak türünün bir örneğini talep ettiğini ve şu anda bu
kaynağı beklediğini belirtir. Rj kaynak türünden Ti ipliğine yönlendirilmiş bir kenar ,
Rj Ti ile gösterilir ; Ti iş parçacığına Rj kaynak türünün bir örneğinin tahsis
edildiğini belirtir . Yönlendirilmiş kenar Ti Rj , istek kenarı
olarak adlandırılır ; yönlendirilmiş kenar Rj Ti'ye atama kenarı denir .
Resimli olarak, her Ti ipliğini bir daire olarak ve her kaynak tipini Rj bir dikdörtgen
olarak temsil ediyoruz. Basit bir örnek olarak, Şekil 8.3'te gösterilen kaynak tahsisi
grafiği, Şekil 8.1'deki programdaki kilitlenme durumunu göstermektedir.
Kaynak türü Rj'nin birden fazla örneği olabileceğinden, bu tür her bir örneği
dikdörtgen içinde bir nokta olarak temsil ederiz. Bir istek kenarının yalnızca Rj
dikdörtgenini gösterdiğine
belirlemesi
, atama kenarının
gerektiğine
da dikdörtgendeki
dikkat edin. noktalardan birini

Ti iş parçacığı Rj kaynak türünün bir örneğini istediğinde , kaynak tahsisi


grafiğine bir istek kenarı eklenir. Bu istek karşılanabildiğinde, istek kenarı anında bir
atama kenarına dönüştürülür. İş parçacığının artık kaynağa erişmesi
gerekmediğinde, kaynağı serbest bırakır. Sonuç olarak, atama kenarı silinir.

Şekil 8.4'te gösterilen kaynak tahsisi grafiği aşağıdakileri gösterir:


durum.

• T, R ve E kümeleri :

T = {T1, T2, T3}


R = {R1, R2, R3, R4}
Machine Translated by Google

324 Bölüm 8 Kilitlenmeler

R1 R3

T1 T2 T3

R2

R4

Şekil 8.4 Kaynak tahsisi grafiği.

E = {T1 R1, T2 R3, R1 T2, R2 T2, R2 T1, R3 T3}


• Kaynak örnekleri:

Bir R1 kaynak türü örneği İki


R2 kaynak türü örneği Bir kaynak
türü R3 örneği Üç R4 kaynak türü
örneği
• Konu durumları:

İş parçacığı T1 , R2 kaynak türü örneğini tutuyor ve R1 kaynak türü


örneğini bekliyor .
İş parçacığı T2 , bir R1 örneğini ve bir R2 örneğini tutuyor ve
R3 örneğini bekliyorum .
İş parçacığı T3 , R3 örneğini tutuyor .

Bir kaynak tahsisi grafiğinin tanımı verildiğinde, grafik döngü içermiyorsa,


sistemdeki hiçbir iş parçacığının kilitlenmediği gösterilebilir. Grafik bir döngü
içeriyorsa, bir kilitlenme mevcut olabilir.
Her kaynak türünün tam olarak bir örneği varsa, bir döngü bir kilitlenmenin
oluştuğunu gösterir. Döngü yalnızca, her biri yalnızca tek bir örneğe sahip olan bir
dizi kaynak türünü içeriyorsa, bir kilitlenme meydana gelmiştir. Döngüye dahil olan
her iş parçacığı kilitlenir. Bu durumda, grafikteki bir döngü, kilitlenmenin varlığı
için hem gerekli hem de yeterli bir koşuldur.
Her kaynak türünün birkaç örneği varsa, bir döngü mutlaka bir kilitlenmenin
meydana geldiği anlamına gelmez. Bu durumda, grafikteki bir döngü, kilitlenmenin
varlığı için gerekli ancak yeterli bir koşul değildir.
Bu kavramı göstermek için Şekil 8.4'te gösterilen kaynak tahsisi grafiğine
dönüyoruz. T3 iş parçacığının R2 kaynak türünün bir örneğini istediğini
varsayalım . Şu anda kullanılabilir kaynak örneği olmadığından, bir istek ekliyoruz
Machine Translated by Google

8.3 Kilitlenme Karakterizasyonu 325

R1 R3

T1 T2 T3

R2

R4

Şekil 8.5 Kilitlenme içeren kaynak tahsisi grafiği.

kenar T3 R2 grafiğe (Şekil 8.5). Bu noktada sistemde iki minimum döngü vardır:

T1 R1 T2 R3 T3 R2 T1
T2 R3 T3 R2 T2

T1, T2 ve T3 iş parçacıkları kilitlendi. T2 iş parçacığı , T3 iş parçacığı tarafından tutulan R3


kaynağını bekliyor . T3 iş parçacığı , T1 iş parçacığının veya T2 iş parçacığının R2
kaynağını serbest bırakmasını bekliyor . Ayrıca, T1 iş parçacığı, T2 iş parçacığının R1
kaynağını serbest bırakmasını bekliyor .
Şimdi Şekil 8.6'daki kaynak tahsisi grafiğini düşünün. Bu örnekte ayrıca bir döngümüz
var:

T1 R1 T3 R2 T1

T2
R1

T3

T1

R2

T4

Şekil 8.6 Bir döngüye sahip ancak kilitlenme olmayan kaynak tahsisi grafiği.
Machine Translated by Google

326 Bölüm 8 Kilitlenmeler

Ancak, herhangi bir kilitlenme yok. T4 iş parçacığının R2 kaynak türü örneğini


yayınlayabileceğini gözlemleyin . Bu kaynak daha sonra döngüyü kırarak T3'e tahsis
edilebilir .
Özetle, bir kaynak tahsisi grafiğinin bir döngüsü yoksa, sistem kilitlenme
durumunda değildir . Bir döngü varsa, sistem kilitlenme durumunda olabilir veya
olmayabilir . Bu gözlem, kilitlenme sorunuyla ilgilenirken önemlidir.

8.4 Kilitlenmeleri İşleme Yöntemleri

Genel olarak konuşursak, kilitlenme sorununu üç yoldan biriyle çözebiliriz:

• Sorunu tamamen yok sayabiliriz ve sistemde kilitlenmeler hiç oluşmamış gibi


davranabiliriz.
• Kilitlenmeleri önlemek veya önlemek için bir protokol kullanabiliriz;
sistem asla kilitlenme durumuna girmez.
• Sistemin bir kilitlenme durumuna girmesine, onu algılamasına ve kurtarmasına izin verebiliriz.

İlk çözüm, Linux ve Windows dahil olmak üzere çoğu işletim sistemi tarafından
kullanılan çözümdür. Daha sonra, genellikle ikinci çözümde özetlenen yaklaşımları
kullanarak kilitlenmeleri işleyen programlar yazmak çekirdek ve uygulama
geliştiricilerine kalmıştır. Veritabanları gibi bazı sistemler üçüncü çözümü benimser,
kilitlenmelerin oluşmasına izin verir ve ardından kurtarmayı yönetir.
Ardından, kilitlenmeleri ele almak için üç yöntemi kısaca detaylandıracağız.
Ardından, Bölüm 8.5 ila Bölüm 8.8'de ayrıntılı algoritmalar sunuyoruz. Devam
etmeden önce, bazı araştırmacıların, işletim sistemlerindeki tüm kaynak tahsisi
sorunları yelpazesi için temel yaklaşımlardan hiçbirinin tek başına uygun olmadığını
savunduklarını belirtmeliyiz. Bununla birlikte, temel yaklaşımlar birleştirilebilir, bu da
bir sistemdeki her kaynak sınıfı için en uygun yaklaşımı seçmemize izin verir.

Kilitlenmelerin asla oluşmamasını sağlamak için, sistem bir kilitlenme önleme


veya bir kilitlenme önleme şeması kullanabilir. Kilitlenme önleme , gerekli koşullardan
en az birinin (Kısım 8.3.1) sağlanmamasını sağlamak için bir dizi yöntem sağlar.
Bu yöntemler, kaynak isteklerinin nasıl yapılabileceğini sınırlayarak kilitlenmeleri
önler. Bu yöntemleri Bölüm 8.5'te tartışıyoruz.
Kilitlenmeden kaçınma , işletim sistemine, bir iş parçacığının ömrü boyunca
hangi kaynakları talep edeceği ve kullanacağı konusunda önceden ek bilgi
verilmesini gerektirir. Bu ek bilgiyle, işletim sistemi her istek için iş parçacığının
bekleyip beklemeyeceğine karar verebilir. Mevcut talebin karşılanıp
karşılanmayacağına veya ertelenmesi gerektiğine karar vermek için, sistem mevcut
kaynakları, her bir iş parçacığına tahsis edilen kaynakları ve her iş parçacığının
gelecekteki isteklerini ve yayınlarını dikkate almalıdır.
Bu şemaları Bölüm 8.6'da tartışıyoruz.
Bir sistem bir kilitlenme önleme veya bir kilitlenme önleme algoritması
kullanmıyorsa, bir kilitlenme durumu ortaya çıkabilir. Bu ortamda sistem, bir
kilitlenmenin oluşup oluşmadığını belirlemek için sistemin durumunu inceleyen bir
algoritma ve bundan kurtulmak için bir algoritma sağlayabilir.
Machine Translated by Google

8.5 Kilitlenme Önleme 327

kilitlenme (eğer gerçekten bir kilitlenme oluşmuşsa). Bu konuları Bölüm 8.7 ve Bölüm
8.8'de tartışıyoruz.
Kilitlenmeleri tespit edecek ve bu kilitlenmelerden kurtulacak algoritmaların
yokluğunda, sistemin kilitlenme durumunda olduğu ancak ne olduğunu tanımanın
hiçbir yolu olmadığı bir duruma varabiliriz. Bu durumda, tespit edilmeyen kilitlenme,
sistemin performansının bozulmasına neden olacaktır, çünkü kaynaklar çalışamayan iş
parçacıkları tarafından tutulmaktadır ve giderek daha fazla iş parçacığı, kaynaklar için
istekte bulundukça, kilitlenme durumuna girecektir. Sonunda sistem çalışmayı durduracak
ve manuel olarak yeniden başlatılması gerekecek.
Bu yöntem, kilitlenme sorununa uygulanabilir bir yaklaşım gibi görünmese de, daha
önce belirtildiği gibi çoğu işletim sisteminde kullanılmaktadır. Harcama önemli bir
husustur. Kilitlenme olasılığını göz ardı etmek diğer yaklaşımlardan daha ucuzdur.
Birçok sistemde kilitlenmeler nadiren (örneğin ayda bir) meydana geldiğinden, diğer
yöntemlerin ekstra masrafı buna değmeyebilir.

Ek olarak, canlı kilitlenme gibi diğer canlılık koşullarından kurtulmak için kullanılan
yöntemler, kilitlenmeden kurtulmak için kullanılabilir. Bazı durumlarda, bir sistem bir
canlılık hatasından muzdariptir ancak kilitlenme durumunda değildir.
Bu durumu, örneğin, en yüksek öncelikte çalışan gerçek zamanlı bir iş parçacığında
(veya önleyici olmayan bir zamanlayıcıda çalışan herhangi bir iş parçacığında) ve kontrolü
hiçbir zaman işletim sistemine geri döndürmediğinde görüyoruz. Sistem, bu tür koşullar
için manuel kurtarma yöntemlerine sahip olmalıdır ve bu teknikleri yalnızca kilitlenme
kurtarma için kullanabilir.

8.5 Kilitlenme Önleme

Bölüm 8.3.1'de belirttiğimiz gibi, bir kilitlenmenin oluşması için dört gerekli koşulun her
birinin geçerli olması gerekir. Bu koşullardan en az birinin gerçekleşmemesini sağlayarak
bir kilitlenme oluşmasını engelleyebiliriz . Bu yaklaşımı, gerekli dört koşulun her birini ayrı
ayrı inceleyerek detaylandırıyoruz.

8.5.1 Karşılıklı Dışlama

Karşılıklı dışlama koşulu geçerli olmalıdır. Yani, en az bir kaynak paylaşılamaz olmalıdır.
Paylaşılabilir kaynaklar, birbirini dışlayan erişim gerektirmez ve bu nedenle bir kilitlenmeye
dahil olamaz. Salt okunur dosyalar, paylaşılabilir bir kaynağa iyi bir örnektir. Birkaç iş
parçacığı aynı anda salt okunur bir dosyayı açmaya çalışırsa, dosyaya aynı anda erişim
izni verilebilir. Bir iş parçacığının asla paylaşılabilir bir kaynak beklemesi gerekmez. Ancak
genel olarak, bazı kaynaklar doğası gereği paylaşılamaz olduğundan, karşılıklı dışlama
koşulunu reddederek kilitlenmeleri önleyemeyiz. Örneğin, bir muteks kilidi aynı anda
birkaç iş parçacığı tarafından paylaşılamaz.

8.5.2 Tut ve Bekle

Tut ve bekle koşulunun sistemde hiçbir zaman oluşmamasını sağlamak için, bir iş
parçacığı bir kaynak istediğinde, başka hiçbir kaynağı tutmadığını garanti etmeliyiz.
Kullanabileceğimiz bir protokol, her iş parçacığının yürütmeye başlamadan önce tüm
kaynaklarını istemesini ve tahsis edilmesini gerektirir. Bu, elbette,
328 Bölüm 8 Kilitlenmeler
Machine Translated by Google

talebin dinamik yapısı nedeniyle çoğu uygulama için pratik değildir


kaynaklar.

Alternatif bir protokol, bir iş parçacığının yalnızca kaynakları olmadığında kaynak


istemesine izin verir. Bir iş parçacığı bazı kaynaklar isteyebilir ve bunları kullanabilir.
Herhangi bir ek kaynak talep etmeden önce, tahsis edilmiş olan tüm kaynakları serbest
bırakmalıdır.
Bu protokollerin her ikisinin de iki ana dezavantajı vardır. Birincisi, kaynaklar tahsis
edilebildiği halde uzun bir süre kullanılmadığından kaynak kullanımı düşük olabilir.
Örneğin, bir iş parçacığına tüm yürütmesi için bir muteks kilidi atanabilir, ancak bunu
yalnızca kısa bir süre için gerektirebilir. İkincisi, açlık mümkündür. Birkaç popüler
kaynağa ihtiyaç duyan bir iş parçacığının süresiz olarak beklemesi gerekebilir, çünkü
ihtiyaç duyduğu kaynaklardan en az biri her zaman başka bir iş parçacığına tahsis edilir.

8.5.3 Ön Alım Yok


Kilitlenmeler için gerekli üçüncü koşul, halihazırda tahsis edilmiş olan kaynakların
herhangi bir önalımının olmamasıdır. Bu koşulun sağlanmadığından emin olmak için
aşağıdaki protokolü kullanabiliriz. Bir iş parçacığı bazı kaynakları tutuyorsa ve
kendisine hemen tahsis edilemeyen başka bir kaynak isterse (yani iş parçacığının
beklemesi gerekir), o zaman iş parçacığının şu anda tuttuğu tüm kaynaklar önceliklidir.
Başka bir deyişle, bu kaynaklar dolaylı olarak serbest bırakılır.
Öncelikli kaynaklar, iş parçacığının beklediği kaynaklar listesine eklenir. İplik, yalnızca
eski kaynaklarını ve talep ettiği yeni kaynakları yeniden kazanabildiğinde yeniden
başlatılacaktır.
Alternatif olarak, bir iş parçacığı bazı kaynaklar isterse, önce bunların kullanılabilir
olup olmadığını kontrol ederiz. Varsa, tahsis ederiz. Değillerse, ek kaynak bekleyen
başka bir iş parçacığına tahsis edilip edilmediğini kontrol ederiz. Eğer öyleyse,
istenen kaynakları bekleyen iş parçacığından önceden alır ve bunları talep eden iş
parçacığına tahsis ederiz. Kaynaklar mevcut değilse veya bekleyen bir iş parçacığı
tarafından tutulmuyorsa, istekte bulunan iş parçacığının beklemesi gerekir. Beklerken,
kaynaklarının bir kısmı önceden alınabilir, ancak yalnızca başka bir iş parçacığı onları
talep ederse. Bir iş parçacığı, yalnızca talep ettiği yeni kaynaklar tahsis edildiğinde
yeniden başlatılabilir ve beklerken önceden ayrılmış tüm kaynakları kurtarır.

Bu protokol genellikle, CPU kayıtları ve veritabanı işlemleri gibi durumları kolayca


kaydedilebilen ve daha sonra geri yüklenebilen kaynaklara uygulanır . Genel olarak
muteks kilitleri ve semaforlar gibi kaynaklara, tam olarak kilitlenmenin en yaygın olarak
meydana geldiği kaynaklara uygulanamaz.

8.5.4 Dairesel Bekleme


Kilitlenme önleme için şimdiye kadar sunulan üç seçenek, çoğu durumda genellikle
pratik değildir. Ancak, kilitlenmeler için dördüncü ve son koşul olan dairesel bekleme
koşulu, gerekli koşullardan birini geçersiz kılarak pratik bir çözüm için bir fırsat sunar.
Bu koşulun hiçbir zaman geçerli olmamasını sağlamanın bir yolu, tüm kaynak
türlerinin toplam sıralamasını uygulamak ve her bir iş parçacığının artan bir sıralama
sırasına göre kaynak istemesini zorunlu kılmaktır.

Örneklemek için, R = {R1, R2, ..., Rm} kaynak türleri kümesi olsun. Her kaynak
türüne benzersiz bir tam sayı atarız, bu da
Machine Translated by Google

8.5 Kilitlenme Önleme 329

iki kaynağı karşılaştırmak ve sıralamamızda birinin diğerinden önce gelip gelmediğini


belirlemek. Biçimsel olarak, bire bir F: R N fonksiyonunu tanımlarız, burada N doğal
sayılar kümesidir. Sistemdeki tüm senkronizasyon nesneleri arasında bir sıralama
geliştirerek bu şemayı bir uygulama programında gerçekleştirebiliriz.
Örneğin, Şekil 8.1'de gösterilen Pthread programındaki kilit sıralaması şöyle olabilir:

F(ilk muteks)=1
F(ikinci muteks)=5

Artık kilitlenmeleri önlemek için aşağıdaki protokolü dikkate alabiliriz: Her iş


parçacığı kaynakları yalnızca artan bir sıralama sırasına göre talep edebilir. Yani, bir iş
parçacığı başlangıçta bir kaynağın örneğini isteyebilir; örneğin Ri. Bundan sonra, iş
parçacığı yalnızca ve ancak F(Rj ) > F(Ri ) olması durumunda Rj kaynağının bir örneğini isteyebilir .
Örneğin, yukarıda tanımlanan işlevi kullanarak, aynı anda hem birinci muteks hem de
ikinci muteks kullanmak isteyen bir iş parçacığı, önce ilk muteks ve sonra ikinci muteks
talep etmelidir. Alternatif olarak, bir Rj kaynağı örneği talep eden bir iş parçacığının ,
F(Ri ) F(Rj ) olacak şekilde herhangi bir Ri kaynağını serbest bırakmasını gerektirebiliriz .
Aynı kaynak türünün birkaç örneğine ihtiyaç duyulursa, hepsi için tek bir istek verilmesi
gerektiğini de unutmayın.
Bu iki protokol kullanılırsa, dairesel bekleme koşulu sağlanamaz. Bu gerçeği
döngüsel bir beklemenin var olduğunu varsayarak gösterebiliriz (çelişkiyle kanıt).
Döngüsel beklemede yer alan iş parçacıkları kümesi {T0, T1, ..., Tn} olsun, burada Ti ,
Ti+1 iş parçacığı tarafından tutulan bir Ri kaynağını bekliyor bir . ( Tn
Rn, kaynağını
T0 tarafından
beklemek
tutulan
için indekslerde modulo aritmetiği kullanılır .) O zaman, Ti+1 parçacığı Ri+1 kaynağı
talep ederken Ri kaynağını tuttuğundan , F(Ri ) < F olmalıdır. (Ri+1) tüm i için. Ancak bu
koşul, F(R0) < F(R1) < ... < F(Rn) < F(R0) anlamına gelir. Geçişlilik ile, F(R0) < F(R0), ki bu
imkansızdır. Bu nedenle, dairesel bir bekleme olamaz.

Bir sıralama veya hiyerarşi geliştirmenin tek başına kilitlenmeyi önlemediğini


unutmayın. Sıralamayı takip eden programlar yazmak uygulama geliştiricilerine kalmıştır.
Bununla birlikte, özellikle yüzlerce veya binlerce kilit içeren bir sistemde bir kilit siparişi
oluşturmak zor olabilir. Bu zorluğun üstesinden gelmek için, birçok Java geliştiricisi, kilit
edinimi sipariş etme işlevi olarak System.identityHashCode(Object) yöntemini (geçtiği
Object parametresinin varsayılan karma kod değerini döndürür ) kullanma stratejisini
benimsemiştir.

Ayrıca, kilitler dinamik olarak alınabiliyorsa, bir kilit siparişi vermenin önceden
kilitlenme önlemeyi garanti etmediğini belirtmek önemlidir. Örneğin, iki hesap
arasında para transferi yapan bir fonksiyonumuz olduğunu varsayalım.
Bir yarış koşulunu önlemek için, her hesabın Şekil 8.7'de gösterildiği gibi bir get lock()
işlevinden elde edilen ilişkili bir muteks kilidi vardır.
Kilitlenme, iki iş parçacığı aynı anda işlem() işlevini çağırarak farklı hesapları aktarırsa
mümkündür. Yani, bir iş parçacığı çağırabilir

işlem(çek hesabı, tasarruf hesabı, 25.0)


ve başka biri çağırabilir

işlem(tasarruf hesabı, çek hesabı, 50.0)


Machine Translated by Google

330 Bölüm 8 Kilitlenmeler

geçersiz işlem(Hesaptan, Hesaptan, çift tutar) {

muteks kilidi1, kilit2;


lock1 = get lock(from); lock2
= get lock(to);

edin(kilit1);
edin(kilit2);

çekmek(den, miktar);
depozito(to, miktar);

serbest bırakma(kilit2);
serbest bırakma(kilit1);
}

Şekil 8.7 Kilit sıralamalı kilitlenme örneği.

8.6 Kilitlenmeden Kaçınma

Kilitlenme önleme algoritmaları, Bölüm 8.5'te tartışıldığı gibi, isteklerin nasıl


yapılabileceğini sınırlayarak kilitlenmeleri önler. Limitler, kilitlenme için gerekli
koşullardan en az birinin oluşmamasını sağlar. Bununla birlikte, bu yöntemle
kilitlenmeleri önlemenin olası yan etkileri, düşük cihaz kullanımı ve düşük sistem
verimidir.
Kilitlenmelerden kaçınmanın alternatif bir yöntemi, kaynakların nasıl isteneceği
hakkında ek bilgi istemektir. Örneğin, R1 ve R2 kaynaklarına sahip bir sistemde,
sistemin her iki kaynağı serbest bırakmadan önce P parçacığının önce R1'i sonra
R2'yi isteyeceğini , oysa Q parçacığının R2 ve ardından R1'i isteyeceğini bilmesi
gerekebilir . Her iş parçacığı için isteklerin ve yayınların tam sırası hakkındaki bu
bilgiyle, sistem olası bir olası kilitlenmeyi önlemek için iş parçacığının beklemesi
gerekip gerekmediğine her istek için karar verebilir. Her istek, bu kararı verirken
sistemin mevcut kaynakları, her bir iş parçacığına tahsis edilen kaynakları ve her
bir iş parçacığının gelecekteki isteklerini ve yayınlarını dikkate almasını gerektirir.

Bu yaklaşımı kullanan çeşitli algoritmalar, gereken bilgi miktarı ve türü açısından


farklılık gösterir. En basit ve en kullanışlı model, her iş parçacığının ihtiyaç
duyabileceği her türden maksimum kaynak sayısını beyan etmesini gerektirir . Bu
a priori bilgi göz önüne alındığında, sistemin asla kilitlenme durumuna girmemesini
sağlayan bir algoritma oluşturmak mümkündür. Bir kilitlenme önleme algoritması,
döngüsel bekleme koşulunun asla var olamayacağından emin olmak için kaynak
tahsis durumunu dinamik olarak inceler. Kaynak tahsis durumu , mevcut ve tahsis
edilen kaynakların sayısı ve iş parçacıklarının maksimum talepleri ile tanımlanır.
Aşağıdaki bölümlerde, iki kilitlenmeden kaçınma algoritmasını inceleyeceğiz.
Machine Translated by Google

8.6 Kilitlenmeden Kaçınma 331

LINUX LOCKDEP ARACI

Kaynakların doğru sırada alınmasını sağlamak çekirdek ve uygulama


geliştiricilerinin sorumluluğunda olsa da, kilitlerin doğru sırayla alındığını
doğrulamak için belirli yazılımlar kullanılabilir. Olası kilitlenmeleri tespit etmek
için Linux , çekirdekteki kilitleme sırasını doğrulamak için kullanılabilecek zengin
işlevselliğe sahip bir araç olan lockdep'i sağlar. lockdep , kilit alma ve serbest
bırakma için bir dizi kurala göre kilit alma ve serbest bırakma kullanım modellerini
izlediğinden, çalışan bir çekirdekte etkinleştirilmek üzere tasarlanmıştır. İki
örnek aşağıdadır, ancak lockdep'in burada açıklanandan çok daha fazla işlevsellik
sağladığını unutmayın:

• Kilitlerin alınma sırası sistem tarafından dinamik olarak korunur. Lockdep ,


kilitlerin bozuk olduğunu algılarsa, olası bir kilitlenme durumu bildirir.

• Linux'ta, kesme işleyicilerinde döndürme kilitleri kullanılabilir. Çekirdek, bir


kesme işleyicisinde de kullanılan bir döndürme kilidi edindiğinde olası bir
kilitlenme kaynağı oluşur. Kilit tutulurken kesme meydana gelirse, kesme
işleyicisi o anda kilidi tutan çekirdek kodunu önceden alır ve ardından kilidi
almaya çalışırken dönerek kilitlenmeye neden olur. Bu durumdan kaçınmanın
genel stratejisi, bir kesme işleyicisinde de kullanılan bir döndürme kilidi
edinmeden önce mevcut işlemcideki kesintileri devre dışı bırakmaktır.
Lockdep , çekirdek kodu aynı zamanda bir kesme işleyicisinde kullanılan bir
kilidi alırken kesmelerin etkinleştirildiğini algılarsa, olası bir kilitlenme
senaryosu bildirir.

lockdep , bir sistemi önemli ölçüde yavaşlatabileceğinden, çekirdekte kod


geliştirme veya değiştirmede bir araç olarak kullanılmak ve üretim sistemlerinde
kullanılmamak üzere geliştirilmiştir. Amacı, yeni bir aygıt sürücüsü veya çekirdek
modülü gibi yazılımların olası bir kilitlenme kaynağı sağlayıp sağlamadığını test
etmektir. Lockdep'in tasarımcıları, 2006'daki geliştirilmesinden sonraki birkaç yıl
içinde, sistem raporlarındaki kilitlenmelerin sayısının büyük bir oranda azaldığını
bildirdiler.⣞ Lockdep başlangıçta yalnızca çekirdekte kullanım için tasarlanmış
olsa da, bunun son revizyonları araç artık Pthreads mutex kilitlerini kullanan
kullanıcı uygulamalarındaki kilitlenmeleri algılamak için kullanılabilir. Lockdep
aracıyla ilgili daha fazla ayrıntı https://www.kernel.org/doc/Documentation/locking/
lockdep-design.txt adresinde bulunabilir.

8.6.1 Güvenli Durum

Sistem her bir iş parçacığına (maksimum değerine kadar) kaynakları belirli bir
sırayla tahsis edebiliyorsa ve yine de bir kilitlenmeyi önleyebiliyorsa, durum
güvenlidir . Daha resmi olarak, bir sistem yalnızca güvenli bir sıra varsa güvenli
durumdadır . <T1, T2, ..., Tn> iş parçacığı dizisi , Ti'nin hala yapabileceği kaynak
tarafından
isteklerinin
karşılanabiliyorsa,
her biri için mevcut
mevcut
Ti ,tahsis
mevcutdurumu
kaynaklar
içinartı
güvenli
tutulan
bir kaynaklar
dizidir. tüm
Tj tarafından , j < i ile. Bu durumda, Ti'nin ihtiyaç duyduğu
mevcut
kaynaklar
değilse,hemen
Ti tüm
Tj'ler bitene kadar bekleyebilir . Bitirdiklerinde, Ti tüm özelliklerini elde edebilir.
Machine Translated by Google

332 Bölüm 8 Kilitlenmeler

güvensiz

kilitlenme

güvenli

Şekil 8.8 Güvenli, güvensiz ve kilitlenmemiş durum alanları.

gerekli kaynaklar, belirlenmiş görevi tamamlayın, tahsis edilen kaynakları iade edin ve sonlandırın. Ti sona
erdiğinde, Ti +1 gerekli kaynakları elde edebilir, vb. Böyle bir sıra yoksa, sistem durumunun güvensiz
olduğu söylenir.
Güvenli durum, kilitlenmiş bir durum değildir. Tersine, kilitlenme durumu güvenli olmayan bir
durumdur. Ancak, tüm güvensiz durumlar kilitlenme değildir (Şekil 8.8).
Güvenli olmayan bir durum kilitlenmeye neden olabilir . Durum güvenli olduğu sürece, işletim sistemi
güvenli olmayan (ve kilitlenmemiş) durumlardan kaçınabilir. Güvenli olmayan bir durumda, işletim sistemi,
iş parçacıklarının bir kilitlenme meydana gelecek şekilde kaynak istemesini engelleyemez. İş parçacıklarının
davranışı güvenli olmayan durumları kontrol eder.
Örneklemek için, on iki kaynağı ve üç iş parçacığı olan bir sistemi düşünün: T0, T1 ve T2. T0 iş
parçacığı on kaynak gerektirir, T1 iş parçacığı dörde ihtiyaç duyabilir ve T2 iş parçacığı en fazla dokuz
kaynağa ihtiyaç duyabilir. t0 zamanında , T0 iş parçacığının beş kaynak tuttuğunu, T1 iş parçacığının iki
kaynak tuttuğunu ve T2 iş parçacığının iki kaynak tuttuğunu varsayalım . (Dolayısıyla, üç ücretsiz kaynak
vardır.)

Maksimum İhtiyaç Mevcut İhtiyaçlar

10 5
T0
4 2
T1
9 2
T2

t0 anında sistem güvenli durumdadır. <T1, T0, T2> dizisi güvenlik koşulunu karşılamaktadır. T1 iş
parçacığı , tüm kaynaklarını hemen tahsis edebilir ve daha sonra bunları iade edebilir (sistem daha sonra
beş kullanılabilir kaynağa sahip olacaktır); daha sonra T0 iş parçacığı tüm kaynaklarını alabilir ve geri
gönderebilir (bu durumda sistem on kullanılabilir kaynağa sahip olacaktır); ve son olarak, iş parçacığı T2
tüm kaynaklarını alabilir ve geri gönderebilir (bu durumda sistem on iki kaynağın tümüne sahip olacaktır).

Bir sistem güvenli durumdan güvenli olmayan bir duruma geçebilir. Diyelim ki, t1 zamanında , T2 iş
parçacığı istekte bulundu ve bir kaynak daha tahsis edildi. Sistem artık güvenli durumda değil. Bu noktada,
tüm kaynakları yalnızca T1 iş parçacığına tahsis edilebilir.
Onları döndürdüğünde, sistem yalnızca dört kullanılabilir kaynağa sahip olacaktır.
T0 iş parçacığına beş kaynak tahsis edildiğinden ancak en fazla on kaynak bulunduğundan, beş kaynak
daha talep edebilir. Bunu yaparsa, beklemesi gerekecek çünkü müsait değiller. Benzer şekilde, T2 iş
parçacığı altı ek kaynak talep edebilir ve beklemesi gerekebilir, bu da bir kilitlenmeye neden olur. Hatamız,
T2 iş parçacığından bir kaynak daha isteğini vermekti. T2'yi ikisinden birine kadar bekletmiş olsaydık
Machine Translated by Google

8.6 Kilitlenmeden Kaçınma 333

threadler bitmiş ve kaynaklarını serbest bırakmıştı, o zaman kilitlenmeyi önleyebilirdik.

Güvenli durum kavramı göz önüne alındığında, sistemin asla kilitlenmemesini


sağlayan kaçınma algoritmaları tanımlayabiliriz. Buradaki fikir, sistemin her zaman
güvenli bir durumda kalmasını sağlamaktır. Başlangıçta, sistem güvenli bir durumdadır.
Bir iş parçacığı mevcut olan bir kaynağı istediğinde, sistem kaynağın hemen tahsis
edilip edilemeyeceğine veya iş parçacığının beklemesi gerektiğine karar vermelidir.
İstek, yalnızca ayırma sistemi güvenli bir durumda bırakırsa verilir.

Bu şemada, bir iş parçacığı halihazırda mevcut olan bir kaynağı talep ederse, yine
de beklemesi gerekebilir. Bu nedenle, kaynak kullanımı, aksi takdirde olacağından daha
düşük olabilir.

8.6.2 Kaynak Tahsis-Grafik Algoritması

Her kaynak türünün yalnızca bir örneğine sahip bir kaynak tahsisat sistemimiz varsa,
kilitlenmeden kaçınmak için Bölüm 8.3.2'de tanımlanan kaynak tahsisi grafiğinin bir
türevini kullanabiliriz. Daha önce açıklanan istek ve atama kenarlarına ek olarak, talep
kenarı adı verilen yeni bir kenar türü sunuyoruz . Bir talep kenarı Ti Rj , Ti parçacığının
gelecekte bir zamanda Rj kaynağı talep edebileceğini gösterir. Bu kenar, yönde bir
istek kenarına benzer, ancak grafikte kesikli bir çizgi ile temsil edilir. Ti parçacığı Rj
kaynağını istediğinde , talep kenarı Ti Rj bir istek kenarına dönüştürülür. Benzer
şekilde,
bir kaynak Rj Ti tarafından serbest bırakıldığında , atama kenarı Rj Ti yeniden bir
talep kenarına Ti Rj dönüştürülür .

Kaynakların sistemde önceden talep edilmesi gerektiğini unutmayın. Yani, Ti


parçacığı yürütülmeye başlamadan önce, tüm talep kenarları kaynak tahsisi grafiğinde
zaten görünmelidir. Ti Rj istem kenarının grafiğe eklenmesine izin vererek, yalnızca
diş Ti ile ilişkili tüm kenarların istem kenarları olması durumunda bu koşulu gevşetebiliriz.

Şimdi Ti iş parçacığının Rj kaynağını istediğini varsayalım . İstek, yalnızca istek


kenarı Ti Rj'nin bir atama kenarına Rj Ti dönüştürülmesi , kaynak tahsisi grafiğinde
bir döngü oluşumuna neden olmazsa verilebilir. Bir döngü algılama algoritması
kullanarak güvenliği kontrol ederiz. Bu grafikte bir döngü tespit etmek için bir
algoritma , n'nin sistemdeki iş parçacığı sayısı olduğu bir n2 işlem sırası gerektirir.

Döngü yoksa, kaynağın tahsisi sistemi güvenli bir durumda bırakacaktır. Bir döngü
bulunursa, tahsis sistemi güvenli olmayan bir duruma sokar. Bu durumda, Ti parçacığı
isteklerinin yerine getirilmesini beklemek zorunda kalacaktır.

Bu algoritmayı göstermek için Şekil 8.9'daki kaynak tahsisi grafiğini ele alıyoruz.
T2'nin R2'yi istediğini varsayalım . R2 şu anda ücretsiz olsa da bu işlem grafikte bir
döngü oluşturacağından T2'ye tahsis edemiyoruz (Şekil 8.10). Belirtildiği gibi bir
döngü, sistemin güvenli olmayan bir durumda olduğunu gösterir. T1 R2'yi ve T2 R1'i
talep ederse , bir kilitlenme meydana gelir.

8.6.3 Bankacı Algoritması

Kaynak tahsisi grafiği algoritması, her kaynak türünün birden çok örneğine sahip bir
kaynak tahsis sistemine uygulanamaz. bu
334 Bölüm 8 Kilitlenmeler
Machine Translated by Google

R1

T1 T2

R2

Şekil 8.9 Kilitlenmeden kaçınma için kaynak tahsisi grafiği.

Daha sonra açıklayacağımız kilitlenmeden kaçınma algoritması böyle bir


sisteme uygulanabilir ancak kaynak tahsisi grafik şemasından daha az
verimlidir. Bu algoritma genellikle bankacının algoritması olarak bilinir. Bu
ad, algoritmanın bir bankacılık sisteminde, bankanın mevcut nakitlerini hiçbir
zaman tüm müşterilerinin ihtiyaçlarını karşılayamayacak şekilde tahsis
etmemesini sağlamak için kullanılabileceği için seçildi.
Yeni bir iş parçacığı sisteme girdiğinde, ihtiyaç duyabileceği her
kaynak türünün maksimum örnek sayısını bildirmelidir. Bu sayı, sistemdeki
toplam kaynak sayısını aşamaz. Bir kullanıcı bir dizi kaynak istediğinde,
sistem bu kaynakların tahsisinin sistemi güvenli bir durumda bırakıp
bırakmayacağını belirlemelidir. Olursa kaynaklar tahsis edilir; aksi takdirde,
iş parçacığı başka bir iş parçacığı yeterince serbest kalana kadar beklemelidir.
kaynaklar.

Bankacının algoritmasını uygulamak için çeşitli veri yapıları korunmalıdır.


Bu veri yapıları, kaynak tahsis sisteminin durumunu kodlar. n'nin sistemdeki
iş parçacığı sayısı ve m'nin kaynak türlerinin sayısı olduğu aşağıdaki veri
yapılarına ihtiyacımız var:

• Mevcut. m uzunluğunda bir vektör, her türden kullanılabilir kaynakların


sayısını gösterir. Kullanılabilir [j] , k'ye eşitse , Rj kaynak türünün k örneği
kullanılabilir.

R1

T1 T2

R2

Şekil 8.10 Kaynak tahsisi grafiğinde güvenli olmayan bir durum.


8.6 Kilitlenmeden Kaçınma 335
Machine Translated by Google
• Maks. Bir n × m matrisi, her dişin maksimum talebini tanımlar.
Maks [i][j] k'ye eşitse , Ti parçacığı Rj kaynak türünün en fazla k örneğini isteyebilir . •
Tahsis. Bir n × m matrisi, her bir iş parçacığına o anda tahsis edilen her türden kaynak

sayısını tanımlar. Allocation [i][j] k'ye eşitse , o zaman Ti iş parçacığına şu anda Rj kaynak
türünün k örneği tahsis edilir . • İhtiyaç. Bir n × m matrisi, her bir iş parçacığının
kalan kaynak ihtiyacını gösterir. Eğer Need[i][j] k'ye eşitse , Ti iş parçacığının görevini

tamamlamak için k tane daha Rj kaynak tipi örneğine ihtiyacı olabilir . İhtiyaç[i][j]' nin
Maks[i][j]'ye eşit olduğunu unutmayın.

Tahsis[i][j].

Bu veri yapıları zaman içinde hem boyut hem de değer olarak değişir.
Bankacının algoritmasının sunumunu basitleştirmek için daha sonra bazı notasyonlar
oluşturacağız. X ve Y , n uzunluğunda vektörler olsun . X Y olduğunu ancak ve ancak X[i]
Y[i] ise tüm i = 1, 2, ..., n için söylüyoruz
Y X. .Ayrıca
Örneğin,
Y X=
ve(1,7,3,2)
Y veYY<=X.
X ise (0,3,2,1) ise, o zaman

Allocation ve Need matrislerindeki her satırı vektör olarak ele alabilir ve Allocationi ve
Needi olarak adlandırabiliriz . Allocationi vektörü , şu anda Ti iş parçacığına tahsis edilen
kaynakları belirtir ; Needi vektörü , Ti iş parçacığının görevini tamamlamak için hala
isteyebileceği ek kaynakları belirtir .

8.6.3.1 Güvenlik Algoritması

Artık bir sistemin güvenli durumda olup olmadığını bulmak için algoritmayı sunabiliriz. Bu
algoritma şu şekilde açıklanabilir:

1. İş ve Bitiş sırasıyla m ve n uzunluğunda vektörler olsun . İşi Başlat = Kullanılabilir ve


Bitir[i] = i = 0, 1, ..., n 1 için false .
2. Her ikisi de olacak şekilde bir i indeksi bulun

a. Bitir[i] == yanlış

b. İhtiyaç İş

Böyle bir i yoksa 4. adıma gidin.

3. İş = İş + Tahsisat Bitir[i] = doğru


2. adıma gidin.

4. Tüm i için Finish[i] == true ise , sistem güvenli durumdadır.

Bu algoritma, bir durumun güvenli olup olmadığını belirlemek için bir m × n2 işlem sırası
gerektirebilir .

8.6.3.2 Kaynak-Talep Algoritması Daha sonra,

isteklerin güvenli bir şekilde verilip verilemeyeceğini belirleyen algoritmayı açıklayacağız.


Ti iş parçacığının istek vektörü Requesti olsun . Requesti [j]
== k ise , Ti iş parçacığı Rj kaynak türünün k örneğini ister . Ti iş parçacığı tarafından
kaynaklar için bir istek yapıldığında , aşağıdaki eylemler gerçekleştirilir:
336 Bölüm 8 Kilitlenmeler
Machine Translated by Google

1. Eğer Requesti Needi ise 2. adıma gidin. Aksi takdirde, bir hata koşulu yükseltin, çünkü
iş parçacığı maksimum iddiasını aştı.

2. Eğer Requesti Uygun ise adım 3'e gidin. Aksi takdirde, Ti'nin beklemesi gerekir.
kaynaklar mevcut değildir.

3. Sistemin, istenen kaynakları tahsis etmiş gibi yapmasını sağlayın.


durumu aşağıdaki gibi değiştirerek Ti'yi işleyin :

Mevcut = Mevcut–Talep
Tahsis = Tahsis + Talep
Needi = Needi -Requesti

Ortaya çıkan kaynak ayırma durumu güvenliyse, işlem tamamlanır ve Ti iş


parçacığına kaynakları tahsis edilir. Ancak, eğer yeni devlet
güvenli değilse, Ti'nin Requesti ve eski kaynak tahsisini beklemesi gerekir .
devlet geri yüklenir.

8.6.3.3 Açıklayıcı Bir Örnek

Bankacı algoritmasının kullanımını göstermek için beşli bir sistem düşünün.


T0 ile T4 arasındaki iş parçacıkları ve A, B ve C üç kaynak türü . Kaynak türü A
on örneği vardır, kaynak türü B'nin beş örneği vardır ve kaynak türü C'nin
yedi örnek. Aşağıdaki anlık görüntünün mevcut durumu temsil ettiğini varsayalım.
sistemin durumu:

Tahsis Maks. Kullanılabilir


ABC ABC
T0 010 753 332
T1 200 322
T2 302 902
T3 211 222
T4 002 433

İhtiyaç matrisinin içeriği Maks - Tahsis olarak tanımlanır ve şu şekildedir :


şöyle:

İhtiyaç

ABC
T0 743
T1 122
T2 600
T3 011
T4 431

Sistemin şu anda güvenli bir durumda olduğunu iddia ediyoruz. Nitekim, sıra
<T1, T3, T4, T2, T0> güvenlik kriterlerini karşılar. Diyelim ki şimdi bu iş parçacığı
T1 , ek bir A tipi kaynak örneği ve iki örnek talep eder.
kaynak türü C, bu nedenle İstek1 = (1,0,2). Bu isteğin gerçekleşip gerçekleşemeyeceğine karar vermek için
hemen verildiğinde, önce İstek1 Uygun olup olmadığını kontrol ederiz - yani
8.7 Kilitlenme Algılama 337
Machine Translated by Google

(1,0,2) (3,3,2), ki bu doğrudur. Daha sonra bu isteğin gerçekleştiğini varsayıyoruz.


yerine getirildi ve aşağıdaki yeni duruma ulaştık:

Tahsis İhtiyacı Mevcut

ABC ABC
T0 010 743 230
T1 302 020
T2 302 600
T3 211 011
T4 002 431

Bu yeni sistem durumunun güvenli olup olmadığını belirlememiz gerekiyor. Bunu yapmak için, biz
güvenlik algoritmamızı yürütün ve <T1, T3, T4, T0, T2> dizisini bulun
güvenlik gereksinimini karşılar. Bu nedenle, isteği hemen verebiliriz
iplik T1.
Bununla birlikte, sistem bu durumdayken, bir
kaynaklar mevcut olmadığı için T4 tarafından (3,3,0) talebi kabul edilemez.
Ayrıca, T0 tarafından (0,2,0) için bir istek ,
Ortaya çıkan durum güvenli olmadığı için kaynaklar mevcuttur.
Bunu, öğrencilerin uygulamayı gerçekleştirmeleri için bir programlama alıştırması olarak bırakıyoruz.
bankacı algoritması.

8.7 Kilitlenme Algılama

Bir sistem bir kilitlenme önleme veya bir kilitlenme önleme algoritması
kullanmıyorsa, bir kilitlenme durumu meydana gelebilir. Bu ortamda,
sistem şunları sağlayabilir:

• olup olmadığını belirlemek için sistemin durumunu inceleyen bir algoritma


bir kilitlenme oluştu

• Kilitlenmeden kurtulmak için bir algoritma

Daha sonra, bu iki gereksinimi, sistemlerle ilgili oldukları için tartışacağız.


her kaynak türünün yalnızca tek bir örneğinin yanı sıra her kaynak türünün
birkaç örneğine sahip sistemlere. Ancak bu noktada şunu belirtelim ki, bir
algılama ve kurtarma şeması, yalnızca
gerekli bilgileri sürdürmenin ve yürütmenin çalışma zamanı maliyetleri
algılama algoritması değil, aynı zamanda kurtarmanın doğasında var olan potansiyel kayıplar
bir kilitlenme.

8.7.1 Her Kaynak Türünün Tek Eşgörünümü

Tüm kaynakların yalnızca tek bir örneği varsa, kaynak tahsisi grafiğinin bir
türevini kullanan bir kilitlenme algılama algoritması tanımlayabiliriz.
bir bekleme grafiği. Bu grafiği kaynak tahsisi grafiğinden şu şekilde elde ederiz:
kaynak düğümlerini kaldırmak ve uygun kenarları daraltmak.
Daha doğrusu, bir bekleme grafiğinde Ti'den Tj'ye bir kenar, ipliğin
Ti , Tj iş parçacığının Ti'nin ihtiyaç duyduğu bir kaynağı serbest bırakmasını bekliyor . Bir kenar Ti Tj
Machine Translated by Google

338
Bölüm 8 Kilitlenmeler

T5

R1 R3 R4

T5

T1 T2 T3

T1 T2 T3

T4
T4
R2 R5

(a) (b)

Şekil 8.11 (a) Kaynak tahsisi grafiği. (b) Karşılık gelen bekleme grafiği.

bir bekleme grafiğinde, ancak ve ancak karşılık gelen kaynak tahsis grafiği, bazı
Rq kaynakları için Ti Rq ve Rq Tj olmak üzere iki kenar içeriyorsa mevcuttur .
Şekil 8.11'de bir kaynak tahsisi grafiği ve buna karşılık gelen bekleme grafiği
sunuyoruz.
Daha önce olduğu gibi, sistemde yalnızca ve yalnızca bekleme grafiği bir
döngü içeriyorsa bir kilitlenme vardır. Kilitlenmeleri algılamak için sistemin grafiği
beklemeyi sürdürmesi ve grafikte bir döngü arayan bir algoritmayı periyodik olarak
başlatması gerekir. Bir grafikteki bir döngüyü algılamak için bir algoritma, O(n2)
işlemlerini gerektirir; burada n , grafikteki köşe sayısıdır.
Bölüm 2.10.4'te açıklanan BCC araç takımı, bir Linux sisteminde çalışan bir
kullanıcı işleminde Pthreads muteks kilitleriyle olası kilitlenmeleri algılayabilen bir
araç sağlar. BCC aracı kilitlenme algılayıcısı , pthread mutex lock() ve pthread
mutex unlock() işlevlerine yapılan çağrıları izleyen problar ekleyerek çalışır .
Belirtilen süreç herhangi bir işleve çağrı yaptığında, kilitlenme algılayıcısı bu
süreçte muteks kilitlerinin bir bekleme grafiği oluşturur ve grafikte bir döngü
algılarsa kilitlenme olasılığını bildirir.

8.7.2 Bir Kaynak Tipinin Birkaç Eşgörünümü


Bekleme grafiği şeması, her kaynak türünün birden çok örneğini olan bir kaynak
tahsis sistemine uygulanamaz. Şimdi böyle bir sisteme uygulanabilen bir kilitlenme
algılama algoritmasına dönüyoruz. Algoritma, bankacının algoritmasında
kullanılanlara benzer zamanla değişen birkaç veri yapısı kullanır (Bölüm 8.6.3):

• Mevcut. m uzunluğunda bir vektör , mevcut kaynakların sayısını gösterir.


her türden.
Machine Translated by Google

8.7 Kilitlenme Algılama 339

JAVA İPLİK DÖKÜMLERİNİ KULLANARAK KİLİT TESPİTİ

Java, kilitlenme tespiti için açık destek sağlamasa da, bir kilitlenme olup olmadığını belirlemek
için çalışan bir programı analiz etmek için bir iş parçacığı dökümü kullanılabilir. İş parçacığı
dökümü, bir Java uygulamasındaki tüm iş parçacıklarının durumlarının anlık görüntüsünü
görüntüleyen kullanışlı bir hata ayıklama aracıdır. Java iş parçacığı dökümleri ayrıca, bloke
edilmiş bir iş parçacığının hangi kilitleri almayı beklediği de dahil olmak üzere kilitleme bilgilerini
gösterir. Bir iş parçacığı dökümü oluşturulduğunda, JVM döngüleri algılamak için bekleme
grafiğini arar ve algıladığı kilitlenmeleri bildirir. Çalışan bir uygulamanın iş parçacığı dökümünü
oluşturmak için komut satırından şunu girin:

Ctrl-L (UNIX, Linux veya macOS)


Ctrl-Break (Windows)

Bu metnin kaynak kodu indirmesinde, Şekil 8.1'de gösterilen programın bir Java örneğini
sunuyoruz ve kilitlenmiş Java iş parçacıklarını bildiren bir iş parçacığı dökümünün nasıl
oluşturulacağını açıklıyoruz.

• Tahsis. Bir n × m matrisi, her bir iş parçacığına o anda tahsis edilen her türden
kaynak sayısını tanımlar.

• İstek. Bir n × m matrisi, her bir iş parçacığının mevcut talebini gösterir.


Request [i][j] k'ye eşitse , Ti iş parçacığı k tane daha Rj kaynak türü örneği istiyor .

İki vektör arasındaki ilişkisi Bölüm 8.6.3'te tanımlanmıştır. Gösterimi


basitleştirmek için, Allocation ve Request matrislerindeki satırları yine vektörler olarak
ele alıyoruz; Biz bunlara Allocationi ve Requesti olarak değiniyoruz . Burada açıklanan
algılama algoritması, tamamlanmak üzere kalan iş parçacıkları için olası her tahsis
sırasını basitçe araştırır. Bu algoritmayı, Bölüm 8.6.3'teki bankacının algoritması ile
karşılaştırın.

1. İş ve Bitiş sırasıyla m ve n uzunluğunda vektörler olsun . Çalışmayı Başlat =


Mevcut. i = 0, 1, ..., n–1 için AllocationiFinish[i]
0 ise,=Finish
true. [i] = false. Aksi takdirde,

2. Her ikisi de olacak şekilde bir i indeksi bulun

a. Bitir[i] == yanlış

b. İstek İş

Böyle bir i yoksa 4. adıma gidin.


3. İş = İş + Tahsisat Bitir[i] =
doğru 2. adıma gidin.

4. Bazı i, 0 i < n için Finish[i] == false ise, sistem kilitlenme durumundadır. Ayrıca,
Finish[i] == false ise, Ti parçacığı kilitlenir.

Bu algoritma , sistemin kilitlenme durumunda olup olmadığını tespit etmek için m ×


n2 sıralı bir işlem gerektirir.
340 Bölüm 8 Kilitlenmeler
Machine Translated by Google

Ti parçacığının kaynaklarını neden geri aldığımızı merak edebilirsiniz (3. adımda)


Requesti Work olduğunu belirlediğimiz anda (adım 2b'de). Ti olduğunu biliyoruz
şu anda bir kilitlenmeye dahil değil ( Requesti Work'ten beri ). Böylece, alıyoruz
iyimser bir tutum ve Ti'nin daha fazla kaynağa ihtiyaç duymayacağını varsayın
görevini tamamlamak; bu nedenle yakında tahsis edilen tüm kaynakları
sistem. Varsayımımız yanlışsa, daha sonra bir kilitlenme meydana gelebilir. O
kilitlenme algılama algoritması bir sonraki seferde kilitlenme algılanacaktır.
çağrılır.
Bu algoritmayı göstermek için, beş iş parçacığı T0 olan bir sistemi ele alıyoruz.
T4 aracılığıyla ve üç kaynak türü A, B ve C. Kaynak türü A'da yedi kaynak türü vardır
örnekler, kaynak türü B'nin iki örneği vardır ve kaynak türü C'nin altı örneği vardır .
örnekler. Aşağıdaki anlık görüntü, sistemin mevcut durumunu temsil eder:

Tahsis Talebi Mevcut


ABC ABC
T0 010 000 000
T1 200 202
T2 303 000
T3 211 100
T4 002 002

Sistemin kilitlenme durumunda olmadığını iddia ediyoruz. Gerçekten, eğer uygularsak


Algoritmamızda, <T0, T2, T3, T1, T4> dizisinin şu sonuçla sonuçlandığını bulacağız .
Finish[i] == tüm i için doğru .
Şimdi, T2 iş parçacığının bir örnek için ek bir istekte bulunduğunu varsayalım.
C tipi . İstek matrisi aşağıdaki gibi değiştirilir:

Rica etmek
ABC
T0 000
T1 202
T2 001
T3 100
T4 002

Sistemin artık kilitlendiğini iddia ediyoruz. geri alabilsek de


T0 iş parçacığı tarafından tutulan kaynaklar, kullanılabilir kaynakların sayısı yeterli değil
diğer konuların isteklerini yerine getirmek için. Bu nedenle, aşağıdakilerden oluşan bir kilitlenme vardır:
T1, T2, T3 ve T4 dişleri .

8.7.3 Algılama-Algoritma Kullanımı

Algılama algoritmasını ne zaman çalıştırmalıyız? Cevap iki şeye bağlı


faktörler:

1. Bir kilitlenmenin meydana gelme olasılığı ne kadardır ?

2. Kilitlenme olduğunda kaç tane iş parçacığı etkilenecek?


8.8 Kilitlenmeden Kurtarma 341
Machine Translated by Google

VERİTABANLARINDA KİLİT YÖNETİM

Veritabanı sistemleri, hem açık kaynaklı hem de ticari yazılımların kilitlenmeyi


nasıl yönettiğine dair faydalı bir örnek sağlar. Bir veritabanındaki
güncellemeler işlem olarak gerçekleştirilebilir ve veri bütünlüğünü
sağlamak için tipik olarak kilitler kullanılır. Bir işlem birkaç kilit içerebilir,
bu nedenle birden fazla eşzamanlı işlem içeren bir veritabanında
kilitlenmelerin mümkün olması şaşırtıcı değildir. Kilitlenmeyi yönetmek
için çoğu işlemsel veritabanı sistemi bir kilitlenme algılama ve kurtarma
mekanizması içerir. Veritabanı sunucusu, bir dizi işlem arasındaki kilitlenmeyi
algılamak için bekleme grafiğindeki döngüleri periyodik olarak arayacaktır.
Kilitlenme tespit edildiğinde, bir kurban seçilir ve işlem iptal edilir ve geri
alınır, kurban işlemi tarafından tutulan kilitler serbest bırakılır ve kalan
işlemler kilitlenmeden kurtarılır. Kalan işlemler devam ettirildiğinde, iptal edilen i
Kurban işleminin seçimi, veritabanı sistemine bağlıdır; örneğin MySQL ,
eklenen, güncellenen veya silinen satır sayısını en aza indiren işlemleri
seçmeye çalışır.

Kilitlenmeler sık sık meydana geliyorsa, algılama algoritması sık sık çalıştırılmalıdır.
Kilitlenen iş parçacıklarına ayrılan kaynaklar, kilitlenme bozulana kadar boşta
kalacaktır. Ek olarak, kilitlenme döngüsüne dahil olan iş parçacıklarının sayısı
artabilir.
Kilitlenmeler, yalnızca bazı iş parçacıkları hemen verilemeyen bir istekte
bulunduğunda meydana gelir. Bu istek, bir bekleyen iş parçacığı zincirini
tamamlayan son istek olabilir. Aşırı durumda, bir tahsisat talebinin hemen
verilemeyeceği her zaman kilitlenme tespit algoritmasını çağırabiliriz. Bu durumda,
yalnızca kilitlenen iş parçacığı kümesini değil, aynı zamanda kilitlenmeye "neden
olan" belirli iş parçacığını da tanımlayabiliriz. (Gerçekte, kilitlenen iş parçacıklarının
her biri, kaynak grafiğindeki döngüdeki bir bağlantıdır, bu nedenle hepsi birlikte
kilitlenmeye neden olur.) Birçok farklı kaynak türü varsa, bir istek kaynak grafiğinde
birçok döngü oluşturabilir. , her döngü en son istek tarafından tamamlanır ve
tanımlanabilir tek bir iş parçacığının "nedenidir".
Elbette, her kaynak isteği için kilitlenme algılama algoritmasını çağırmak,
hesaplama süresinde önemli bir ek yüke neden olacaktır. Daha ucuz bir alternatif,
algoritmayı tanımlı aralıklarla, örneğin saatte bir kez veya CPU kullanımı yüzde 40'ın
altına düştüğünde çalıştırmaktır.
(Bir kilitlenme sonunda sistem verimini felce uğratır ve CPU kullanımının düşmesine
neden olur.) Algılama algoritması zaman içinde rastgele noktalarda çağrılırsa,
kaynak grafiği birçok döngü içerebilir. Bu durumda, genellikle kilitlenen birçok iş
parçacığından hangisinin kilitlenmeye "neden olduğunu" söyleyemeyiz.

8.8 Kilitlenmeden Kurtarma


Bir algılama algoritması bir kilitlenme olduğunu belirlediğinde, birkaç alternatif
yerli kullanılabilir. Bir olasılık, operatöre bir kilitlenme oluştuğunu bildirmek ve
operatörün kilitlenmeyle manuel olarak ilgilenmesine izin vermektir. Diğer bir
olasılık, sistemin kilitlenmeden otomatik olarak kurtulmasına izin vermektir. Orası
342 Bölüm 8 Kilitlenmeler
Machine Translated by Google

bir kilitlenmeyi kırmak için iki seçenek vardır. Biri, dairesel beklemeyi kırmak için bir veya
daha fazla iş parçacığını iptal etmektir. Diğeri, kilitlenen bir veya daha fazla iş parçacığından
bazı kaynakları önceden almaktır.

8.8.1 İşlem ve İplik Sonlandırma

Bir işlemi veya iş parçacığını iptal ederek kilitlenmeleri ortadan kaldırmak için iki yöntemden
birini kullanırız. Her iki yöntemde de sistem, sonlandırılan işlemlere tahsis edilen tüm
kaynakları geri alır.

• Kilitlenen tüm süreçleri iptal edin. Bu yöntem açıkça kilitlenme döngüsünü kıracaktır,
ancak büyük bir maliyetle. Kilitli süreçler uzun süre hesaplanmış olabilir ve bu kısmi
hesaplamaların sonuçları atılmalı ve muhtemelen daha sonra yeniden hesaplanması
gerekecektir.

• Kilitlenme döngüsü ortadan kalkana kadar bir seferde bir işlemi iptal edin. Her işlem iptal
edildikten sonra, herhangi bir işlemin hala kilitlenip kilitlenmediğini belirlemek için bir
kilitlenme algılama algoritmasının çağrılması gerektiğinden, bu yöntem önemli
ölçüde ek yüke neden olur.

Bir işlemi iptal etmek kolay olmayabilir. İşlem bir dosyayı güncellemenin ortasındaysa,
sonlandırmak o dosyayı yanlış bir durumda bırakabilir. Benzer şekilde, işlem bir muteks kilidi
tutarken paylaşılan verileri güncellemenin ortasındaysa, paylaşılan verilerin bütünlüğü ile
ilgili hiçbir garanti verilemese de, sistem kilidin durumunu kullanılabilir olarak geri
yüklemelidir.
Kısmi sonlandırma yöntemi kullanılıyorsa, hangi kilitli işlemin (veya işlemlerin)
sonlandırılacağını belirlememiz gerekir. Bu belirleme, CPU zamanlama kararlarına benzer
bir ilke kararıdır. Soru temelde ekonomiktir; sonlandırılması minimum maliyete neden olacak
süreçleri iptal etmeliyiz. Ne yazık ki, minimum maliyet terimi kesin değildir. Aşağıdakiler
de dahil olmak üzere birçok faktör hangi sürecin seçildiğini etkileyebilir:

1. Sürecin önceliği nedir 2. Sürecin ne kadar

uzun olduğunu ve sürecin ne kadar uzun olduğunu


belirlenen görevini tamamlamadan önce hesaplayacak

3. Sürecin ne kadar ve ne tür kaynak kullandığını (sınav için)


ple, kaynakların önceden alınmasının kolay olup olmadığı)

4. İşlemin tamamlanması için daha kaç kaynağa ihtiyacı var 5. Kaç işlemin

sonlandırılması gerekecek

8.8.2 Kaynak Önceliği

Kaynak önceliğini kullanarak kilitlenmeleri ortadan kaldırmak için, bazı kaynakları


süreçlerden art arda önlüyor ve kilitlenme döngüsü bozulana kadar bu kaynakları diğer
süreçlere veriyoruz.
Kilitlenmelerle başa çıkmak için önceden alım gerekiyorsa, o zaman üç konunun ele
alınması gerekir:
Machine Translated by Google 8.9 Özet 343

1. Bir kurban seçmek. Hangi kaynaklar ve hangi süreçler önlenmelidir? İşlem


sonlandırmada olduğu gibi, maliyeti en aza indirmek için ön alım sırasını
belirlememiz gerekir. Maliyet faktörleri, kilitlenmemiş bir işlemin tuttuğu
kaynak sayısı ve işlemin o ana kadar tükettiği süre gibi parametreleri içerebilir.

2. Geri alma. Bir kaynağı bir süreçten önce alırsak, o süreçle ne yapılmalı?
Açıkçası, normal yürütmesine devam edemez; bazı gerekli kaynak eksik.
İşlemi güvenli bir duruma geri almalı ve bu durumdan yeniden başlatmalıyız.

Genel olarak güvenli durumun ne olduğunu belirlemek zor olduğundan,


en basit çözüm tam bir geri almadır: işlemi iptal edin ve ardından yeniden
başlatın. Süreci yalnızca kilitlenmeyi kırmak için gerektiği kadar geri almak
daha etkili olsa da, bu yöntem sistemin çalışan tüm süreçlerin durumu
hakkında daha fazla bilgi tutmasını gerektirir.
3. Açlık. Açlığın oluşmayacağından nasıl emin olabiliriz? Yani, kaynakların her
zaman aynı süreçten etkilenmeyeceğini nasıl garanti edebiliriz?

Kurban seçiminin öncelikli olarak maliyet faktörlerine dayandığı bir


sistemde, kurban olarak her zaman aynı sürecin seçilmesi söz konusu olabilir.
Sonuç olarak, bu süreç hiçbir zaman belirlenmiş görevini tamamlamaz,
herhangi bir pratik sistemin ele alması gereken bir açlık durumu. Açıkçası, bir
sürecin yalnızca (küçük) sınırlı sayıda kurban olarak seçilebilmesini sağlamalıyız.
En yaygın çözüm, maliyet faktörüne geri alma sayısını dahil etmektir.

8.9 Özet
• Bir dizi işlemde, kümedeki her işlem yalnızca kümedeki başka bir işlemin neden
olabileceği bir olayı beklediğinde kilitlenme oluşur. • Kilitlenme için dört
gerekli koşul vardır: (1) karşılıklı dışlama, (2) bekle ve bekle, (3) ön alma yok ve (4)
döngüsel bekle. Kilitlenme yalnızca dört koşulun tümü mevcut olduğunda
mümkündür.
• Kilitlenmeler, bir döngünün olduğu kaynak tahsisi grafikleriyle modellenebilir.
kilitlenmeyi gösterir.

• Deadlock için gerekli dört koşuldan birinin gerçekleşmemesi sağlanarak


kilitlenmeler önlenebilir. Dört gerekli koşuldan dairesel beklemeyi ortadan
kaldırmak tek pratik yaklaşımdır.
• Kilitlenme, sistemi kilitlenmenin mümkün olacağı güvenli olmayan bir duruma
sokacaksa kaynak vermeyen bankacı algoritması kullanılarak önlenebilir. • Bir
kilitlenme algılama algoritması, bir dizi işlemin kilitlenme durumunda olup
olmadığını belirlemek için çalışan bir sistemdeki işlemleri ve kaynakları
değerlendirebilir. • Kilitlenme meydana gelirse, sistem döngüsel beklemedeki
işlemlerden birini iptal ederek veya kilitlenmiş bir sürece atanmış kaynakları
önleyerek kilitlenmeden kurtarmayı deneyebilir.
Machine Translated by Google

344 Bölüm 8 Kilitlenmeler

Alıştırmalar

8.1 Bir bilgisayarla ilgili olmayan üç kilitlenme örneği listeleyin


sistem ortamı.

8.2 Bir sistemin güvenli olmayan bir durumda olduğunu varsayalım. İş parçacıklarının
bir kilitlenme girmeden yürütmelerini tamamlamalarının mümkün olduğunu gösterin.
durum.

8.3 Bir sistemin aşağıdaki anlık görüntüsünü göz önünde bulundurun:

Tahsis Maks. Kullanılabilir


ABCD ABCD ABCD
T0 0012 0012 1520
T1 1000 1750
T2 1354 2356
T3 0632 0652
T4 0014 0656

Bankacının algoritmasını kullanarak aşağıdaki soruları yanıtlayın:


a. İhtiyaç matrisinin içeriği nedir ?

b. Sistem güvenli durumda mı? c.


(0,4,2,0) için T1 iş parçacığından bir istek gelirse, istek şu şekilde olabilir mi?
hemen verildi?

8.4 Kilitlenmeleri önlemenin olası bir yöntemi, başka herhangi bir kaynaktan önce
talep edilmesi gereken tek, daha yüksek dereceli bir kaynağa sahip olmaktır.
Örneğin, birden çok iş parçacığı A ··· E eşitleme nesnelerine erişmeye
çalışırsa, kilitlenme mümkündür. (Bu tür senkronizasyon nesneleri muteksler,
semaforlar, koşul değişkenleri ve benzerlerini içerebilir.) Altıncı bir F nesnesi
ekleyerek kilitlenmeyi önleyebiliriz . Ne zaman bir iş parçacığı herhangi bir
A ··· E nesnesi için senkronizasyon kilidini almak isterse , önce F nesnesi için
kilidi alın . Bu çözüm, kapsama olarak bilinir : A ··· E nesnelerinin kilitleri, F
nesnesinin kilidinin içinde bulunur .
Bu şemayı Bölüm 8.5.4'teki dairesel bekleme şemasıyla karşılaştırın.

8.5 Bölüm 8.6.3'te sunulan güvenlik algoritmasının m × n2 işlem sırası gerektirdiğini


kanıtlayın.
8.6 Ayda 5.000 iş çalıştıran ve kilitlenme önleme veya kilitlenme önleme şeması
olmayan bir bilgisayar sistemi düşünün. Kilitlenmeler ayda yaklaşık iki kez
meydana gelir ve operatörün kilitlenme başına yaklaşık on işi sonlandırması
ve yeniden çalıştırması gerekir. Her iş yaklaşık iki dolar değerindedir ( CPU
zamanı olarak) ve sonlandırılan işler, iptal edildiklerinde yaklaşık yarısı
kadar yapılır.
Bir sistem programcısı, sistem başına ortalama yürütme süresinde
yaklaşık yüzde 10'luk bir artışla bir kilitlenme önleme algoritmasının
(bankacının algoritması gibi) sisteme kurulabileceğini tahmin etmiştir.
Alıştırmalar 345
Machine Translated by Google

Görev. Makine şu anda yüzde 30 boşta kalma süresine sahip olduğundan,


geri dönüş süresi ortalama yüzde 20 artacak olsa da, ayda 5.000 işin tümü
yine de çalıştırılabilir.

a. Kilitlenmeden kaçınmayı yüklemek için argümanlar nelerdir?


algoritma?
b. Kilitlenmeden kaçınmanın kurulmasına karşı argümanlar nelerdir?
algoritma?

8.7 Bir sistem, iş parçacıklarından bazılarının aç kaldığını algılayabilir mi? Cevabınız


“evet” ise nasıl olabileceğini açıklayın. “Hayır” cevabını verirseniz, sistemin açlık
sorunuyla nasıl başa çıkabileceğini açıklayın.

8.8 Aşağıdaki kaynak tahsisi politikasını göz önünde bulundurun. Kaynak isteklerine
ve kaynakların serbest bırakılmasına her zaman izin verilir. Kaynaklar müsait
olmadığı için bir kaynak talebi karşılanamıyorsa, kaynakları beklerken bloke
edilmiş herhangi bir iş parçacığını kontrol ederiz. Engellenen bir iş parçacığı
istenen kaynaklara sahipse, bu kaynaklar ondan alınır ve istekte bulunan iş
parçacığına verilir. Engellenen iş parçacığının beklediği kaynakların
vektörü, alınan kaynakları içerecek şekilde artırılır.

Örneğin, bir sistemin üç kaynak türü vardır ve Kullanılabilir vektörü


( 4,2,2 ) olarak başlatılır. T0 ipliği (2,2,1) isterse, onları alır. T1 (1,0,1) isterse ,
onları alır. Ardından, T0 (0,0,1) isterse, bloke edilir (kaynak mevcut değil). T2
şimdi (2,0,0) isterse , mevcut olanı (1,0,0) ve T0'a tahsis edileni (T0 bloke
olduğundan ) alır.
T0'ın Tahsis vektörü (1,2,1)'e düşer ve İhtiyaç vektörü (1,0,1)'e yükselir.

a. Kilitlenme meydana gelebilir mi? Cevabınız “evet” ise bir örnek veriniz.
Cevabınız “hayır” ise, hangi gerekli koşulun gerçekleşemeyeceğini belirtin.

b. Süresiz engelleme gerçekleşebilir mi? Cevabını açıkla.

8.9 Bir sistemin aşağıdaki anlık görüntüsünü göz önünde bulundurun:

Tahsis Maks
ABCD ABCD
T0 3014 5117
T1 2210 3211
T2 3121 3321
T3 0510 4612
T4 4212 6325

Bankacının algoritmasını kullanarak, aşağıdaki durumların her birinin güvensiz


olup olmadığını belirleyin. Durum güvenliyse, iş parçacıklarının
tamamlanabileceği sırayı gösterin. Aksi takdirde, devletin neden güvensiz olduğun

a. Mevcut = (0, 3, 0, 1) b.
Mevcut = (1, 0, 0, 2)
Machine Translated by Google

346 Bölüm 8 Kilitlenmeler

8.10 Bir sistemin güvenli durumda olup olmadığını belirleyen kilitlenme önleme
güvenlik algoritmasını kodladığınızı ve şimdi kilitlenme algılama algoritmasını
uygulamanız istendiğini varsayalım. Bunu, sadece güvenlik algoritması
kodunu kullanarak ve Maxi = Waitingi + Allocationi'yi yeniden tanımlayarak
yapabilir misinizkaynakları
, burada Waitingi
belirten, bir
i'nin hangi iş parçacığı
vektördür içinBölüm
ve Allocationi beklediği
8.6'da
tanımlandığı gibidir?
Cevabını açıkla.
8.11 Yalnızca tek iş parçacıklı bir kilitlenme olması mümkün müdür?
işlem? Cevabını açıkla.

Daha fazla okuma


Kilitlenmeyi içeren araştırmaların çoğu yıllar önce yapılmıştır. [Dijkstra (1965)]
çıkmaza ilk ve en etkili katkıda bulunanlardan biriydi.
alan.

MySQL veritabanının kilitlenmeyi nasıl yönettiğinin ayrıntıları http://dev.mysql.com/


adresinde bulunabilir.
Lockdep aracıyla ilgili ayrıntılar https://www.kernel.org/doc/ Documentation/
locking/lockdep-design.txt adresinde bulunabilir.

bibliyografya

[Dijkstra (1965)] EW Dijkstra, “Cooperating Sequential Processes”, Teknik


rapor, Technological University, Eindhoven, Hollanda (1965).
Machine Translated by Google

EX-27

Bölüm 8 Alıştırmalar

8.12 Şekil 8.12'de gösterilen trafik kilitlenmesini göz önünde bulundurun.

a. Kilitlenme için gerekli dört koşulun bu durumda tutulduğunu gösterin.


örnek.

b. Bu sistemdeki kilitlenmeleri önlemek için basit bir kural belirtin.

8.13 Bölüm 8.2'de Şekil 8.1'de gösterilen program örneğinden kilitlenmeyi gösteren
kaynak tahsisi grafiğini çizin.

8.14 Bölüm 6.8.1'de, P0 ve P1 süreçleri ile S ve Q semaforlarını içeren olası bir kilitlenme
senaryosunu tanımladık . Bu bölümde sunulan senaryo altında kilitlenmeyi
gösteren kaynak tahsis grafiğini çizin.

8.15 Çok iş parçacıklı bir uygulamanın senkronizasyon için yalnızca okuyucu-yazıcı kilitlerini
kullandığını varsayın. Kilitleme için gerekli dört koşulun uygulanması, birden fazla
okuyucu-yazıcı kilidi kullanılması durumunda yine de kilitlenme mümkün müdür?

8.16 Şekil 8.1'de gösterilen program örneği her zaman kilitlenmeye yol açmaz. CPU
zamanlayıcısının oynadığı rolü ve bu programda kilitlenmeye nasıl katkıda
bulunabileceğini açıklayın.

8.17 Bölüm 8.5.4'te tüm kilitlerin belirli bir sırayla alınmasını sağlayarak kilitlenmeyi
önlediğimiz bir durumu tanımlamıştık. Ancak, iki iş parçacığı aynı anda işlem()
işlevini çağırırsa, bu durumda kilitlenmenin mümkün olduğuna da işaret ediyoruz .
Kilitlenmeleri önlemek için transaction() işlevini düzeltin .





Şekil 8.11 Alıştırma 8.12 için trafik kilitlenmesi.


Machine Translated by Google

Egzersizler EX-28

8.18 Şekil 8.12'de gösterilen altı kaynak tahsisi grafiğinden hangisi, kilitlenme
durumunu gösterir? Kilitlenmeyen durumlar için aşağıdakileri sağlayın:
iş parçacığı ve kaynak döngüsü. Kilitlenme durumunun olmadığı durumlarda,
iş parçacıklarının yürütmeyi tamamlayabileceği sırayı gösterir.

8.19 Dairesel bekleme şemasını çeşitli kilitlenmeden kaçınma ile karşılaştırın


aşağıdakilere göre şemalar (bankacının algoritması gibi)
konular:

a. Çalışma zamanı yükü

b. Sistem verimi

8.20 Gerçek bir bilgisayar sisteminde, ne mevcut kaynaklar ne de


iş parçacıklarının kaynaklara yönelik talepleri uzun süreler boyunca tutarlıdır
(ay). Kaynaklar bozulur veya değiştirilir, yeni süreçler ve iş parçacıkları
gelip gider ve yeni kaynaklar satın alınır ve sisteme eklenir.
Kilitlenme bankacının algoritması tarafından kontrol ediliyorsa, aşağıdakilerden hangisi

(a) (b)
T1 T3
R2_
R1

• • R1 R2
_ R3
_

•••
T1 T2 T3

T2 _

(c) (d)
R1 R2
_ T1 T2

•• •• R1 R2
_

•• ••
T1 T2 3_

4_
T3

(e) (f )

T1 T2
T1 T2

R1 R2
_
R1 R2 R3
_

•• •• • •• ••

T3 T4
T3 T4

Şekil 8.12 Alıştırma 8.18 için kaynak tahsisi grafikleri.


EX-29
Machine Translated by Google

aşağıdaki değişiklikler güvenli bir şekilde yapılabilir (


kilitlenme olasılığı) ve hangi koşullar altında?

a. Mevcut Artır (yeni kaynaklar eklendi).

b. Azalt Kullanılabilir (kaynak sistemden kalıcı olarak kaldırıldı).

c. Bir iş parçacığı için Maks'ı artırın (iş parçacığı daha fazlasını istiyor veya istiyor
izin verilenden daha fazla kaynaklar).

d. Bir iş parçacığı için Maks'ı azaltın (iş parçacığı buna gerek olmadığına karar verir
bu kadar kaynak).
e. Konu sayısını artırın.

f. İş parçacığı sayısını azaltın.

8.21 Bir sistemin aşağıdaki anlık görüntüsünü göz önünde bulundurun:

Tahsis Maks.
ABCD ABCD
T0 2106 6327
T1 3313 5415
T2 2312 6614
T3 1234 4345
T4 3030 7261

İhtiyaç matrisinin içeriği nedir ?

8.22 Aynı türden dört kaynaktan oluşan bir sistem düşünün:


her biri en fazla iki kaynağa ihtiyaç duyan üç iş parçacığı tarafından paylaşılır.
Sistemde kilitlenme olmadığını gösterin.

8.23 Aynı türden m kaynaktan oluşan bir sistem düşünün:


n konu tarafından paylaşıldı . Bir iş parçacığı yalnızca bir kaynak isteyebilir veya serbest bırakabilir
zamanında. Aşağıdaki iki durum varsa sistemin kilitlenmeden kurtulduğunu gösterin.
koşullar tutun:

a. Her iş parçacığının maksimum ihtiyacı bir kaynak ile m


kaynaklar.

b. Tüm maksimum ihtiyaçların toplamı m + n'den azdır.

8.24 Yemek-filozoflar sorununun,


yemek çubukları masanın ortasına yerleştirilir ve bunlardan herhangi ikisi
bir filozof tarafından kullanılabilir. Yemek çubukları isteklerinin
birer birer yapılmıştır. olup olmadığını belirlemek için basit bir kural tanımlayın.
belirli bir istek, verilen kilitlenmeye neden olmadan karşılanabilir.
yemek çubuklarının filozoflara tahsis edilmesi.

8.25 Önceki alıştırmadaki ayarı tekrar düşünün. şimdi varsayalım ki


her filozof yemek için üç yemek çubuğuna ihtiyaç duyar. Kaynak istekleri
hala birer birer yayınlandı. belirlemek için bazı basit kuralları tanımlayın.
belirli bir isteğin kilitlenmeye neden olmadan karşılanıp karşılanamayacağı
Filozoflara mevcut yemek çubukları tahsisi göz önüne alındığında.
Egzersizler EX-30
Machine Translated by Google

8.26 Tek bir kaynak türü için bankacının algoritmasını şuradan elde edebiliriz:
genel bankacının algoritması sadece boyutsallığı azaltarak
çeşitli dizilerin 1.
Tek kaynak tipini uygulayarak çoklu kaynak tipi bankacı şemasını
uygulayamayacağımızı bir örnekle gösterin.
her kaynak türüne ayrı ayrı şema.
8.27 Bir sistemin aşağıdaki anlık görüntüsünü göz önünde bulundurun:

Tahsis Maks.
ABCD ABCD
T0 1202 4316
T1 0112 2424
T2 1240 3651
T3 1201 2623
T4 1001 3112

Bankacının algoritmasını kullanarak, her birinin olup olmadığını belirleyin.


aşağıdaki durumlar güvenli değildir. Devlet güvenliyse, hangi sırada olduğunu gösterin.
ipler tamamlanabilir. Aksi takdirde, devletin neden güvensiz olduğunu gösterin.

a. Mevcut = (2, 2, 2, 3)
b. Mevcut = (4, 4, 1, 1)
c. Mevcut = (3, 0, 1, 4)
d. Mevcut = (1, 5, 2, 2)

8.28 Bir sistemin aşağıdaki anlık görüntüsünü göz önünde bulundurun:

Tahsis Maks. Mevcut


ABCD ABCD ABCD
T0 3141 6473 2224
T1 2102 4232
T2 2413 2533
T3 4110 6332
T4 2221 5675

Bankacının algoritmasını kullanarak aşağıdaki soruları yanıtlayın:

a. Aşağıdakileri göstererek sistemin güvenli durumda olduğunu gösterin.


iş parçacıklarının tamamlanabileceği sıra.
b. (2, 2, 2, 4) için T4 iş parçacığından bir istek gelirse , istek şu şekilde olabilir mi?
hemen verildi?
c. (0, 1, 1, 0) için T2 iş parçacığından bir istek gelirse , istek şu şekilde olabilir mi?
hemen verildi?
d. T3 iş parçacığından (2, 2, 1, 2) için bir istek gelirse, istek şu şekilde olabilir mi?
hemen verildi?
Machine Translated by Google

EX-31

8.29 Kilitlenme algılama algoritmasında yapılan iyimser varsayım nedir? Bu varsayım nasıl
ihlal edilebilir?

8.30 Tek şeritli bir köprü, iki Vermont köyünü North Tun köprüsü ile Güney Tunbridge'i
birbirine bağlar. İki köydeki çiftçiler ürünlerini komşu kasabaya ulaştırmak için
bu köprüyü kullanıyor. Kuzeye giden ve güneye giden bir çiftçi aynı anda köprüye
binerse, köprü çıkmaza girebilir. (Vermont çiftçileri inatçıdır ve yedekleme
yapamazlar.) Semaforlar ve/veya muteks kilitleri kullanarak, kilitlenmeyi önleyen
sözde kodda bir algoritma tasarlayın. Başlangıçta, açlıktan endişe etmeyin (kuzeye
giden çiftçilerin güneye giden çiftçilerin köprüyü kullanmasını engellemesi veya
tam tersi durum).

8.31 Çözümünüzü, açlıktan arınmış olacak şekilde Alıştırma 8.30'a göre değiştirin.
Machine Translated by Google

P-45 Bölüm 8 Kilitlenmeler

Programlama Sorunları

8.32 Çözümünüzü POSIX senkronizasyonunu kullanarak Alıştırma 8.30'a uygulayın .


Özellikle, kuzeye ve güneye giden çiftçileri ayrı konular olarak temsil edin. Bir
çiftçi köprüde olduğunda, ilişkili iplik, köprüden geçmeyi temsil eden
rastgele bir süre boyunca uyur.
Programınızı, kuzeye ve güneye giden çiftçileri temsil eden birkaç iş
parçacığı oluşturabileceğiniz şekilde tasarlayın.

8.33 Şekil 8.7'de, dinamik olarak kilitleri alan bir işlem() fonksiyonunu gösteriyoruz.
Metinde, bu fonksiyonun kilitlenmeyi önleyecek şekilde kilitleri elde etmek
için nasıl zorluklar sunduğunu açıklıyoruz. Bu metin için kaynak kodu
indirmesinde sağlanan işlem() Java uygulamasını kullanarak , kilitlerin sırayla
alınması için Sys tem.identityHashCode() yöntemini kullanarak değiştirin.

Programlama Projeleri

Bankacı Algoritması
Bu proje için, Bölüm 8.6.3'te tartışılan bankacı algoritmasını uygulayan bir program
yazacaksınız. Müşteriler bankadan kaynakları talep eder ve serbest bırakır. Bankacı,
yalnızca sistemden güvenli bir durumda çıkarsa bir talepte bulunacaktır. Sistemi
güvenli olmayan bir durumda bırakan bir istek reddedilecektir.
Bu projeyi açıklayan kod örnekleri C'de gösterilmiş olsa da, Java kullanarak da bir
çözüm geliştirebilirsiniz.

Bankacı

Bankacı , Bölüm 8.6.3'te ana hatlarıyla belirtildiği gibi, m kaynak türü için n
müşteriden gelen talepleri değerlendirecektir . Bankacı, aşağıdaki veri yapılarını
kullanarak kaynakları takip edecektir:

#define MÜŞTERİ SAYISI 5 #define KAYNAK SAYISI 4

/* her kaynağın kullanılabilir miktarı */ int kullanılabilir[KAYNAK


SAYISI];

/*her müşterinin maksimum talebi */ int


maksimum[NUMBER OF CUSTOMERS][NUMBER OF KAYNAK];

/* şu anda her müşteriye tahsis edilen miktar */ int tahsisi[NUMBER OF


CUSTOMERS][NUMBER OF KAYNAK];

/* her müşterinin kalan ihtiyacı */ int ihtiyaç[MÜŞTERİ


SAYISI][KAYNAK SAYISI];
Machine Translated by Google

Programlama Projeleri P-46

Bankacı, Bölüm 8.6.3.1'de özetlenen güvenlik algoritmasını karşılaması halinde bir


talebi yerine getirecektir. Bir talep sistemi güvenli bir durumda bırakmazsa, bankacı
bunu reddeder. Kaynakları istemek ve serbest bırakmak için işlev prototipleri aşağıdaki
gibidir:

int istek kaynakları(int müşteri numarası, int istek[]);

void yayın kaynakları(int müşteri numarası, int yayın[]);

request Resources() işlevi başarılı olursa 0 , başarısız olursa –1 döndürmelidir.

Uygulamanızı Test Etme

Kullanıcının etkileşimli olarak kaynaklar için bir istek girmesine, kaynakları serbest
bırakmasına veya bankacının algoritmasıyla kullanılan farklı veri yapılarının (mevcut,
maksimum, tahsis ve ihtiyaç) değerlerini çıkarmasına izin veren bir program
tasarlayın.
Komut satırında her türden kaynak sayısını ileterek programınızı çağırmalısınız.
Örneğin, birinci türden on, ikinci türden beş, üçüncü türden yedi ve dördüncü türden
sekiz örnekle dört kaynak türü olsaydı, programınızı aşağıdaki gibi çağırırdınız:

./a.out 10 5 7 8

Kullanılabilir dizi bu değerlere başlatılacaktır.


Programınız başlangıçta her müşteri için maksimum sayıda istek içeren bir
dosyada okuyacaktır. Örneğin, beş müşteri ve dört kaynak varsa, girdi dosyası
aşağıdaki gibi görünür:

6,4,7,3
4,2,3,2
2,5,3,3
6,3,3,2
5,6,7,5

burada girdi dosyasındaki her satır, her müşteri için her kaynak türünün maksimum
talebini temsil eder. Programınız maksimum diziyi bu değerlere başlatacaktır.

Programınız daha sonra kullanıcının bir kaynak talebine, kaynakların serbest


bırakılmasına veya farklı veri yapılarının mevcut değerlerine yanıt veren komutları
girmesini sağlayacaktır. Kaynak istemek için 'RQ' , kaynakları serbest bırakmak için
'RL' ve farklı veri yapılarının değerlerini çıktılamak için '*' komutunu kullanın .
Örneğin, müşteri 0 kaynakları (3, 1, 2, 1) talep ederse, aşağıdaki komut girilecektir:

RQ 0 3 1 2 1
Programınız daha sonra, Bölüm 8.6.3.1'de belirtilen güvenlik algoritmasını kullanarak
talebin karşılanıp karşılanmayacağını veya reddedileceğini bildirir.
Machine Translated by Google

P-47 Bölüm 8 Kilitlenmeler

Benzer şekilde, müşteri 4 kaynakları (1, 2, 3, 1) serbest bırakırsa, kullanıcı


aşağıdaki komutu girer:
RL 4 1 2 3 1

Son olarak, '*' komutu girilirse, programınız kullanılabilir, maksimum, tahsis ve


ihtiyaç dizilerinin değerlerini verir.
Machine Translated by Google

Dördüncü Bölüm

Hafıza
Yönetmek
Bir bilgisayar sisteminin temel amacı programları yürütmektir. Bu programlar,
eriştikleri verilerle birlikte yürütme sırasında en azından kısmen ana bellekte
olmalıdır.
Modern bilgisayar sistemleri, sistem yürütme sırasında birkaç işlemi bellekte
tutar. Çeşitli yaklaşımları yansıtan birçok bellek yönetimi şeması mevcuttur ve her
algoritmanın etkinliği duruma göre değişir. Bir sistem için bellek yönetimi
şemasının seçimi, özellikle sistemin donanım tasarımı olmak üzere birçok faktöre
bağlıdır. Çoğu algoritma, bir tür donanım desteği gerektirir.
Machine Translated by Google
Machine Translated by Google

9 BÖLÜM

Ana hafıza
Bölüm 5'te CPU'nun bir dizi işlem tarafından nasıl paylaşılabileceğini gösterdik.
CPU programlamanın bir sonucu olarak , hem CPU kullanımını hem de
bilgisayarın kullanıcılarına yanıt verme hızını iyileştirebiliriz . Ancak
performanstaki bu artışı gerçekleştirmek için birçok işlemi hafızada tutmalıyız,
yani hafızayı paylaşmalıyız.
Bu bölümde, belleği yönetmenin çeşitli yollarını tartışacağız. Bellek
yönetimi algoritmaları, ilkel bir çıplak makine yaklaşımından sayfalama
kullanan bir stratejiye kadar değişir. Her yaklaşımın kendine göre avantajları
ve dezavantajları vardır. Belirli bir sistem için bellek yönetimi yönteminin
seçimi, özellikle sistemin donanım tasarımı gibi birçok faktöre bağlıdır.
Göreceğimiz gibi, çoğu algoritma donanım desteği gerektirir, bu da birçok
sistemin donanım ve işletim sistemi bellek yönetimini yakından entegre
etmesine neden olur.

BÖLÜM HEDEFLERİ

• Mantıksal ve fiziksel adres arasındaki farkı ve adres çevirmede bellek yönetim


biriminin (MMU) rolünü açıklayın . • Bellek bitişiklerini ayırmak için ilk, en iyi
ve en kötü uyan stratejilerini uygulayın
kesinlikle.

• Dahili ve harici parçalanma arasındaki farkı açıklayın. • Bir çeviri


arabelleği (TLB) içeren bir sayfalama sisteminde mantıksal adresleri fiziksel
adreslere çevirin. • Hiyerarşik sayfalama, karma sayfalama ve ters çevrilmiş
sayfa tablolarını tanımlayın. • IA-32, x86-64 ve ARMv8 mimarileri için adres
çevirisini tanımlayın .

9.1 Arka Plan

Bölüm 1'de gördüğümüz gibi, bellek, modern bir bilgisayar sisteminin


işleyişinin merkezinde yer alır. Bellek, her biri kendi adresine sahip geniş bir
bayt dizisinden oluşur. CPU , komutun değerine göre komutları bellekten alır.
349
Machine Translated by Google

350 Bölüm 9 Ana Bellek

program sayacı. Bu talimatlar, belirli bellek adreslerinden ek yüklemeye ve bu


adreslere depolamaya neden olabilir.
Örneğin, tipik bir talimat yürütme döngüsü, önce bellekten bir talimat getirir.
Talimat daha sonra kodu çözülür ve işlenenlerin bellekten alınmasına neden olabilir.
Komut işlenenlerde yürütüldükten sonra, sonuçlar bellekte saklanabilir. Bellek birimi
yalnızca bellek adresleri akışını görür; bunların nasıl oluşturulduğunu (talimat
sayacı, dizin oluşturma, dolaylı adresler, değişmez adresler vb. tarafından) veya ne
için olduklarını (talimatlar veya veriler) bilmez. Buna göre, bir programın nasıl bir
bellek adresi oluşturduğunu görmezden gelebiliriz . Yalnızca çalışan program
tarafından oluşturulan bellek adresleri dizisiyle ilgileniyoruz.

Tartışmamıza belleği yönetmeyle ilgili birkaç konuyu ele alarak başlıyoruz:


temel donanım, sembolik (veya sanal) bellek adreslerinin gerçek fiziksel adreslere
bağlanması ve mantıksal ve fiziksel adresler arasındaki ayrım. Bölümü, dinamik
bağlantı ve paylaşılan kitaplıkların tartışılmasıyla sonlandırıyoruz.

9.1.1 Temel Donanım


Ana bellek ve her bir işlem çekirdeğinde yerleşik olan kayıtlar, CPU'nun doğrudan
erişebileceği tek genel amaçlı depolamadır. Argüman olarak bellek adreslerini alan
makine yönergeleri vardır, ancak hiçbiri disk adreslerini almaz. Bu nedenle,
yürütülmekte olan herhangi bir talimat ve talimatlar tarafından kullanılan herhangi
bir veri, bu doğrudan erişimli depolama cihazlarından birinde olmalıdır. Veriler
bellekte değilse, CPU'nun üzerlerinde işlem yapabilmesi için önce oraya taşınmaları
gerekir .
Her CPU çekirdeğinde yerleşik olan kayıtlara genellikle CPU saatinin bir
döngüsü içinde erişilebilir . Bazı CPU çekirdekleri, talimatların kodunu çözebilir ve
saat işareti başına bir veya daha fazla işlem hızında kayıt içeriği üzerinde basit
işlemler gerçekleştirebilir. Aynı şey, bellek veriyolundaki bir işlem aracılığıyla erişilen
ana bellek için söylenemez. Bir bellek erişiminin tamamlanması, CPU saatinin birçok
çevrimini alabilir . Bu gibi durumlarda, yürüttüğü talimatı tamamlamak için gereken
verilere sahip olmadığı için işlemcinin normal olarak durması gerekir. Bu durum,
bellek erişimlerinin sıklığı nedeniyle dayanılmazdır. Çözüm, CPU ile ana bellek
arasına, hızlı erişim için tipik olarak CPU yongasına hızlı bellek eklemektir . Böyle bir
önbellek Bölüm 1.5.5'te açıklanmıştır. CPU'da yerleşik bir önbelleği yönetmek için
donanım, herhangi bir işletim sistemi kontrolü olmaksızın bellek erişimini otomatik
olarak hızlandırır. (Bölüm 5.5.2'den, bellek durması sırasında çok iş parçacıklı bir
çekirdeğin, durdurulan donanım iş parçacığından başka bir donanım iş
parçacığına geçebileceğini hatırlayın.)
Yalnızca fiziksel belleğe erişmenin göreceli hızıyla ilgilenmiyoruz, aynı zamanda
doğru çalışmayı da sağlamalıyız. Sistemin düzgün çalışması için, işletim sistemini
kullanıcı süreçlerinin erişimine karşı korumamız ve ayrıca kullanıcı işlemlerini
birbirinden korumamız gerekir. Bu koruma donanım tarafından sağlanmalıdır,
çünkü işletim sistemi genellikle CPU ile bellek erişimleri arasına müdahale etmez
(sonuçta ortaya çıkan performans cezası nedeniyle). Donanım, bölüm boyunca
gösterdiğimiz gibi, bu üretimi birkaç farklı şekilde uygular. Burada, olası bir
uygulamayı özetliyoruz.
Machine Translated by Google

9.1 Arka Plan 351

1024000
işletim
sistemi
880000

işlem

420940 taban + sınır

işlem

300040
temel

işlem

256000

Şekil 9.1 Bir taban ve bir limit kaydı, mantıksal bir adres alanı tanımlar.

Öncelikle her işlemin ayrı bir bellek alanına sahip olduğundan emin olmamız gerekir.
İşlem başına ayrı bellek alanı, işlemleri birbirinden korur ve aynı anda yürütme için
belleğe yüklenen birden çok işlemin olması için esastır. Bellek alanlarını ayırmak için,
işlemin erişebileceği yasal adres aralığını belirleme ve işlemin yalnızca bu yasal adreslere
erişebilmesini sağlama yeteneğine ihtiyacımız var. Bu korumayı Şekil 9.1'de gösterildiği
gibi genellikle bir taban ve bir sınır olmak üzere iki kayıt kullanarak sağlayabiliriz.

Temel kayıt , en küçük yasal fiziksel bellek adresini tutar; limit kaydı , aralığın boyutunu
belirtir. Örneğin, temel kayıt 300040'a sahipse ve sınır kaydı 120900 ise, program yasal
olarak 300040 ila 420939 (dahil) arasındaki tüm adreslere erişebilir.

Bellek alanının korunması, CPU donanımının kullanıcı modunda oluşturulan her


adresi kayıtlarla karşılaştırmasını sağlayarak gerçekleştirilir. Kullanıcı modunda çalışan
bir programın işletim sistemi belleğine veya diğer kullanıcıların belleğine erişmeye
yönelik herhangi bir girişimi, işletim sistemine bir tuzak kurulmasına neden olur ve bu,
girişimi önemli bir hata olarak değerlendirir (Şekil 9.2). Bu şema, bir kullanıcı programının
(yanlışlıkla veya kasıtlı olarak) işletim sisteminin veya diğer kullanıcıların kod veya veri
yapılarını değiştirmesini önler.
Taban ve limit kayıtları, yalnızca özel bir ayrıcalıklı talimat kullanan işletim sistemi
tarafından yüklenebilir. Ayrıcalıklı komutlar yalnızca çekirdek modunda yürütülebildiğinden
ve yalnızca işletim sistemi çekirdek modunda yürütüldüğünden, yalnızca işletim sistemi
taban ve sınır yazmaçlarını yükleyebilir.
Bu şema, işletim sisteminin kayıtların değerini değiştirmesine izin verir, ancak kullanıcı
programlarının kayıtların içeriğini değiştirmesini engeller.
Çekirdek modunda çalışan işletim sistemine hem işletim sistemi belleğine hem de
kullanıcı belleğine sınırsız erişim verilir. Bu hüküm, işletim sisteminin kullanıcı
programlarını kullanıcı belleğine yüklemesine, hata durumunda bu programları dışarı
atmasına, sistem çağrılarının parametrelerine erişmesine ve bunları değiştirmesine ,
kullanıcı belleğine ve belleğinden G/Ç gerçekleştirmesine ve birçok işlev sağlamasına
izin verir. diğer servisler. Örneğin, bir işletim sisteminin bir
Machine Translated by Google

352
Bölüm 9 Ana Bellek

temel taban + sınır

adres evet evet


İşlemci
<
hayır hayır

işletim sistemine tuzak yasadışı


adresleme hatası hafıza

Şekil 9.2 Taban ve limit kayıtları ile donanım adres koruması.

çoklu işlem sistemi, bir sonraki işlemin içeriğini ana bellekten kayıtlara yüklemeden
önce, bir işlemin durumunu kayıtlardan ana belleğe depolayarak bağlam
anahtarlarını yürütmelidir.

9.1.2 Adres Bağlama


Genellikle, bir program bir diskte ikili yürütülebilir dosya olarak bulunur. Çalıştırmak
için, programın belleğe alınması ve mevcut bir CPU üzerinde yürütülmeye uygun
hale geldiği bir süreç (Bölüm 2.5'te açıklandığı gibi) bağlamına yerleştirilmesi
gerekir. İşlem yürütülürken, bellekten talimatlara ve verilere erişir. Sonunda süreç
sona erer ve belleği diğer süreçler tarafından kullanılmak üzere geri alınır.

Çoğu sistem, bir kullanıcı işleminin fiziksel belleğin herhangi bir bölümünde
kalmasına izin verir. Bu nedenle, bilgisayarın adres alanı 00000'den başlasa da,
kullanıcı işleminin ilk adresinin 00000 olması gerekmez. Daha sonra işletim sisteminin
bir işlemi fiziksel belleğe gerçekte nasıl yerleştirdiğini göreceksiniz.
Çoğu durumda, bir kullanıcı programı yürütülmeden önce, bazıları isteğe bağlı
olabilen birkaç adımdan geçer (Şekil 9.3). Bu adımlar sırasında adresler farklı
şekillerde gösterilebilir. Kaynak programdaki adresler genellikle semboliktir
(değişken sayısı gibi). Bir derleyici tipik olarak bu sembolik adresleri yeniden
yerleştirilebilir adreslere bağlar ("bu modülün başlangıcından itibaren 14 bayt" gibi).
Bağlayıcı veya yükleyici (bkz. Bölüm 2.5), yeri değiştirilebilen adresleri mutlak
adreslere (74014 gibi) bağlar. Her bağlama, bir adres alanından diğerine bir
eşlemedir.
Klasik olarak, komutların ve verilerin bellek adreslerine bağlanması,
yol boyunca herhangi bir adımda yapılabilir:

• Derleme zamanı. Derleme zamanında işlemin bellekte nerede kalacağını


biliyorsanız, mutlak kod oluşturulabilir. Örneğin, bir kullanıcı işleminin R
konumundan başlayacağını biliyorsanız , oluşturulan derleyici kodu o konumdan
başlayacak ve oradan yukarıya doğru genişleyecektir. Daha sonra başlangıç
konumu değişirse, bu kodu yeniden derlemek gerekecektir.
Machine Translated by Google

9.1 Arka Plan 353

kaynak

program

Derleme
derleyici
zamanı

nesne
dosyası
başka

nesne
dosyaları

bağlayıcı

yük

çalıştırılabilir zaman

dosya

yükleyici
dinamik olarak
bağlantılı

kitaplıklar
uygulamak
bellekteki
zaman
program
(çalışma zamanı)

Şekil 9.3 Bir kullanıcı programının çok adımlı işlenmesi.

• Yükleme süresi. Derleme zamanında işlemin bellekte nerede kalacağı bilinmiyorsa,


derleyicinin yeri değiştirilebilen kod oluşturması gerekir. Bu durumda, son
bağlama yükleme süresine kadar ertelenir. Başlangıç adresi değişirse, bu
değiştirilen değeri dahil etmek için yalnızca kullanıcı kodunu yeniden
yüklememiz gerekir. • Yürütme süresi. İşlem yürütülürken bir bellek bölümünden
diğerine taşınabilirse, bağlama çalışma zamanına kadar ertelenmelidir.
Bölüm 9.1.3'te tartışılacağı gibi, bu şemanın çalışması için özel donanım
mevcut olmalıdır. Çoğu işletim sistemi bu yöntemi kullanır.

Bu bölümün büyük bir kısmı, bu çeşitli bağlamaların bir bilgisayar sisteminde nasıl
etkin bir şekilde uygulanabileceğini göstermeye ve uygun donanım desteğini
tartışmaya ayrılmıştır.

9.1.3 Fiziksel Adres Alanına Karşı Mantıksal

CPU tarafından oluşturulan bir adrese genellikle mantıksal adres denir, oysa bellek
birimi tarafından görülen bir adres, yani, bir adrese yüklenen adres.
Machine Translated by Google

354 Bölüm 9 Ana Bellek

fiziksel
mantıksal adres adres
fiziksel
İşlemci MMU
hafıza

Şekil 9.4 Bellek yönetim birimi (MMU).

belleğin bellek adres kaydı —genel olarak fiziksel adres olarak adlandırılır.

Derleme veya yükleme zamanındaki bağlama adresleri, aynı mantıksal ve


fiziksel adresleri oluşturur. Ancak, yürütme zamanı adres bağlama şeması, farklı
mantıksal ve fiziksel adreslerle sonuçlanır. Bu durumda, mantıksal adrese genellikle
sanal adres olarak atıfta bulunuruz. Bu metinde mantıksal adres ve sanal adresi
birbirinin yerine kullanıyoruz. Bir program tarafından oluşturulan tüm mantıksal
adreslerin kümesi, bir mantıksal adres alanıdır. Bu mantıksal adreslere karşılık gelen
tüm fiziksel adreslerin kümesi, bir fiziksel adres alanıdır. Bu nedenle, yürütme
zamanı adres bağlama şemasında, mantıksal ve fiziksel adres alanları farklıdır.

Sanal adreslerden fiziksel adreslere çalışma zamanı eşlemesi, bellek yönetim


birimi (MMU) adı verilen bir donanım aygıtı tarafından yapılır (Şekil 9.4).
Bölüm 9.2'den Bölüm 9.3'e kadar tartıştığımız gibi, bu tür haritalamayı
gerçekleştirmek için birçok farklı yöntem arasından seçim yapabiliriz. Şimdilik, bu
eşlemeyi Bölüm 9.1.1'de açıklanan temel kayıt şemasının bir genellemesi olan basit
bir MMU şemasıyla gösteriyoruz. Temel kayıt, artık bir yer değiştirme kaydı olarak
adlandırılmaktadır. Yer değiştirme kaydındaki değer, adres belleğe gönderildiğinde
bir kullanıcı işlemi tarafından oluşturulan her adrese eklenir (bkz. Şekil 9.5). Örneğin,
baz 14000'deyse, kullanıcı tarafından konum 0'a yönelik bir girişim, dinamik olarak
konum 14000'e yeniden konumlandırılır; 346 konumuna bir erişim, 14346 konumuna
eşlenir.
Kullanıcı programı hiçbir zaman gerçek fiziksel adreslere erişmez. Program,
konum 346 için bir işaretçi oluşturabilir, onu bellekte saklayabilir, değiştirebilir ve
diğer adreslerle karşılaştırabilir - hepsi 346 sayısı olarak. Yalnızca bir bellek adresi
olarak kullanıldığında (belki dolaylı bir yüklemede veya depoda) ) temel kayıt
defterine göre yeniden konumlandırıldı mı? Kullanıcı programı mantıksal adreslerle
ilgilenir. Bellek eşleme donanımı, mantıksal adresleri fiziksel adreslere dönüştürür.
Bu yürütme zamanı bağlama biçimi, Bölüm 9.1.2'de tartışılmıştır. Başvurulan bir
bellek adresinin son konumu, başvuru yapılıncaya kadar belirlenmez.

Artık iki farklı adres tipimiz var: mantıksal adresler (0 ila maksimum aralığında)
ve fiziksel adresler ( bir temel değer R için R + 0 ila R + max aralığında ). Kullanıcı
programı yalnızca mantıksal adresler üretir ve işlemin 0'dan maksimuma kadar olan
bellek konumlarında çalıştığını düşünür. Ancak, bu mantıksal adresler kullanılmadan
önce fiziksel adreslerle eşlenmelidir. bu
Machine Translated by Google

9.1 Arka Plan 355

Şekil 9.5 Bir yer değiştirme kaydı kullanarak dinamik yer değiştirme.

Ayrı bir fiziksel adres alanına bağlı mantıksal adres alanı kavramı, uygun bellek
yönetiminin merkezinde yer alır.

9.1.4 Dinamik Yükleme Buraya


kadarki tartışmamızda, işlemin yürütülmesi için tüm programın ve bir işlemin
tüm verilerinin fiziksel bellekte olması gerekliydi. Bir işlemin boyutu bu nedenle
fiziksel belleğin boyutuyla sınırlandırılmıştır. Daha iyi bellek alanı kullanımı elde
etmek için dinamik yüklemeyi kullanabiliriz. Dinamik yükleme ile bir rutin
çağrılana kadar yüklenmez. Tüm rutinler, yeniden yerleştirilebilir bir yükleme
biçiminde diskte tutulur. Ana program belleğe yüklenir ve yürütülür. Bir rutinin
başka bir rutini çağırması gerektiğinde, çağıran rutin önce diğer rutinin
yüklenip yüklenmediğini kontrol eder. Değilse, istenen rutini belleğe yüklemek
ve programın adres tablolarını bu değişikliği yansıtacak şekilde güncellemek
için yeniden konumlandırılabilir bağlantı yükleyicisi çağrılır. Ardından kontrol,
yeni yüklenen rutine geçirilir.
Dinamik yüklemenin avantajı, bir rutinin yalnızca ihtiyaç duyulduğunda
yüklenmesidir. Bu yöntem, hata rutinleri gibi seyrek olarak meydana gelen
durumları işlemek için büyük miktarda kod gerektiğinde özellikle yararlıdır.
Böyle bir durumda, toplam program boyutu büyük olsa da, kullanılan (ve
dolayısıyla yüklenen) kısım çok daha küçük olabilir.
Dinamik yükleme, işletim sisteminden özel destek gerektirmez. Programlarını
böyle bir yöntemden yararlanmak için tasarlamak kullanıcıların
sorumluluğundadır. Ancak işletim sistemleri, dinamik yüklemeyi uygulamak
için kitaplık rutinleri sağlayarak programcıya yardımcı olabilir.

9.1.5 Dinamik Bağlantı ve Paylaşılan Kitaplıklar


Dinamik olarak bağlantılı kitaplıklar (DLL'ler) , programlar çalıştırıldığında
kullanıcı programlarına bağlanan sistem kitaplıklarıdır (Şekil 9.3'e bakın). Bazı
işletim sistemleri, yalnızca sistem kitaplıklarının işlendiği statik bağlantıyı destekler.
Machine Translated by Google

356 Bölüm 9 Ana Bellek


diğer nesne modülleri gibi ve yükleyici tarafından ikili program görüntüsünde
birleştirilir. Dinamik bağlama, aksine, dinamik yüklemeye benzer.
Ancak burada yükleme yerine bağlama, yürütme zamanına kadar ertelenir.
Bu özellik genellikle standart C dil kitaplığı gibi sistem kitaplıklarında kullanılır. Bu
olanak olmadan, sistemdeki her program, yürütülebilir görüntüde kendi dil kitaplığının
(veya en azından program tarafından başvurulan rutinlerin) bir kopyasını içermelidir.
Bu gereksinim, yalnızca yürütülebilir bir görüntünün boyutunu artırmakla kalmaz, aynı
zamanda ana belleği boşa harcayabilir. DLL'lerin ikinci bir avantajı, bu kitaplıkların
birden çok işlem arasında paylaşılabilmesidir, böylece DLL'nin yalnızca bir örneği ana
bellekte bulunur. Bu nedenle DLL'ler paylaşılan kitaplıklar olarak da bilinir ve Windows
ve Linux sistemlerinde yaygın olarak kullanılır.

Bir program dinamik kitaplıktaki bir yordama başvurduğunda, yükleyici DLL'yi


bulur ve gerekirse belleğe yükler. Ardından, dinamik kitaplıktaki işlevlere başvuran
adresleri, DLL'nin depolandığı bellekteki konuma ayarlar.

Dinamik olarak bağlantılı kitaplıklar, kitaplık güncellemelerine (hata düzeltmeleri


gibi) genişletilebilir. Ayrıca, bir kitaplık yeni bir sürümle değiştirilebilir ve kitaplığa
başvuran tüm programlar otomatik olarak yeni sürümü kullanır.
Dinamik bağlantı olmadan, yeni kitaplığa erişim kazanmak için bu tür tüm programların
yeniden bağlanması gerekir. Programların yanlışlıkla yeni, uyumsuz kitaplık sürümlerini
çalıştırmaması için sürüm bilgileri hem programa hem de kitaplığa dahil edilir. Bir
kitaplığın birden fazla sürümü belleğe yüklenebilir ve her program, kitaplığın hangi
kopyasının kullanılacağına karar vermek için sürüm bilgilerini kullanır. Küçük
değişikliklere sahip sürümler aynı sürüm numarasını korurken, büyük değişikliklere
sahip sürümler numarayı artırır. Bu nedenle, yalnızca yeni kitaplık sürümüyle derlenen
programlar, içindeki uyumsuz değişikliklerden etkilenir. Yeni kitaplık kurulmadan önce
bağlanan diğer programlar eski kitaplığı kullanmaya devam edecek.

Dinamik yüklemeden farklı olarak, dinamik bağlantı ve paylaşılan kitaplıklar


genellikle işletim sisteminden yardım gerektirir. Bellekteki işlemler birbirinden
korunuyorsa, işletim sistemi, gerekli rutinin başka bir işlemin bellek alanında olup
olmadığını kontrol edebilen veya birden çok işlemin aynı bellek adreslerine erişmesine
izin verebilen tek varlıktır.
Bölüm 9.3.4'te sayfalamayı tartışırken , bu kavramın yanı sıra DLL'lerin birden çok süreç
tarafından nasıl paylaşılabileceğini de detaylandırıyoruz.

9.2 Bitişik Bellek Tahsisi

Ana bellek hem işletim sistemini hem de çeşitli kullanıcı işlemlerini barındırmalıdır. Bu
nedenle, ana belleği mümkün olan en verimli şekilde tahsis etmemiz gerekiyor. Bu
bölüm, erken bir yöntem olan bitişik bellek tahsisini açıklar.

Bellek genellikle iki bölüme ayrılır: biri işletim sistemi ve diğeri kullanıcı işlemleri
için. İşletim sistemini düşük bellek adreslerine veya yüksek bellek adreslerine
yerleştirebiliriz. Bu karar, kesme vektörünün konumu gibi birçok faktöre bağlıdır.
Ancak birçok işletim sistemi (Linux ve Windows dahil) işletim sistemini yüksek belleğe
yerleştirir ve bu nedenle sadece bu durumu tartışıyoruz.
Machine Translated by Google

357
9.2 Bitişik Bellek Tahsisi

Genellikle birkaç kullanıcı işleminin aynı anda bellekte kalmasını isteriz. Bu


nedenle, belleğe getirilmeyi bekleyen işlemlere kullanılabilir belleğin nasıl tahsis
edileceğini düşünmemiz gerekir. Bitişik bellek tahsisinde, her işlem , bir sonraki
işlemi içeren bölüme bitişik olan tek bir bellek bölümünde bulunur. Bu bellek
ayırma şemasını daha fazla tartışmadan önce, bellek koruması konusunu ele
almalıyız.

9.2.1 Bellek Koruması


Daha önce tartışılan iki fikri birleştirerek, bir işlemin sahip olmadığı belleğe
erişmesini engelleyebiliriz. Eğer bir yer değiştirme kaydına (Bölüm 9.1.3) sahip bir
sistemimiz varsa, bir limit kaydı (Bölüm 9.1.1) ile birlikte hedefimize ulaşırız. Yer
değiştirme kaydı, en küçük fiziksel adresin değerini içerir; limit kaydı, mantıksal
adres aralığını içerir (örneğin, yer değiştirme = 100040 ve limit = 74600). Her
mantıksal adres, sınır kaydı tarafından belirtilen aralık içinde kalmalıdır. MMU , yer
değiştirme kaydındaki değeri ekleyerek mantıksal adresi dinamik olarak eşler. Bu
eşlenen adres belleğe gönderilir (Şekil 9.6).

CPU zamanlayıcı yürütme için bir süreç seçtiğinde, dağıtım programı içerik
anahtarının bir parçası olarak yer değiştirme ve limit kayıtlarını doğru değerlerle
yükler. Bir CPU tarafından üretilen her adres bu kayıtlara karşı kontrol edildiğinden,
hem işletim sistemini hem de diğer kullanıcıların programlarını ve verilerini bu
çalışan işlem tarafından değiştirilmekten koruyabiliriz.
Yer değiştirme-kayıt şeması, işletim sisteminin boyutunun dinamik olarak
değişmesine izin vermek için etkili bir yol sağlar. Bu esneklik birçok durumda arzu
edilir. Örneğin, işletim sistemi, aygıt sürücüleri için kod ve arabellek alanı içerir. Bir
aygıt sürücüsü şu anda kullanımda değilse, onu bellekte tutmanın pek bir anlamı
yoktur; bunun yerine, yalnızca gerektiğinde belleğe yüklenebilir. Aynı şekilde, aygıt
sürücüsüne artık ihtiyaç duyulmadığında kaldırılabilir ve belleği diğer ihtiyaçlar
için ayrılabilir.

limit yer
kaydı değiştirme kaydı

fiziksel
mantıksal adres evet adres
İşlemci < + hafıza

hayır

tuzak: adresleme hatası

Şekil 9.6 Yer değiştirme ve limit kayıtları için donanım desteği.


Machine Translated by Google

358
Bölüm 9 Ana Bellek
9.2.2 Bellek Tahsisi
Artık bellek ayırmaya geçmeye hazırız. Bellek ayırmanın en basit yöntemlerinden
biri, her bölümün tam olarak bir süreç içerebileceği bellekteki değişken
büyüklükteki bölümlere süreçler atamaktır. Bu değişken bölüm şemasında, işletim
sistemi, belleğin hangi bölümlerinin kullanılabilir olduğunu ve hangilerinin işgal
edildiğini gösteren bir tablo tutar. Başlangıçta, tüm bellek kullanıcı işlemleri için
kullanılabilir ve bir büyük kullanılabilir bellek bloğu, bir boşluk olarak kabul edilir.
Sonunda, göreceğiniz gibi, bellek çeşitli boyutlarda bir dizi delik içerir.

Şekil 9.7 bu şemayı göstermektedir. Başlangıçta, 5, 8 ve 2 işlemlerini içeren


bellek tamamen kullanılır. İşlem 8 çıktıktan sonra, bir bitişik delik vardır. Daha
sonra işlem 9 gelir ve bellek tahsis edilir. Ardından, bitişik olmayan iki delik ile
sonuçlanan 5 parçayı işleyin.
İşlemler sisteme girerken, işletim sistemi, hangi işlemlere bellek tahsis
edildiğini belirlerken her işlemin bellek gereksinimlerini ve kullanılabilir bellek alanı
miktarını dikkate alır. Bir işleme alan tahsis edildiğinde, belleğe yüklenir ve burada
CPU zamanı için rekabet edebilir. Bir işlem sona erdiğinde, işletim sisteminin daha
sonra başka bir işleme sağlayabileceği belleğini serbest bırakır.

Gelen bir sürecin taleplerini karşılamak için yeterli bellek olmadığında ne olur?
Seçeneklerden biri, süreci reddetmek ve uygun bir hata mesajı sağlamaktır.
Alternatif olarak, bu tür işlemleri bir bekleme kuyruğuna yerleştirebiliriz. Bellek
daha sonra serbest bırakıldığında, işletim sistemi bekleyen bir işlemin bellek
taleplerini karşılayıp karşılamayacağını belirlemek için bekleme kuyruğunu kontrol
eder.
Genel olarak, belirtildiği gibi, mevcut bellek blokları, bellek boyunca dağılmış
çeşitli boyutlarda bir dizi delik içerir. Bir işlem geldiğinde ve belleğe ihtiyaç
duyduğunda, sistem bu işlem için yeterince büyük bir delik için kümeyi arar. Delik
çok büyükse, iki parçaya bölünür. Bir kısım gelen işleme tahsis edilir; diğeri delik
kümesine döndürülür. Bir işlem sona erdiğinde, bellek bloğunu serbest bırakır ve
bu blok daha sonra delikler grubuna geri yerleştirilir. Yeni delik diğer deliklere
bitişikse, bu bitişik delikler daha büyük bir delik oluşturmak üzere birleştirilir.

Bu prosedür, bir serbest delikler listesinden n boyutundaki bir talebin nasıl


karşılanacağı ile ilgili genel dinamik depolama tahsis probleminin özel bir örneğidir.
Bu sorunun birçok çözümü var. İlk -uyum, en iyi-fi ve en kötü-fi stratejileri, mevcut,
deliklerden bir serbest delik seçmek için en yaygın olarak kullanılanlardır.

yüksek hafıza
işletim sistemi işletim sistemi işletim sistemi işletim sistemi

süreç 5 süreç 5 süreç 5


süreç 9 süreç 9
süreç 8

düşük
süreç 2 süreç 2 süreç 2 süreç 2
hafıza

Şekil 9.7 Değişken bölümü.


9.2 Bitişik Bellek Tahsisi 359
Machine Translated by Google

• İlk uyum. Yeterince büyük olan ilk deliği tahsis edin. Arama, ya delik setinin
başlangıcında ya da bir önceki ilk-uyum aramasının bittiği yerde başlayabilir. Yeterince
büyük bir serbest delik bulur bulmaz aramayı bırakabiliriz.

• En iyi fi . Yeterince büyük olan en küçük deliği tahsis edin. Liste boyuta göre
sıralanmadıkça, tüm listeyi aramalıyız. Bu strateji, en küçük kalan deliği üretir.

• En kötü uyum. En büyük deliği tahsis edin. Yine, boyuta göre sıralanmadıkça tüm listeyi
aramalıyız. Bu strateji, en uygun yaklaşımdan daha küçük artık delikten daha faydalı
olabilecek en büyük artık deliği üretir.

Simülasyonlar, azalan süre ve depolama kullanımı açısından hem ilk uyum hem de en
iyi uyumun en kötü uyumdan daha iyi olduğunu göstermiştir. Ne ilk uyum ne de en iyi
uyum, depolama kullanımı açısından diğerinden açıkça daha iyi değildir, ancak ilk uyum
genellikle daha hızlıdır.

9.2.3 Parçalanma

Bellek tahsisi için hem ilk uyum hem de en uygun stratejiler, harici parçalanmadan
muzdariptir . İşlemler yüklenip bellekten çıkarıldığında, boş bellek alanı küçük parçalara
bölünür. Bir isteği karşılamak için yeterli toplam bellek alanı olduğunda ancak kullanılabilir
alanlar bitişik olmadığında harici parçalanma vardır: depolama çok sayıda küçük deliğe
bölünür. Bu parçalanma sorunu ciddi olabilir. En kötü durumda, her iki işlem arasında bir
boş (veya boşa harcanmış) bellek bloğumuz olabilir. Bunun yerine tüm bu küçük bellek
parçaları tek bir büyük boş blokta olsaydı, birkaç işlem daha çalıştırabilirdik.

İlk-uyum ya da en-uygun stratejiyi kullanıp kullanmamamız parçalanma miktarını


etkileyebilir. (Bazı sistemler için ilk uyum daha iyiyken, diğerleri için en iyi uyum daha
iyidir.) Diğer bir faktör de serbest bloğun hangi ucunun tahsis edildiğidir. (Artık parça
hangisi - üstteki mi yoksa alttaki mi?) Bununla birlikte, hangi algoritma kullanılırsa kullanılsın,
harici parçalanma bir sorun olacaktır.
Toplam bellek depolama miktarına ve ortalama işlem boyutuna bağlı olarak, harici
parçalanma küçük veya büyük bir sorun olabilir. Örneğin, ilk uyumun istatistiksel analizi,
belirli bir optimizasyonla bile, tahsis edilmiş N blok verildiğinde, başka bir 0,5 N bloğun
parçalanma nedeniyle kaybedileceğini ortaya koymaktadır.
Yani, belleğin üçte biri kullanılamaz durumda olabilir! Bu özellik yüzde 50 kuralı olarak
bilinir .
Bellek parçalanması hem dahili hem de harici olabilir. 18.464 baytlık bir deliğe sahip
çok bölümlü bir tahsis şeması düşünün. Bir sonraki işlemin 18,462 bayt istediğini
varsayalım. Tam olarak istenen bloğu tahsis edersek, 2 baytlık bir boşlukla kalırız. Bu deliği
takip etmek için gereken ek yük, deliğin kendisinden önemli ölçüde daha büyük olacaktır.
Bu sorunu önlemeye yönelik genel yaklaşım, fiziksel belleği sabit boyutlu bloklara bölmek
ve belleği blok boyutuna göre birimler halinde tahsis etmektir. Bu yaklaşımla, bir işleme
ayrılan bellek, istenen bellekten biraz daha büyük olabilir. Bu iki sayı arasındaki fark, dahili
parçalanmadır - bir bölümün içindeki kullanılmayan bellek.
Machine Translated by Google

360 Bölüm 9 Ana Bellek

Dış parçalanma sorununa bir çözüm sıkıştırmadır. Amaç, tüm boş belleği
tek bir büyük blokta bir araya getirmek için bellek içeriğini karıştırmaktır.
Ancak sıkıştırma her zaman mümkün değildir. Yer değiştirme statik ise ve
montaj veya yükleme sırasında yapılıyorsa sıkıştırma yapılamaz. Yalnızca yer
değiştirme dinamikse ve yürütme zamanında yapılırsa mümkündür. Adresler
dinamik olarak yeniden yerleştirildiyse, yer değiştirme yalnızca programı ve
verileri taşımayı ve ardından yeni temel adresi yansıtacak şekilde temel kaydı
değiştirmeyi gerektirir. Sıkıştırma mümkün olduğunda, maliyetini belirlememiz
gerekir. En basit sıkıştırma algoritması, tüm süreçleri belleğin bir ucuna
taşımaktır; tüm delikler diğer yönde hareket ederek büyük bir kullanılabilir
bellek deliği oluşturur. Bu şema pahalı olabilir.
Dış parçalanma sorununa bir başka olası çözüm, işlemlerin mantıksal
adres alanının bitişik olmamasına izin vermek, böylece bir işleme, bu tür
belleğin bulunduğu her yerde fiziksel bellek tahsis edilmesine izin vermektir.
Bu, bilgisayar sistemleri için en yaygın bellek yönetimi tekniği olan sayfalamada
kullanılan stratejidir . Aşağıdaki bölümde sayfalamayı açıklıyoruz.
Parçalanma, veri bloklarını yönetmeniz gereken her yerde meydana
gelebilecek bilgi işlemde genel bir sorundur. Konuyu depolama yönetimi
bölümlerinde daha ayrıntılı tartışıyoruz (Bölüm 11 ila Bölüm 15).

9.3 Çağrı

Buraya kadar tartışılan bellek yönetimi, bir işlemin fiziksel adres alanının bitişik
olmasını gerektirmiştir. Şimdi , bir işlemin fiziksel adres alanının bitişik
olmamasına izin veren bir bellek yönetimi şeması olan sayfalamayı tanıtıyoruz.
Sayfalama, bitişik bellek tahsisini rahatsız eden iki sorun olan harici parçalanmayı
ve buna bağlı sıkıştırma ihtiyacını önler. Sayısız avantaj sunduğu için, çeşitli
biçimlerde sayfalama, büyük sunuculardan mobil cihazlara kadar çoğu işletim
sisteminde kullanılır.
Sayfalama, işletim sistemi ve bilgisayar donanımı arasındaki işbirliği ile
gerçekleştirilir.

9.3.1 Temel Yöntem


Sayfalamayı uygulamanın temel yöntemi, fiziksel belleği çerçeve adı verilen
sabit boyutlu bloklara ve mantıksal belleği sayfa adı verilen aynı boyuttaki
bloklara bölmeyi içerir. Bir işlem yürütüleceği zaman, sayfaları kaynaklarından
(bir dosya sistemi veya yedekleme deposu) mevcut herhangi bir bellek
çerçevesine yüklenir. Destek deposu, bellek çerçeveleri veya çoklu çerçeve
kümeleriyle aynı boyutta olan sabit boyutlu bloklara bölünmüştür. Bu oldukça
basit fikir, harika işlevselliğe ve geniş sonuçlara sahiptir. Örneğin, mantıksal
adres alanı artık fiziksel adres alanından tamamen ayrıdır, bu nedenle sistem
264 bayttan daha az fiziksel belleğe sahip olsa bile bir işlem mantıksal 64 bit
adres alanına sahip olabilir .
CPU tarafından oluşturulan her adres iki bölüme ayrılır: bir sayfa
sayı (p) ve sayfa ofseti (d):

sayfa numarası sayfa ofseti


p d
Machine Translated by Google

9.3 Çağrı 361

Şekil 9.8 Çağrı donanımı.

Sayfa numarası, işlem başına sayfa tablosunda bir dizin olarak kullanılır . Bu,
Şekil 9.8'de gösterilmektedir. Sayfa tablosu, fiziksel bellekteki her çerçevenin
temel adresini içerir ve ofset, başvurulan çerçevedeki konumdur.
Böylece çerçevenin temel adresi, fiziksel bellek adresini tanımlamak için sayfa
ofseti ile birleştirilir. Belleğin sayfalama modeli Şekil 9.9'da gösterilmektedir.

Aşağıda, MMU tarafından mantıksal bir metni çevirmek için atılan adımlar özetlenmektedir.
CPU tarafından fiziksel bir adrese oluşturulan adres:

1. Sayfa numarasını p çıkarın ve sayfa tablosuna bir dizin olarak kullanın.


2. Sayfa tablosundan ilgili çerçeve numarasını f çıkarın.
3. Mantıksal adresteki p sayfa numarasını çerçeve numarasıyla değiştirin
f.

Ofset d değişmediği için değiştirilmez ve çerçeve numarası ve ofset artık


fiziksel adresi oluşturur.
Sayfa boyutu (çerçeve boyutu gibi) donanım tarafından tanımlanır. Bir
sayfanın boyutu, bilgisayar mimarisine bağlı olarak tipik olarak sayfa başına 4
KB ile 1 GB arasında değişen 2 katıdır. Sayfa boyutu olarak 2 katının seçilmesi,
mantıksal bir adresin sayfa numarasına ve sayfa ofsetine çevrilmesini özellikle
kolaylaştırır. Mantıksal adres alanının boyutu 2m ve sayfa boyutu 2n bayt ise,
mantıksal adresin yüksek sıralı m n bitleri sayfa numarasını, n düşük sıralı
bitleri ise sayfa ofsetini belirtir. Böylece, mantıksal adres aşağıdaki gibidir:

sayfa numarası sayfa ofseti


p d

m-n n
Machine Translated by Google

362 Bölüm 9 Ana Bellek


çerçeve
numarası

sayfa 0 0
0 1
Sayfa 1 1 sayfa 0
1 4
2 3
sayfa 2 2
3 7

3. sayfa sayfa tablosu 3 sayfa 2

4 Sayfa 1
mantıksal bellek
5

7 3. sayfa

fiziksel
hafıza

Şekil 9.9 Mantıksal ve fiziksel belleğin sayfalama modeli.

burada p , sayfa tablosundaki bir dizindir ve d , sayfa içindeki yer değiştirmedir.

Somut (küçük de olsa) bir örnek olarak, Şekil 9.10'daki hafızayı ele alalım. Burada, mantıksal
adreste, n = 2 ve m = 4. 4 baytlık bir sayfa boyutu ve 32 baytlık bir fiziksel bellek (8 sayfa) kullanarak,
programcının bellek görünümünün fiziksel belleğe nasıl eşleştirilebileceğini gösteriyoruz.
Mantıksal adres 0, sayfa 0, ofset 0'dır. Sayfa tablosuna indeksleme, sayfa 0'ın çerçeve 5'te
olduğunu buluruz. Böylece, mantıksal adres 0, fiziksel adres 20 [= (5 × 4) + 0] ile eşlenir. Mantıksal
adres 3 (sayfa 0, ofset 3), fiziksel adres 23'e [= (5 × 4) + 3] eşlenir. Mantıksal adres 4, sayfa 1, ofset
0'dır; sayfa tablosuna göre, sayfa 1 çerçeve 6'ya eşlenir. Böylece mantıksal adres 4, fiziksel adres
24 [= (6 × 4) + 0] ile eşlenir. Mantıksal adres 13, fiziksel adres 9 ile eşleşir.

Sayfalamanın kendisinin bir dinamik yer değiştirme biçimi olduğunu fark etmiş olabilirsiniz.
Her mantıksal adres, disk belleği donanımı tarafından bazı fiziksel adreslere bağlıdır. Sayfalamayı
kullanmak, her bellek çerçevesi için bir tane olmak üzere, bir taban (veya yer değiştirme) kayıtları
tablosu kullanmaya benzer.
Bir sayfalama şeması kullandığımızda, harici parçalanma olmaz: herhangi bir boş çerçeve,
ihtiyacı olan bir işleme tahsis edilebilir. Ancak, bazı iç parçalanmalarımız olabilir. Çerçevelerin
birimler olarak tahsis edildiğine dikkat edin. Bir işlemin bellek gereksinimleri sayfa sınır dizileriyle
çakışmazsa, ayrılan son çerçeve tamamen dolu olmayabilir. Örneğin, sayfa boyutu 2.048 bayt
ise, 72.766 baytlık bir işlem için 35 sayfa artı 1.086 bayt gerekir.

36 çerçeve tahsis edilecektir, bu da 2.048 - 1.086 = 962 baytlık dahili parçalanma ile sonuçlanacaktır.
En kötü durumda, bir işlem n sayfa artı 1 bayta ihtiyaç duyar.
Neredeyse tüm çerçevenin dahili parçalanmasına neden olacak şekilde n + 1 çerçeve tahsis
edilecektir .
Machine Translated by Google

9.3 Çağrı 363

0 0
1 ab
2
3 CD
4 4
5 ef
0 5
6
7 1 6 ijkl
8 2 1 8 m
9 n
3 2
10
11 ghijkl sayfa tablosu operasyon

12 12
13 milyon

14 Ö
15 p

mantıksal bellek 16

20
ab
c
d
24
ef

gh
28

fiziksel hafıza

Şekil 9.10 4 baytlık sayfaları olan 32 baytlık bir bellek için sayfalama örneği.

İşlem boyutu sayfa boyutundan bağımsızsa, dahili parçalamanın işlem başına


ortalama yarım sayfa olmasını bekleriz. Bu düşünce, küçük sayfa boyutlarının arzu
edildiğini göstermektedir. Ancak, her sayfa tablosu girişinde ek yük söz konusudur
ve sayfaların boyutu arttıkça bu ek yük azalır. Ayrıca, aktarılan veri miktarı daha
büyük olduğunda disk G/Ç daha verimlidir (Bölüm 11). Genel olarak, süreçler, veri
kümeleri ve ana bellek büyüdükçe sayfa boyutları zaman içinde büyümüştür.
Günümüzde sayfalar genellikle 4 KB veya 8 KB boyutundadır ve bazı sistemler daha
da büyük sayfa boyutlarını destekler. Bazı CPU'lar ve işletim sistemleri birden çok
sayfa boyutunu bile destekler. Örneğin, x86-64 sistemlerinde Windows 10, 4 KB ve
2 MB sayfa boyutlarını destekler. Linux ayrıca iki sayfa boyutunu da destekler:
varsayılan sayfa boyutu (tipik olarak 4 KB) ve büyük sayfalar olarak adlandırılan
mimariye bağlı daha büyük sayfa boyutu .
Sıklıkla, 32 bit CPU'da her sayfa tablosu girişi 4 bayt uzunluğundadır, ancak bu
boyut da değişebilir. 32 bitlik bir giriş, 232 fiziksel sayfa çerçevesinden birine işaret
edebilir. Çerçeve boyutu 4 KB (212) ise, 4 bayt girişli bir sistem 244 bayt (veya 16 TB)
fiziksel belleği adresleyebilir. Burada, disk belleğine alınmış bir bellek sistemindeki
fiziksel belleğin boyutunun, bir işlemin maksimum mantıksal boyutundan tipik
olarak farklı olduğunu belirtmeliyiz. Sayfalamayı daha fazla keşfettikçe,
Machine Translated by Google

364 Bölüm 9 Ana Bellek

LINUX SİSTEMLERİNDE SAYFA BOYUTUNU ALMAK

Bir Linux sisteminde sayfa boyutu mimariye göre değişir ve sayfa


boyutunu elde etmenin birkaç yolu vardır. Bir yaklaşım getpagesize()
sistem çağrısını kullanmaktır . Başka bir strateji, komut satırına aşağıdaki
komutu girmektir:

getconf PAGESIZE

Bu tekniklerin her biri sayfa boyutunu bayt sayısı olarak döndürür.

sayfa tablosu girişlerinde tutulması gereken diğer bilgileri tanıtın. Bu bilgi, sayfa
çerçevelerini adreslemek için kullanılabilen bit sayısını azaltır. Bu nedenle, 32-bit
sayfa tablosu girişleri olan bir sistem, olası maksimumdan daha az fiziksel belleğe
hitap edebilir.
Sisteme yürütülecek bir işlem geldiğinde sayfalarla ifade edilen boyutu incelenir.
Sürecin her sayfası bir çerçeveye ihtiyaç duyar. Bu nedenle, işlem n sayfa
gerektiriyorsa, bellekte en az n çerçeve bulunmalıdır. Eğer n tane çerçeve mevcutsa,
bu gelen sürece tahsis edilirler. İşlemin ilk sayfası tahsis edilen çerçevelerden
birine yüklenir ve bu işlem için sayfa tablosuna çerçeve numarası konur. Sonraki
sayfa başka bir çerçeveye yüklenir, çerçeve numarası sayfa tablosuna konur ve bu
şekilde devam eder (Şekil 9.11).
Sayfalamanın önemli bir yönü, programcının belleğe bakış açısı ile gerçek
fiziksel bellek arasındaki net ayrımdır. Programcı, belleği yalnızca bu programı
içeren tek bir alan olarak görür. Aslında, kullanıcı programı fiziksel belleğe
dağılmıştır ve bu da

serbest çerçeve serbest çerçeve listesi


listesi 14 13 15
13 13 sayfa 1
18 20 15

14 14 sayfa 0

15 15

sayfa 0 16 sayfa 0 16
sayfa 1 sayfa 1
sayfa 2 17 sayfa 2 17
sayfa 3 sayfa 3
yeni süreç 18 yeni süreç 18 sayfa 2

19 0 14 19
1 13
2
20 18 3
20 20 sayfa 3

21 yeni süreç sayfası tablosu 21

(a) (b)

Şekil 9.11 Serbest çerçeveler (a) tahsis öncesi ve (b) tahsis sonrası.
9.3 Çağrı 365
Machine Translated by Google

diğer programlar. Programcının belleğe bakışı ile gerçek fiziksel bellek arasındaki
fark, adres çevirme donanımı tarafından uzlaştırılır. Mantıksal adresler fiziksel
adreslere çevrilir. Bu eşleme pingi programcıdan gizlenir ve işletim sistemi tarafından
kontrol edilir.
Kullanıcı işleminin tanım gereği sahip olmadığı belleğe erişemediğine dikkat edin.
Sayfa tablosunun dışında belleğe hitap etmenin bir yolu yoktur ve tablo yalnızca
işlemin sahip olduğu sayfaları içerir.
İşletim sistemi fiziksel belleği yönettiğinden, fiziksel belleğin tahsis
ayrıntılarının (hangi çerçevelerin ayrıldığı, hangi çerçevelerin mevcut olduğu,
toplam kaç çerçeve olduğu vb.) farkında olması gerekir. Bu bilgiler genellikle
çerçeve tablosu adı verilen sistem çapında tek bir veri yapısında tutulur. Çerçeve
tablosu, her bir fiziksel sayfa çerçevesi için, ikincisinin serbest mi yoksa tahsisli mi
olduğunu ve tahsis edilmişse, hangi işlemin (veya işlemlerin) hangi sayfasına
olduğunu gösteren bir girişe sahiptir.
Ek olarak, işletim sistemi, kullanıcı süreçlerinin kullanıcı alanında çalıştığının
farkında olmalıdır ve tüm mantıksal adreslerin fiziksel adresler üretecek şekilde
eşlenmesi gerekir. Bir kullanıcı bir sistem çağrısı yaparsa ( örneğin G/Ç yapmak
için) ve parametre olarak bir adres sağlarsa (örneğin bir arabellek), doğru fiziksel
adresi üretmek için bu adresin eşlenmesi gerekir. İşletim sistemi, talimat sayacının
ve kayıt içeriğinin bir kopyasını tuttuğu gibi, her işlem için sayfa tablosunun bir
kopyasını tutar. Bu kopya, işletim sisteminin mantıksal bir adresi fiziksel bir adresle
manuel olarak eşleştirmesi gerektiğinde, mantıksal adresleri fiziksel adreslere
çevirmek için kullanılır. Ayrıca, CPU'ya bir işlem tahsis edileceği zaman donanım
sayfa tablosunu tanımlamak için CPU gönderici tarafından kullanılır . Bu nedenle
sayfalama, bağlam değiştirme süresini artırır.

9.3.2 Donanım Desteği

Sayfa tabloları işlem başına veri yapıları olduğundan, sayfa tablosuna bir işaretçi,
her işlemin işlem kontrol bloğunda diğer kayıt değerleriyle (talimat işaretçisi gibi)
saklanır. CPU zamanlayıcı yürütme için bir süreç seçtiğinde, kullanıcı kayıtlarını ve
uygun donanım sayfa tablosu değerlerini saklanan kullanıcı sayfası tablosundan
yeniden yüklemesi gerekir.
Sayfa tablosunun donanım uygulaması birkaç yolla yapılabilir. En basit durumda,
sayfa tablosu, sayfa adresi çevirisini çok verimli kılan, atanmış yüksek hızlı donanım
kayıtları kümesi olarak uygulanır. Bununla birlikte, bu yaklaşım bağlam değiştirme
süresini artırır, çünkü bu kayıtların her birinin bir bağlam değiştirme sırasında
değiştirilmesi gerekir.
Sayfa tablosu oldukça küçükse (örneğin, 256 giriş) sayfa tablosu için kayıtların
kullanımı tatmin edicidir. Bununla birlikte, çoğu çağdaş CPU, çok daha büyük sayfa
tablolarını destekler (örneğin, 220 girdi). Bu makineler için, sayfa tablosunu
uygulamak için hızlı kayıtların kullanılması mümkün değildir. Bunun yerine, sayfa
tablosu ana bellekte tutulur ve bir sayfa tablosu taban kaydı (PTBR) sayfa tablosuna
işaret eder. Sayfa tablolarının değiştirilmesi, yalnızca bu kaydın değiştirilmesini
gerektirir, bu da bağlam değiştirme süresini önemli ölçüde azaltır.

9.3.2.1 Çeviri Görünümü Arabelleği

Sayfa tablosunu ana bellekte depolamak daha hızlı bağlam anahtarları sağlasa da,
daha yavaş bellek erişim süreleriyle de sonuçlanabilir. i konumuna erişmek
istediğimizi varsayalım . Önce içindeki değeri kullanarak sayfa tablosuna indekslemeliy
Machine Translated by Google

366 Bölüm 9 Ana Bellek


i için sayfa numarasına göre PTBR ofseti . Bu görev, bir bellek erişimi gerektirir.
Gerçek adresi üretmek için sayfa ofseti ile birleştirilen çerçeve numarasını bize
sağlar. Daha sonra hafızada istediğimiz yere ulaşabiliriz.
Bu şema ile, verilere erişmek için iki bellek erişimi gerekir (biri sayfa tablosu girişi
için ve diğeri gerçek veriler için). Bu nedenle, bellek erişimi, çoğu durumda
dayanılmaz olarak kabul edilen bir gecikme olan 2 faktörü kadar yavaşlar.
Bu sorunun standart çözümü, çeviriye bakma arabelleği (TLB) adı verilen özel,
küçük, hızlı aramalı bir donanım önbelleği kullanmaktır. TLB birleştirici , yüksek hızlı
bellektir. TLB'deki her giriş iki bölümden oluşur: bir anahtar (veya etiket) ve bir
değer. İlişkisel belleğe bir öğe sunulduğunda, öğe aynı anda tüm anahtarlarla
karşılaştırılır. Öğe bulunursa, yanıt veren değer alanı döndürülür. Arama hızlıdır;
modern donanımdaki bir TLB araması, talimat hattının bir parçasıdır ve esasen
performans cezası eklemez. Ancak aramayı bir ardışık düzen adımında
gerçekleştirebilmek için TLB'nin küçük tutulması gerekir. Genellikle 32 ila 1.024 giriş
boyutundadır. Bazı CPU'lar ayrı talimat ve veri adresi TLB'leri uygular. Bu, mevcut
TLB girişlerinin sayısını ikiye katlayabilir , çünkü bu aramalar farklı işlem hattı
adımlarında gerçekleşir. Bu gelişmede CPU teknolojisinin evriminin bir örneğini
görebiliriz: sistemler , tıpkı birden çok önbellek düzeyine sahip oldukları gibi, TLB'leri
olmamasından birden çok düzeyde TLB'ye sahip olmaya doğru evrilmiştir .

TLB , sayfa tablolarıyla aşağıdaki şekilde kullanılır. TLB , sayfa tablosu


girişlerinden yalnızca birkaçını içerir. CPU tarafından mantıksal bir adres
oluşturulduğunda , MMU önce sayfa numarasının TLB'de olup olmadığını kontrol
eder . Sayfa numarası bulunursa, çerçeve numarası hemen kullanılabilir ve belleğe
erişmek için kullanılır. Az önce bahsedildiği gibi, bu adımlar CPU içindeki talimat
hattının bir parçası olarak yürütülür ve sayfalama uygulamayan bir sisteme kıyasla
hiçbir performans cezası eklemez.
Sayfa numarası TLB'de değilse ( TLB eksik olarak bilinir ), adres çevirisi, sayfa
tablosuna bir bellek referansının yapılması gereken Bölüm 9.3.1'de gösterilen
adımları izleyerek ilerler. Çerçeve numarası elde edildiğinde bunu belleğe erişmek
için kullanabiliriz (Şekil 9.12). Ayrıca , bir sonraki referansta hızlı bir şekilde
bulunabilmeleri için TLB'ye sayfa numarası ve çerçeve numarasını ekliyoruz .

TLB zaten girişlerle doluysa , değiştirme için mevcut bir giriş seçilmelidir.
Değiştirme ilkeleri, en son kullanılandan (LRU) sıralı denemeye ve rastgeleye kadar
uzanır. Bazı CPU'lar , işletim sisteminin LRU girişinin değiştirilmesine katılmasına
izin verirken, diğerleri konuyu kendileri halleder.
Ayrıca, bazı TLB'ler belirli girişlerin kabloyla bağlanmasına izin verir , yani TLB'den
kaldırılamazlar . Tipik olarak, anahtar çekirdek kodu için TLB girişleri kablolanır.

Bazı TLB'ler , her TLB girişinde adres alanı tanımlayıcısını (ASID'ler) saklar . Bir
ASID , her işlemi benzersiz bir şekilde tanımlar ve bu işlem için adres alanı koruması
sağlamak için kullanılır. TLB sanal sayfa numaralarını çözümlemeye çalıştığında, o
anda çalışan işlemin ASID'sinin sanal sayfayla ilişkili ASID ile eşleşmesini sağlar.
ASID'ler eşleşmezse , deneme TLB kaçırma olarak değerlendirilir. Bir ASID , adres
alanı koruması sağlamanın yanı sıra, TLB'nin aynı anda birkaç farklı işlem için
girişleri içermesine izin verir . TLB ayrı ASID'leri desteklemiyorsa , her yeni sayfa
tablosu seçildiğinde (örneğin, her bağlam anahtarıyla), bir sonraki yürütme
işleminin
9.3 Çağrı 367
Machine Translated by Google

mantıksal adres
İşlemci
pd

sayfa çerçeve
numarası numarası

TLB isabeti
fiziksel
adres

f d
TLB

p
TLB özledim
f

fiziksel
hafıza

sayfa tablosu

Şekil 9.12 TLB ile çağrı donanımı.

yanlış çeviri bilgisi. Aksi takdirde, TLB , geçerli sanal adresleri içeren ancak önceki süreçten kalan
yanlış veya geçersiz fiziksel adresleri olan eski girdileri içerebilir.

İlgilenilen sayfa numarasının TLB'de bulunma yüzdesine isabet oranı denir . Örneğin yüzde
80'lik bir isabet oranı, istenen sayfa numarasını TLB'de zamanın yüzde 80'inde bulduğumuz
anlamına gelir . Belleğe erişmek 10 nanosaniye sürüyorsa, sayfa numarası TLB'deyken eşlenmiş
bellek erişimi 10 nanosaniye sürer . TLB'de sayfa numarasını bulamazsak, önce sayfa tablosu ve
çerçeve numarası (10 nanosaniye) için belleğe erişmeli, ardından toplam 20 nanosaniyelik
bellekte istenen bayta (10 nanosaniye) erişmeliyiz. (Bir sayfa tablosu aramasının yalnızca bir bellek
erişimi aldığını varsayıyoruz, ancak göreceğimiz gibi daha fazlasını gerektirebilir.) Etkin bellek
erişim süresini bulmak için , durumu olasılığına göre ağırlıklandırıyoruz:

etkin erişim süresi = 0,80 × 10 + 0,20 × 20 = 12


nanosaniye

Bu örnekte, ortalama bellek erişim süresinde (10 ila 12 nanosaniye) yüzde 20'lik bir yavaşlama
yaşıyoruz. Çok daha gerçekçi olan yüzde 99 isabet oranı için

etkin erişim süresi = 0,99 × 10 + 0,01 × 20 = 10,1


nanosaniye

Bu artan isabet oranı, erişim süresinde yalnızca yüzde 1'lik bir yavaşlama üretir.
Machine Translated by Google

368 Bölüm 9 Ana Bellek

Daha önce belirtildiği gibi, bugün CPU'lar birden fazla TLB düzeyi sağlayabilir.
Modern CPU'larda bellek erişim sürelerinin hesaplanması bu nedenle yukarıdaki
örnekte gösterilenden çok daha karmaşıktır. Örneğin, Intel Core i7 CPU , 128 girişli
L1 talimat TLB'sine ve 64 girişli L1 veri TLB'sine sahiptir. L1'de bir ıskalama durumunda,
L2 512 girişli TLB'deki girişi kontrol etmek CPU'nun altı çevrimini alır . L2'de bir kayıp,
CPU'nun yüzlerce döngü alabilen ilişkili çerçeve adresini bulmak için bellekteki sayfa
tablosu girişlerini gözden geçirmesi veya işi yapması için işletim sistemini kesmesi
gerektiği anlamına gelir.
Böyle bir sistemde sayfalama ek yükünün eksiksiz bir performans analizi, her TLB
katmanı hakkında yanlış oran bilgisi gerektirir. Bununla birlikte, yukarıdaki genel
bilgilerden, donanım özelliklerinin bellek performansı üzerinde önemli bir etkisi
olabileceğini ve işletim sistemi iyileştirmelerinin (sayfalama gibi) donanım
değişiklikleriyle sonuçlanabileceğini ve dolayısıyla donanım değişikliklerinden (ör.
TLB'ler). İsabet oranının TLB üzerindeki etkisini Bölüm 10'da daha ayrıntılı olarak
inceleyeceğiz.
TLB'ler bir donanım özelliğidir ve bu nedenle işletim sistemleri ve tasarımcıları
için çok az endişe verici görünmektedir. Ancak tasarımcının, donanım platformuna
göre değişen TLB'lerin işlevini ve özelliklerini anlaması gerekir . Optimal çalışma
için, belirli bir platform için bir işletim sistemi tasarımı, platformun TLB tasarımına
göre sayfalamayı gerçekleştirmelidir. Benzer şekilde, TLB tasarımındaki bir değişiklik
(örneğin, farklı nesil Intel CPU'lar arasında) , onu kullanan işletim sistemlerinin
sayfalama uygulamasında bir değişiklik gerektirebilir.

9.3.3 Koruma
Disk belleği ortamındaki bellek koruması, her bir çerçeveyle ilişkili koruma bitleri
tarafından gerçekleştirilir. Normalde bu bitler sayfa tablosunda tutulur.
Bir bit, okunacak -yazılacak veya salt okunur olarak bir sayfa tanımlayabilir.
Belleğe yapılan her başvuru, doğru çerçeve numarasını bulmak için sayfa
tablosundan geçer. Fiziksel adres hesaplanırken aynı zamanda, salt okunur bir
sayfaya yazma yapılmadığını doğrulamak için koruma bitleri kontrol edilebilir. Salt
okunur bir sayfaya yazma girişimi, işletim sisteminde bir donanım tuzağına (veya
bellek koruması ihlaline) neden olur.
Daha iyi bir koruma düzeyi sağlamak için bu yaklaşımı kolayca genişletebiliriz.
Salt okunur, okuma-yazma veya salt yürütme koruması sağlamak için donanım
oluşturabiliriz; veya her erişim türü için ayrı koruma bitleri sağlayarak bu erişimlerin
herhangi bir kombinasyonuna izin verebiliriz. Yasadışı girişimler işletim sistemine
hapsolacaktır.
Sayfa tablosundaki her girişe genellikle bir ek bit eklenir: geçerli-geçersiz bir bit.
Bu bit geçerli olarak ayarlandığında , ilişkili sayfa işlemin mantıksal adres alanındadır
ve bu nedenle yasal (veya geçerli) bir sayfadır. Bit geçersiz olarak ayarlandığında ,
sayfa işlemin mantıksal adres alanında olmaz. Geçersiz adresler, geçerli –geçersiz bit
kullanılarak yakalanır. İşletim sistemi, sayfaya erişime izin vermek veya vermemek
için her sayfa için bu biti ayarlar.
Örneğin, 14 bitlik bir adres alanına (0 ila 16383) sahip bir sistemde, yalnızca 0 ila
10468 arasındaki adresleri kullanması gereken bir programımız olduğunu varsayalım.
2 KB'lık bir sayfa boyutu verildiğinde, Şekilde gösterilen duruma sahibiz. 9.13. 0, 1, 2,
3, 4 ve 5. sayfalardaki adresler, sayfa tablosu aracılığıyla normal şekilde eşlenir.
Bununla birlikte, 6. veya 7. sayfalarda bir adres oluşturmaya yönelik herhangi bir girişim,
9.3 Çağrı 369
Machine Translated by Google

2 sayfa 0
çerçeve numarası geçerli-geçersiz bit
12.287
sayfa 5 3 Sayfa 1
10.468
0 2 v
sayfa 4 4 sayfa 2
1 3 v

2 4 v
3. sayfa 5
3 7 v

4 8 v 6
sayfa 2
5 9 v
Sayfa 1 6 0 i 7 3. sayfa

7 0 i
sayfa 0 8 sayfa 4
00000 sayfa tablosu
9 sayfa 5


sayfa n

Şekil 9.13 Bir sayfa tablosunda geçerli (v) veya geçersiz (i) bit.

valid –invalid bit geçersiz olarak ayarlanır ve bilgisayar işletim sistemine tuzak kurar
(geçersiz sayfa referansı).
Bu şemanın bir sorun yarattığına dikkat edin. Program yalnızca 10468 adresine
genişletildiğinden, bu adresin ötesindeki herhangi bir başvuru geçersizdir.
Ancak, sayfa 5'e yapılan referanslar geçerli olarak sınıflandırılır, bu nedenle 12287'ye
kadar olan adreslere erişim geçerlidir. Yalnızca 12288 ile 16383 arasındaki adresler
geçersizdir. Bu sorun, 2 KB'lık sayfa boyutunun bir sonucudur ve sayfalamanın dahili
parçalanmasını yansıtır.
Nadiren bir işlem tüm adres aralığını kullanır. Aslında, birçok işlem, kendilerine
sunulan adres alanının yalnızca küçük bir bölümünü kullanır. Bu durumlarda, adres
aralığındaki her sayfa için girişler içeren bir sayfa tablosu oluşturmak israf olur. Bu
tablonun çoğu kullanılmayacak, ancak değerli bellek alanını kaplayacaktır. Bazı
sistemler , sayfa tablosunun boyutunu belirtmek için bir sayfa tablosu uzunluk kaydı
(PTLR) biçiminde donanım sağlar . Bu değer, adresin işlem için geçerli aralıkta
olduğunu doğrulamak için her mantıksal adrese karşı kontrol edilir. Bu testin başarısız
olması, işletim sisteminde bir hata tuzağına neden olur.

9.3.4 Paylaşılan Sayfalar


Sayfalamanın bir avantajı, birden çok işlemin olduğu bir ortamda özellikle önemli olan
bir husus olan ortak kodu paylaşma olasılığıdır.
UNIX ve Linux'un birçok sürümü için sistem çağrı arabiriminin bir bölümünü sağlayan
standart C kitaplığını düşünün . Tipik bir Linux sisteminde, çoğu kullanıcı işlemi standart
C kitaplığı libc'yi gerektirir. Bir seçenek sahip olmaktır
Machine Translated by Google

370
Bölüm 9 Ana Bellek
her işlem kendi libc kopyasını adres alanına yükler. Bir sistemde 40 kullanıcı işlemi
varsa ve libc kitaplığı 2 MB ise, bunun için 80 MB bellek gerekir.

Ancak kod yeniden giriş koduysa , Şekil 9.14'te gösterildiği gibi paylaşılabilir.
Burada, standart C kitaplığı libc için sayfaları paylaşan üç süreç görüyoruz . (Şekil,
libc kitaplığının dört sayfa kapladığını gösterse de, gerçekte daha fazla yer kaplar.)
Yeniden giriş kodu, kendi kendini değiştirmeyen koddur: yürütme sırasında asla
değişmez. Böylece iki veya daha fazla işlem aynı kodu aynı anda çalıştırabilir. Her
işlemin, işlemin yürütülmesi için verileri tutmak için kendi kayıt kopyaları ve veri
deposu vardır. İki farklı süreç için veriler elbette farklı olacaktır. Standart C
kitaplığının yalnızca bir kopyasının fiziksel bellekte tutulması gerekir ve her kullanıcı
işlemi için sayfa tablosu libc'nin aynı fiziksel kopyasına eşlenir. Bu nedenle, 40 işlemi
desteklemek için kitaplığın yalnızca bir kopyasına ihtiyacımız var ve şimdi gereken
toplam alan 80 MB yerine 2 MB - önemli bir tasarruf!

libc gibi çalışma zamanı kitaplıklarına ek olarak , yoğun olarak kullanılan diğer
programlar da paylaşılabilir - derleyiciler, pencere sistemleri, veritabanı sistemleri vb.
Bölüm 9.1.5'te tartışılan paylaşılan kitaplıklar tipik olarak paylaşılan sayfalarla
uygulanır. Paylaşılabilir olması için kodun yeniden girişli olması gerekir. Paylaşılan
kodun salt okunur olması, kodun doğruluğuna bırakılmamalıdır; işletim sistemi bu
özelliği zorunlu kılmalıdır.

libc 1
0
3
libc 2
4
1 libc 4
6
libc 3
1
2
libc 4 ...

...
P 1 için sayfa 3 libc 1
libc 1
tablosu
3
libc 2 4 libc 2
süreç P 1
4
6
libc 3
5
1

libc 4 ...
6 libc 3

...
P 2 için sayfa
libc 1 tablosu
3 7
libc 2 süreç P
4 2

6 8
libc 3
1

libc 4 ... 9

...
P 3 için sayfa
tablosu
fiziksel hafıza

süreç P 3

Şekil 9.14 Bir sayfalama ortamında standart C kitaplığının paylaşımı.


Machine Translated by Google

9.4 Sayfa Tablosunun Yapısı 371

Bir sistemdeki süreçler arasında belleğin paylaşımı, Bölüm 4'te açıklanan bir
görevin adres alanının iş parçacıkları tarafından paylaşılmasına benzer.
Ayrıca, Bölüm 3'te paylaşılan belleği bir süreçler arası iletişim yöntemi olarak
tanımladığımızı hatırlayın. Bazı işletim sistemleri, paylaşılan sayfaları kullanarak
paylaşılan belleği uygular.
Belleği sayfalara göre düzenlemek, birkaç işlemin aynı fiziksel sayfaları paylaşmasına
izin vermenin yanı sıra sayısız fayda sağlar. Bölüm 10'da diğer bazı faydaları ele alıyoruz.

9.4 Sayfa Tablosunun Yapısı

Bu bölümde, hiyerarşik sayfalama, karma sayfa tabloları ve ters çevrilmiş sayfa tabloları
dahil olmak üzere sayfa tablosunu yapılandırmak için en yaygın tekniklerden bazılarını
keşfedeceğiz.

9.4.1 Hiyerarşik Çağrı

Çoğu modern bilgisayar sistemi, büyük bir mantıksal adres alanını (232 - 264) destekler.
Böyle bir ortamda, sayfa tablosunun kendisi aşırı derecede büyür. Örneğin, 32 bit
mantıksal adres alanına sahip bir sistem düşünün. Böyle bir sistemdeki sayfa boyutu 4
KB (212) ise, o zaman bir sayfa tablosu 1 milyondan fazla girişten oluşabilir (220 =
232/212). Her girişin 4 bayttan oluştuğunu varsayarsak, her işlem yalnızca sayfa tablosu
için 4 MB'a kadar fiziksel adres alanına ihtiyaç duyabilir. Açıkçası, sayfa tablosunu ana
bellekte bitişik olarak tahsis etmek istemeyiz. Bu sorunun basit bir çözümü, sayfa
tablosunu daha küçük parçalara bölmektir. Bu bölme işlemini birkaç şekilde
gerçekleştirebiliriz.
Bir yol, sayfa tablosunun kendisinin de sayfalandığı iki seviyeli bir sayfalama
algoritması kullanmaktır (Şekil 9.15). Örneğin, 32 bit mantıksal adres alanına ve 4 KB
sayfa boyutuna sahip sistemi yeniden ele alalım. Mantıksal bir adres, 20 bitten oluşan
bir sayfa numarasına ve 12 bitten oluşan bir sayfa ofsetine bölünür. Sayfa tablosunu
sayfaladığımız için, sayfa numarası ayrıca 10 bitlik bir sayfa numarasına ve 10 bitlik bir
sayfa uzaklığına bölünmüştür. Böylece, mantıksal bir adres aşağıdaki gibidir:

sayfa numarası sayfa ofseti


p1 p2 d

10 10 12

burada p1 dış sayfa tablosuna bir dizindir ve p2 , iç sayfa tablosunun sayfası içindeki yer
değiştirmedir. Bu mimari için adres-çeviri yöntemi Şekil 9.16'da gösterilmiştir. Adres
çevirisi, dış sayfa tablosundan içe doğru çalıştığından, bu şema, ileriye doğru eşlenmiş
sayfa tablosu olarak da bilinir .

64 bit mantıksal adres alanına sahip bir sistem için iki seviyeli bir sayfalama şeması
artık uygun değildir. Bu noktayı açıklamak için, böyle bir sistemdeki sayfa boyutunun
4 KB (212) olduğunu varsayalım . Bu durumda, sayfa tablosu en fazla 252 girişten
oluşur. İki seviyeli bir sayfalama şeması kullanırsak, iç sayfa tabloları uygun bir şekilde
bir sayfa uzunluğunda olabilir veya 210 adet 4 baytlık giriş içerebilir. Adresler şöyle
görünür:
372
Bölüm
Machine Translated by Google 9 Ana Bellek
0

1
1
• •
• •
• •
100
500
• •
• •
• •
100
500
• •
• •
• • •

708 •

• 708



dış sayfa 929 •
900
tablosu •



900 •

sayfa 929
sayfası tablosu



sayfa tablosu
hafıza

Şekil 9.15 İki seviyeli bir sayfa tablosu şeması.

dış sayfa iç sayfa telafi etmek

p1 p2 d
42 10 12

Dış sayfa tablosu 242 girişten veya 244 bayttan oluşur. Böyle büyük bir tablodan kaçınmanın
bariz yolu, dış sayfa tablosunu daha küçük parçalara bölmektir.
(Bu yaklaşım, ek esneklik ve verimlilik için bazı 32 bit işlemcilerde de kullanılır.)

Dış sayfa tablosunu çeşitli şekillerde bölebiliriz. Örneğin, bize üç seviyeli bir sayfalama
şeması vererek dış sayfa tablosunu sayfalandırabiliriz. Dış sayfa tablosunun standart boyutlu
sayfalardan (210 giriş veya 212 bayt) oluştuğunu varsayalım.
Bu durumda, 64 bitlik bir adres alanı hala göz korkutucudur:

2. dış sayfa dış sayfa iç sayfa telafi etmek

p1 p2 p3 d
32 10 10 12

Dış sayfa tablosu hala 234 bayt (16 GB) boyutundadır.


Bir sonraki adım, ikinci düzey dış sayfa tablosunun kendisinin de çağrıldığı, vb. dört
düzeyli bir sayfalama şeması olacaktır. 64-bit UltraSPARC , yedi düzey sayfalama gerektirir -
çok sayıda bellek erişimi -
Machine Translated by Google

9.4 Sayfa Tablosunun Yapısı 373

mantıksal adres
p1 p2 d

p1

p2

dış sayfa d
tablosu

sayfa
sayfası tablosu

Şekil 9.16 İki seviyeli 32 bitlik bir çağrı mimarisi için adres çevirisi.

her mantıksal adresi çevirmek için. Bu örnekte, 64 bit mimariler için hiyerarşik
sayfa tablolarının neden genellikle uygunsuz olarak değerlendirildiğini görebilirsiniz.

9.4.2 Karma Sayfa Tabloları


32 bitten büyük adres alanlarını işlemek için bir yaklaşım , karma değeri sanal
sayfa numarası olan karma bir sayfa tablosu kullanmaktır. Karma tablosundaki her
giriş, aynı konuma hash olan (çarpışmaları işlemek için) bağlantılı bir öğe listesi
içerir. Her öğe üç alandan oluşur: (1) sanal sayfa numarası, (2) eşlenen sayfa
çerçevesinin değeri ve (3) bağlantılı listedeki bir sonraki öğeye yönelik bir
işaretçi.
Algoritma şu şekilde çalışır: Sanal adresteki sanal sayfa numarası hash
tablosuna hashlenir. Sanal sayfa numarası, bağlantılı listedeki ilk öğedeki alan 1
ile karşılaştırılır. Bir eşleşme varsa, istenen fiziksel adresi oluşturmak için ilgili sayfa
çerçevesi (alan 2) kullanılır.
Eşleşme yoksa, bağlantılı listedeki sonraki girişler eşleşen bir sanal sayfa numarası
için aranır. Bu şema Şekil 9.17'de gösterilmiştir.

fiziksel
mantıksal adres adres

p d r d

Özet •••
fiziksel
fonksiyonu
qs pr hafıza

karma tablo

Şekil 9.17 Karma sayfa tablosu.


Machine Translated by Google

374
Bölüm 9 Ana Bellek

64 bitlik adres alanları için yararlı olan bu şemanın bir varyasyonu önerilmiştir.
Bu varyasyon , karma tablodaki her girişin tek bir sayfa yerine birkaç sayfaya (16
gibi) başvurması dışında, karma sayfa tablolarına benzeyen kümelenmiş sayfa
tablolarını kullanır. Bu nedenle, tek bir sayfa tablosu girişi, birden çok fiziksel sayfa
çerçevesi için eşlemeleri depolayabilir. Kümelenmiş sayfa tabloları, bellek
referanslarının bitişik olmadığı ve adres alanı boyunca dağıldığı seyrek adres
alanları için özellikle yararlıdır .

9.4.3 Tersine Çevrilmiş Sayfa Tabloları

Genellikle, her işlemin ilişkili bir sayfa tablosu vardır. Sayfa tablosu, işlemin kullandığı
her sayfa için bir girişe (veya ikincisinin geçerliliğinden bağımsız olarak her sanal
adres için bir yuvaya) sahiptir. Referans sayfalarını sayfaların sanal adresleri
aracılığıyla işlediğinden, bu tablo gösterimi doğaldır. İşletim sistemi daha sonra
bu referansı fiziksel bir bellek adresine çevirmelidir. Tablo sanal adrese göre
sıralandığından, işletim sistemi ilişkili fiziksel adres girişinin tabloda nerede
olduğunu hesaplayabilir ve bu değeri doğrudan kullanabilir. Bu yöntemin
dezavantajlarından biri, her sayfa tablosunun milyonlarca girdiden oluşabilmesidir.
Bu tablolar, diğer fiziksel belleğin nasıl kullanıldığını takip etmek için büyük
miktarda fiziksel bellek tüketebilir.

Bu sorunu çözmek için ters çevrilmiş bir sayfa tablosu kullanabiliriz. Tersine
çevrilmiş bir sayfa tablosu, belleğin her gerçek sayfası (veya çerçevesi) için bir
girişe sahiptir. Her giriş, sayfanın sahibi olan süreç hakkında bilgilerle birlikte o
gerçek bellek konumunda saklanan sayfanın sanal adresinden oluşur. Böylece
sistemde yalnızca bir sayfa tablosu bulunur ve fiziksel belleğin her sayfası için
yalnızca bir girişi vardır. Şekil 9.18, ters çevrilmiş bir sayfa tablosunun çalışmasını
gösterir. Çalışmakta olan standart bir sayfa tablosunu gösteren Şekil 9.8 ile
karşılaştırın. Tersine çevrilmiş sayfa tabloları, genellikle sayfa tablosunun her
girişinde bir adres alanı tanımlayıcısının (Bölüm 9.3.2) saklanmasını gerektirir, çünkü tablo genellikle birkaç tane iç

mantıksal adres fiziksel


adres
d fiziksel
İşlemci pid p i d
hafıza

arama i

pid p

sayfa tablosu

Şekil 9.18 Ters çevrilmiş sayfa tablosu.


Machine Translated by Google

375
9.4 Sayfa Tablosunun Yapısı

fiziksel belleği eşleyen farklı adres alanları. Adres alanı tanımlayıcısının saklanması,
belirli bir işlem için mantıksal bir sayfanın karşılık gelen fiziksel sayfa çerçevesiyle
eşlenmesini sağlar. Tersine çevrilmiş sayfa tabloları kullanan sistemlere örnek olarak
64-bit UltraSPARC ve PowerPC dahildir.
Bu yöntemi göstermek için, IBM RT'de kullanılan ters çevrilmiş sayfa tablosunun
basitleştirilmiş bir sürümünü açıklıyoruz. IBM , IBM System 38 ile başlayan ve RS/6000 ve
mevcut IBM Power CPU'ları boyunca devam eden , tersine çevrilmiş sayfa tablolarını kullanan
ilk büyük şirketti . IBM RT için , sistemdeki her bir sanal adres, bir üçlüden oluşur:

<işlem kimliği, sayfa numarası, ofset>.

Her ters çevrilmiş sayfa tablosu girişi, işlem kimliğinin adres alanı tanımlayıcısı rolünü
üstlendiği bir <işlem kimliği, sayfa numarası> çiftidir. Bir bellek referansı oluştuğunda,
sanal adresin <işlem kimliği, sayfa numarası>' ndan oluşan kısmı bellek alt sistemine
sunulur. Ters çevrilmiş sayfa tablosu daha sonra bir eşleşme için aranır. Bir eşleşme
bulunursa (örneğin, i girişinde ) fiziksel adres <i, offset> oluşturulur. Eşleşme
bulunamazsa, yasa dışı bir adres erişimi denenmiştir.

Bu şema, her sayfa tablosunu depolamak için gereken bellek miktarını azaltsa da,
bir sayfa başvurusu oluştuğunda tabloyu aramak için gereken süreyi artırır. Tersine
çevrilmiş sayfa tablosu fiziksel adrese göre sıralandığından, ancak aramalar sanal
adreslerde gerçekleştiğinden, bir eşleşme bulunmadan önce tüm tablonun aranması
gerekebilir. Bu arama çok uzun sürecektir.
Bu sorunu hafifletmek için, aramayı bir veya en fazla birkaç sayfa tablosu girişiyle
sınırlamak için Bölüm 9.4.2'de açıklandığı gibi bir karma tablo kullanıyoruz. Elbette,
karma tablosuna her erişim, prosedüre bir bellek referansı ekler, bu nedenle bir sanal
bellek referansı en az iki gerçek bellek okuması gerektirir - biri karma tablo girişi için
diğeri sayfa tablosu için. ( Karma tabloya danışılmadan önce TLB'nin arandığını ve
bazı performans iyileştirmelerinin yapıldığını hatırlayın.)
Tersine çevrilmiş sayfa tablolarıyla ilgili ilginç bir sorun, paylaşılan bellekle ilgilidir.
Standart sayfalama ile, her işlemin, birden çok sanal adresin aynı fiziksel adrese
eşlenmesine izin veren kendi sayfa tablosu vardır. Bu yöntem, ters çevrilmiş sayfa
tablolarıyla kullanılamaz; her fiziksel sayfa için yalnızca bir sanal sayfa girişi
olduğundan, bir fiziksel sayfada iki (veya daha fazla) paylaşılan sanal adres olamaz. Bu
nedenle, ters çevrilmiş sayfa tablolarında, herhangi bir zamanda sanal bir adresin
paylaşılan fiziksel adrese yalnızca bir eşlemesi gerçekleşebilir. Belleği paylaşan başka
bir işlemin referansı, bir sayfa hatasına neden olacak ve eşlemeyi farklı bir sanal adresle
değiştirecektir.

9.4.4 Oracle SPARC Solaris


Son bir örnek olarak, düşük maliyetli sanal bellek sağlamak için sıkı bir şekilde entegre
edilmiş modern bir 64-bit CPU ve işletim sistemini düşünün. SPARC CPU üzerinde
çalışan Solaris , tamamen 64-bit bir işletim sistemidir ve bu nedenle, birden çok sayfa
tablosu seviyesi tutarak tüm fiziksel belleğini tüketmeden sanal bellek sorununu
çözmesi gerekir. Yaklaşımı biraz karmaşıktır ancak karma sayfa tablolarını kullanarak
sorunu verimli bir şekilde çözer. Biri çekirdek için diğeri tüm kullanıcı işlemleri için
olmak üzere iki karma tablo vardır. Her biri bellek adreslerini sanaldan fiziksel belleğe
eşler. Her karma tablo girişi, aşağıdakilerden daha verimli olan, eşlenmiş sanal
belleğin bitişik bir alanını temsil eder.
Machine Translated by Google

376
Bölüm 9 Ana Bellek
her sayfa için ayrı bir karma tablo girişi olması. Her girişin bir temel adresi ve girişin
temsil ettiği sayfa sayısını gösteren bir aralığı vardır.
Her adresin bir karma tablosunda arama yapması gerekiyorsa, sanaldan fiziksele
çeviri çok uzun sürer, bu nedenle CPU , hızlı donanım aramaları için çeviri tablosu
girişlerini (TTE'ler) tutan bir TLB uygular. Bu TTE'lerin önbelleği, son erişilen sayfa
başına bir giriş içeren bir çeviri depolama arabelleğinde (TSB) bulunur. Bir sanal
adres referansı oluştuğunda, donanım TLB'de bir çeviri arar. Hiçbiri bulunamazsa,
donanım, aramaya neden olan sanal adrese karşılık gelen TTE'yi arayan bellekteki
TSB'den geçer. Bu TLB yürüme işlevi birçok modern CPU'da bulunur. TSB'de bir
eşleşme bulunursa , CPU TSB girişini TLB'ye kopyalar ve bellek çevirisi tamamlanır.
TSB'de eşleşme bulunamazsa , hash tablosunu aramak için çekirdek kesintiye uğrar.
Çekirdek daha sonra uygun hash tablosundan bir TTE oluşturur ve bunu CPU bellek
yönetim birimi tarafından TLB'ye otomatik olarak yüklenmek üzere TSB'de saklar .
Son olarak, kesme işleyicisi , adres çevirisini tamamlayan ve istenen bayt veya
sözcüğü ana bellekten alan MMU'ya kontrolü geri verir .

9.5 Değiştirme

İşlem talimatları ve üzerinde çalıştıkları veriler yürütülebilmek için bellekte


olmalıdır. Bununla birlikte, bir işlem veya bir işlemin bir kısmı, geçici olarak bellekten
bir yedekleme deposuna değiştirilebilir ve ardından devam eden yürütme için
belleğe geri getirilebilir (Şekil 9.19). Değiştirme, tüm süreçlerin toplam fiziksel
adres alanının sistemin gerçek fiziksel belleğini aşmasını mümkün kılar, böylece bir
sistemdeki çoklu programlama derecesini arttırır.

işletim
sistemi

süreç P1
1 takas etmek

süreç P2
2 takas etmek

kullanıcı

Uzay
Destek deposu

ana hafıza

Şekil 9.19 Bir diski yedekleme deposu olarak kullanan iki işlemin standart takası.
Machine Translated by Google

9.5 Değiştirme 377

9.5.1 Standart Değiştirme

Standart takas, tüm işlemlerin ana bellek ile bir destek deposu arasında taşınmasını
içerir. Destek deposu genellikle hızlı ikincil depolamadır.
Depolanması ve alınması gereken süreçlerin herhangi bir bölümünü barındıracak
kadar büyük olmalı ve bu bellek görüntülerine doğrudan erişim sağlamalıdır. Bir
işlem veya parça yedek depoya değiştirildiğinde, işlemle ilişkili veri yapılarının
destek deposuna yazılması gerekir.
Çok iş parçacıklı bir süreç için, tüm iş parçacığı başına veri yapılarının da
değiştirilmesi gerekir. İşletim sistemi, değiştirilen işlemler için meta verileri de
korumalıdır, böylece bunlar belleğe geri yerleştirildiklerinde geri yüklenebilirler.

Standart takasın avantajı, fiziksel belleğin gereğinden fazla kullanılmasına izin


vermesidir, böylece sistem, bunları depolamak için gerçek fiziksel bellekten daha
fazla işlemi barındırabilir. Boşta olan veya çoğunlukla boşta olan süreçler takas için
iyi adaylardır; bu etkin olmayan işlemlere tahsis edilen herhangi bir bellek daha
sonra aktif işlemlere ayrılabilir. Değiştirilen etkin olmayan bir işlem bir kez daha
aktif hale gelirse, tekrar değiştirilmelidir. Bu, Şekil 9.19'da gösterilmektedir.

9.5.2 Sayfa Değiştirme ile Değiştirme

Standart değiştirme, geleneksel UNIX sistemlerinde kullanılıyordu, ancak genel


olarak artık çağdaş işletim sistemlerinde kullanılmamaktadır, çünkü tüm işlemleri
bellek ile yedekleme deposu arasında taşımak için gereken süre engelleyicidir.
(Bunun bir istisnası, hala standart takası kullanan, ancak yalnızca kullanılabilir bellek
son derece düşük olduğunda korkunç koşullar altında olan Solaris'tir.)

Linux ve Windows da dahil olmak üzere çoğu sistem, artık bir sürecin tamamı
yerine sayfalarının değiştirilebildiği bir takas pingi varyasyonu kullanıyor. Bu strateji
hala fiziksel belleğin gereğinden fazla kullanılmasına izin verir, ancak muhtemelen
yalnızca az sayıda sayfa değiş tokuşa dahil olacağından, tüm işlemlerin
değiştirilmesi maliyetini doğurmaz. Aslında, takas terimi artık genel olarak standart
takası ifade eder ve sayfalama , sayfalama ile değiştirmeyi ifade eder. Bir sayfa çıkışı
işlemi, bir sayfayı bellekten yedekleme deposuna taşır; tersine işlem, sayfa girişi
olarak bilinir . Sayfalama ile değiştirme, Şekil 9.20'de gösterilmektedir, burada A ve
B işlemleri için sayfaların bir alt kümesi sırasıyla sayfalandırılır ve sayfalandırılır.
Bölüm 10'da göreceğimiz gibi, disk belleği ile takas, sanal bellekle birlikte iyi çalışır.

9.5.3 Mobil Sistemlerde Değiştirme

PC'ler ve sunucular için çoğu işletim sistemi sayfa değiştirmeyi destekler. Buna
karşılık, mobil sistemler tipik olarak herhangi bir biçimde takası desteklemez. Mobil
cihazlar, kalıcı depolama için genellikle daha geniş sabit diskler yerine flash bellek
kullanır. Ortaya çıkan alan kısıtlaması, mobil işletim sistemi tasarımcılarının takas
yapmaktan kaçınmasının bir nedenidir. Diğer nedenler arasında, flash belleğin
güvenilmez hale gelmeden önce tolere edebileceği sınırlı sayıda yazma işlemi ve bu
cihazlarda ana bellek ile flash bellek arasındaki düşük verim sayılabilir.
378 Bölüm 9 Ana Bellek
Machine Translated by Google

işlem c
sayfa çıktı 0 1 2 3
A
d
4 b 5 c 6 e 7
e
8 9 10 11

f 12 13 14 15

g 18 19 16 17 j
sayfa
işlem h
B 20 21 22 23
i

j
Destek deposu

ana
hafıza

Şekil 9.20 Çağrı ile değiştirme.

Boş bellek belirli bir eşiğin altına düştüğünde, takas kullanmak yerine, Apple'ın iOS'u
uygulamalardan gönüllü olarak ayrılmış bellekten vazgeçmelerini ister . Salt okunur veriler
(kod gibi) ana bellekten kaldırılır ve daha sonra
gerekirse flash bellekten yeniden yüklenir. Değiştirilen veriler (örn.
yığın olarak) asla kaldırılmaz. Ancak, serbest bırakılamayan tüm uygulamalar
yeterli bellek, işletim sistemi tarafından sonlandırılabilir.
Android, iOS tarafından kullanılana benzer bir strateji benimser . Bir sonlandırabilir
Yetersiz boş bellek varsa işlem yapın. Ancak, bir işlemi sonlandırmadan önce
Android, uygulama durumunu flash belleğe yazar, böylece
hızlı bir şekilde yeniden başlatıldı.

Bu kısıtlamalar nedeniyle, mobil sistem geliştiricileri dikkatli bir şekilde


uygulamalarının da kullanmadığından emin olmak için bellek ayırın ve bırakın
çok fazla bellek veya bellek sızıntılarından muzdarip.

DEĞİŞİM ALTINDA SİSTEM PERFORMANSI

Sayfaları değiştirmek, tüm süreçleri değiştirmekten daha verimli olsa da,


Bir sistem herhangi bir değiş tokuşa maruz kaldığında, bu genellikle bir işarettir.
kullanılabilir fiziksel bellekten daha aktif işlemler. genel olarak var
bu durumu ele almak için iki yaklaşım: (1) bazı süreçleri sonlandırmak veya
(2) daha fazla fiziksel bellek elde edin!
Machine Translated by Google

379
9.6 Örnek: Intel 32- ve 64-bit Mimarileri

9.6 Örnek: Intel 32- ve 64-bit Mimarileri


Intel çiplerinin mimarisi, kişisel bilgisayar ortamına onlarca yıldır hükmediyor. 16-bit
Intel 8086, 1970'lerin sonlarında ortaya çıktı ve kısa süre sonra, orijinal IBM PC'de
kullanılan çip olduğu için dikkate değer olan başka bir 16-bit çip olan Intel 8088
tarafından takip edildi. Intel daha sonra 32-bit Pentium işlemci ailesini de içeren bir
dizi 32-bit çip (IA-32) üretti .
Daha yakın zamanlarda Intel, x86-64 mimarisine dayalı bir dizi 64-bit yonga üretti.
Şu anda, Windows, macOS ve Linux dahil olmak üzere en popüler PC işletim
sistemlerinin tümü Intel yongaları üzerinde çalışıyor (ancak Linux, elbette, birkaç
başka mimaride de çalışıyor). Bununla birlikte, özellikle, Intel'in hakimiyeti, ARM
mimarisinin şu anda önemli bir başarıya sahip olduğu mobil sistemlere yayılmamıştır
(bkz. Bölüm 9.7).
Bu bölümde, hem IA-32 hem de x86-64 mimarileri için adres çevirisini
inceliyoruz. Ancak devam etmeden önce, Intel'in yıllar içinde mimarilerinin çeşitli
versiyonlarının yanı sıra varyasyonlarını da yayınladığı için, tüm yongalarının bellek
yönetimi yapısının tam bir tanımını sağlayamayacağımızı belirtmek önemlidir. Tüm
CPU ayrıntılarını da sağlayamıyoruz , çünkü bu bilgi en iyi bilgisayar mimarisi
üzerine kitaplara bırakılıyor. Bunun yerine, bu Intel CPU'ların ana bellek yönetimi
kavramlarını sunuyoruz.

9.6.1 IA-32 Mimarisi


IA-32 sistemlerinde bellek yönetimi, segmentasyon ve sayfalama olmak üzere iki
bileşene bölünmüştür ve aşağıdaki gibi çalışır: CPU , segmentasyon birimine verilen
mantıksal adresleri üretir. Segmentasyon birimi, her mantıksal adres için doğrusal
bir adres üretir. Doğrusal adres daha sonra çağrı birimine verilir, bu da ana bellekte
fiziksel adresi oluşturur. Böylece, segmentasyon ve sayfalama birimleri, bellek
yönetimi biriminin (MMU) eşdeğerini oluşturur. Bu şema Şekil 9.21'de gösterilmiştir.

9.6.1.1 IA-32 Segmentasyonu


IA-32 mimarisi, bir segmentin 4 GB kadar büyük olmasına izin verir ve işlem başına
maksimum segment sayısı 16 K'dır. Bir işlemin mantıksal adres alanı iki bölüme
ayrılmıştır. İlk bölüm, o sürece özel olan 8 K'ye kadar bölümden oluşur. İkinci
bölüm, tüm süreçler arasında paylaşılan 8 K'ye kadar bölümden oluşur. İlk bölümle
ilgili bilgiler yerel tanımlayıcı tablosunda (LDT) tutulur ; ikinci bölümle ilgili bilgiler
genel tanımlayıcı tablosunda (GDT) tutulur . LDT ve GDT'deki her giriş, belirli bir
segment hakkında, o segmentin temel konumu ve limiti de dahil olmak üzere ayrıntılı
bilgi içeren 8 baytlık bir segment tanımlayıcısından oluşur.

fiziksel
doğrusal adres
İşlemci
mantıksal adres segmentasyonu çağrı adres fiziksel
birim birimi hafıza

Şekil 9.21 IA-32'de mantıksaldan fiziksel adrese çevirme.


Machine Translated by Google

380 Bölüm 9 Ana Bellek

mantıksal adres seçici telafi etmek

tanımlayıcı tablo

segment tanımlayıcı +

32 bit doğrusal adres

Şekil 9.22 IA-32 segmentasyonu.

Mantıksal adres, seçicinin 16 bitlik bir sayı olduğu bir çifttir (seçici, ofset):

s g p
13 1 2

Burada s , segment numarasını belirtir , g segmentin GDT'de mi yoksa LDT'de mi olduğunu


gösterir ve p koruma ile ilgilidir. Ofset, söz konusu segment içindeki baytın konumunu
belirten 32 bitlik bir sayıdır.
Makinede altı segment kaydı vardır ve bu, altı segmentin herhangi bir zamanda bir işlem
tarafından adreslenmesine izin verir. Ayrıca, LDT veya GDT'den ilgili tanımlayıcıları tutmak için
altı adet 8 baytlık mikro program kaydına sahiptir .
Bu önbellek, Pentium'un her bellek referansı için tanımlayıcıyı bellekten okumak zorunda
kalmamasını sağlar.
IA-32 üzerindeki lineer adres 32 bit uzunluğundadır ve aşağıdaki gibi oluşturulmuştur.
Segment kaydı, LDT veya GDT'deki uygun girişi gösterir. Söz konusu segmente ilişkin taban
ve limit bilgileri, doğrusal bir adres oluşturmak için kullanılır. İlk olarak, limit adres
geçerliliğini kontrol etmek için kullanılır. Adres geçerli değilse, işletim sistemine bir tuzakla
sonuçlanan bir bellek hatası oluşturulur. Geçerliyse, ofset değeri taban değerine eklenir
ve 32 bit doğrusal adres elde edilir. Bu, Şekil 9.22'de gösterilmektedir. Aşağıdaki bölümde,
çağrı biriminin bu doğrusal adresi nasıl fiziksel bir adrese dönüştürdüğünü tartışacağız.

9.6.1.2 IA-32 Sayfalama

IA-32 mimarisi, 4 KB veya 4 MB sayfa boyutuna izin verir . 4 KB sayfalar için IA -32, 32 bit
doğrusal adresin bölünmesinin aşağıdaki gibi olduğu iki seviyeli bir çağrı şeması kullanır:

sayfa numarası sayfa ofseti


p1 p2 d

10 10 12
Machine Translated by Google

381
9.6 Örnek: Intel 32- ve 64-bit Mimarileri

(doğrusal adres)

sayfa dizini sayfa tablosu telafi etmek

31 22 21 12 11 0

sayfa 4-KB
tablosu sayfa

sayfa
dizini

CR3
4 MB
kaydı
sayfa

sayfa dizini telafi etmek

31 22 21 0

Şekil 9.23 IA-32 mimarisinde sayfalama.

Bu mimari için adres-çeviri şeması, Şekil 9.16'da gösterilen şemaya benzer. IA-32
adres çevirisi , Şekil 9.23'te daha ayrıntılı olarak gösterilmektedir. 10 yüksek
dereceli bit, en dıştaki sayfa tablosundaki, IA-32'nin sayfa dizini olarak adlandırdığı
bir girdiye başvurur. ( CR3 kaydı, geçerli işlem için sayfa dizinini gösterir.) Sayfa
dizini girişi, doğrusal adresteki en içteki 10 bitin içeriği tarafından indekslenen
bir iç sayfa tablosuna işaret eder. Son olarak, 0–11 arasındaki düşük sıralı bitler ,
sayfa tablosunda gösterilen 4 KB'lık sayfadaki ofseti ifade eder.

Sayfa dizinindeki bir giriş, eğer ayarlanmışsa, sayfa çerçevesinin boyutunun


standart 4 KB değil 4 MB olduğunu gösteren Sayfa Boyutu bayrağıdır .
Bu bayrak ayarlanırsa, sayfa dizini , iç sayfa tablosunu atlayarak doğrudan 4
MB'lık sayfa çerçevesine işaret eder; ve lineer adresteki 22 düşük değerli bit, 4
MB'lık sayfa çerçevesindeki ofseti ifade eder.
Fiziksel bellek kullanımının verimliliğini artırmak için IA-32 sayfa tabloları
diske değiştirilebilir. Bu durumda, girişin işaret ettiği tablonun bellekte mi yoksa
diskte mi olduğunu belirtmek için sayfa dizini girişinde geçersiz bir bit kullanılır.
Tablo diskteyse, işletim sistemi tablonun disk konumunu belirtmek için diğer 31
biti kullanabilir. Tablo daha sonra talep üzerine belleğe getirilebilir.

Yazılım geliştiriciler , 32 bit mimarilerin 4 GB bellek sınırlamalarını keşfetmeye


başladığında , Intel, 32 bit işlemcilerin 4 GB'den daha büyük bir fiziksel adres
alanına erişmesine izin veren bir sayfa adresi uzantısını (PAE) benimsedi. PAE
desteğinin getirdiği temel fark , sayfalamanın iki seviyeli bir şemadan (Şekil
9.23'te gösterildiği gibi) üç seviyeli bir şemaya gitmesiydi, burada en üstteki iki
bit bir sayfa dizini işaretçi tablosuna atıfta bulunuyordu. Şekil 9.24 , 4 KB sayfalı
bir PAE sistemini göstermektedir. (PAE ayrıca 2 MB'lık sayfaları da destekler.)
PAE ayrıca sayfa dizini ve sayfa tablosu girişlerini boyut olarak 32'den 64 bit'e çıkardı, bu
da sayfa tablolarının ve sayfa çerçevelerinin temel adresinin
Machine Translated by Google

382
Bölüm 9 Ana Bellek

sayfa dizini sayfa tablosu telafi etmek

31 30 29 21 20 12 11 0

4-KB
sayfa
CR3
Kayıt ol sayfa dizini sayfa sayfa
işaretçi tablosu dizin masa

Şekil 9.24 Sayfa adresi uzantıları.

20 ila 24 bit arasında uzanır. PAE desteği ekleyerek 12 bit ofset ile birlikte
IA- 32'ye , adres alanını 64 GB'a kadar destekleyen 36 bite çıkardı
fiziksel bellekten. İşletim sistemi desteğine dikkat etmek önemlidir.
PAE kullanmak için gereklidir . Hem Linux hem de macOS PAE'yi destekler . Ancak 32 bit
Windows masaüstü işletim sistemlerinin sürümleri hala yalnızca
PAE etkinleştirilmiş olsa bile 4 GB fiziksel bellek.

9.6.2 x86-64
Intel'in 64 bit mimariler geliştirme konusunda ilginç bir geçmişi var. İlk girişi IA-64
(daha sonra Itanium olarak adlandırılacak) mimarisiydi, ancak bu mimari geniş çapta
benimsenmedi. Bu arada, başka bir çip üreticisi—AMD
— tabanlı x86-64 olarak bilinen 64 bitlik bir mimari geliştirmeye başladı
mevcut IA-32 komut setinin genişletilmesi hakkında. x86-64 çok destekledi
daha büyük mantıksal ve fiziksel adres alanlarının yanı sıra diğer birçok mimari
gelişme. Tarihsel olarak, AMD genellikle Intel'e dayalı çipler geliştirmişti.
mimarisi, ancak şimdi Intel, AMD'nin x86-64'ünü benimsediği için roller tersine döndü.
mimari. Bu mimariyi tartışırken, ticari
AMD64 ve Intel 64 adları için daha genel bir terim olan x86-64'ü kullanacağız .
64 bit adres alanı desteği, şaşırtıcı bir şekilde 264 baytlık veri sağlar.
adreslenebilir bellek—16 kentilyondan (veya 16 eksabayttan) büyük bir sayı.
Bununla birlikte, 64-bit sistemler potansiyel olarak bu kadar çok belleğe hitap edebilse
de, uygulamada adres gösterimi için 64 bitten çok daha azı kullanılır.
güncel tasarımlar. x86-64 mimarisi şu anda 48 bit sanal
dört düzey kullanarak 4 KB, 2 MB veya 1 GB sayfa boyutlarını destekleyen adres
sayfalama hiyerarşisi. Doğrusal adresin temsili Şekilde görülmektedir.
9.25. Bu adresleme şeması PAE kullanabildiğinden, sanal adresler 48 bittir.
boyutundadır ancak 52 bit fiziksel adresleri (4,096 terabayt) destekler.

sayfa haritası sayfa dizini sayfa sayfa


kullanılmamış Seviye 4 işaretçi tablosu dizin masa telafi etmek

63 4748 39 38 30 29 21 20 12 11 0

Şekil 9.25 x86-64 lineer adres.


Machine Translated by Google

9.7 Örnek: ARMv8 Mimarisi 383

9.7 Örnek: ARMv8 Mimarisi


Intel çipleri kişisel bilgisayar pazarına daha fazla hakim olmasına rağmen
30 yılı aşkın süredir, akıllı telefonlar ve tablet bilgisayarlar gibi mobil cihazlar için
çipler genellikle ARM işlemcilerde çalışıyor. İlginç bir şekilde, Intel hem
cips tasarlar ve üretir, ARM sadece onları tasarlar. Daha sonra lisanslar
mimari tasarımlarını çip üreticilerine sunmaktadır. Apple, ARM'nin lisansını aldı
iPhone ve iPad mobil cihazları için tasarlanmıştır ve çoğu Android tabanlı akıllı
telefon da ARM işlemcileri kullanır. Mobil cihazlara ek olarak, ARM ayrıca
gerçek zamanlı gömülü sistemler için mimari tasarımlar sağlar. çünkü
ARM mimarisinde çalışan cihazların bolluğu, 100 milyardan fazla ARM
işlemciler üretildi, bu da onu en yaygın kullanılan mimari haline getirdi
üretilen cips miktarıyla ölçüldüğünde. Bu bölümde anlatıyoruz
64-bit ARMv8 mimarisi.
ARMv8'in üç farklı çeviri granülü vardır: 4 KB , 16 KB ve 64
KB. Her çeviri granülü, farklı sayfa boyutlarının yanı sıra daha büyük
bölgeler olarak bilinen bitişik bellek bölümleri. Sayfa ve bölge boyutları
farklı çeviri granülleri için aşağıda gösterilmiştir:

Çeviri Granül Boyutu Sayfa boyutu Bölge Boyutu


4 KB 4 KB 2 MB, 1 GB
16 KB 16 KB 32 MB
64 KB 64 KB 512 MB

4-KB ve 16-KB granüller için dört sayfaya kadar sayfalama seviyesi kullanılabilir,
64 KB granüller için üç adede kadar sayfalama düzeyi ile . Şekil 9.26 göstermektedir
4 KB'ye kadar çeviri granülü için ARMv8 adres yapısı dörde kadar
sayfalama seviyeleri. ( ARMv8'in 64 bit bir mimari olmasına rağmen, yalnızca 48
bitler şu anda kullanılmaktadır.) için dört seviyeli hiyerarşik sayfalama yapısı
4-KB çeviri granülü Şekil 9.27'de gösterilmiştir. ( TTBR kaydı,
çeviri tablosu taban kaydı ve mevcut için seviye 0 tablosuna işaret eder
iplik.)
Dört seviyenin tümü kullanılıyorsa, ofset (Şekil 9.26'da 0-11 bitleri)
4 KB'lık bir sayfa içinde ofset . Ancak, seviye 1 için tablo girişlerinin ve

64-BİT BİLGİSAYAR

Tarih bize, bellek kapasiteleri, CPU hızları ve


benzer bilgisayar yetenekleri, talebi karşılamak için yeterince büyük görünüyor.
öngörülebilir gelecekte, teknolojinin büyümesi nihayetinde mevcut
kapasiteler ve kendimizi ek belleğe veya işlemeye ihtiyaç duyuyoruz
güç, genellikle düşündüğümüzden daha erken. Teknolojinin geleceği neler getirebilir?
bu 64 bitlik bir adres alanının çok küçük görünmesine neden olur mu?
Machine Translated by Google

384
Bölüm 9 Ana Bellek
seviye 0 1. seviye seviye 2 seviye 3

kullanılmamış indeksi indeks indeksi indeksi telafi etmek

63 4748 39 38 30 29 21 20 12 11 0

Şekil 9.26 ARM 4-KB çeviri granülü.

düzey 2, başka bir tabloya veya 1 GB'lik bir bölgeye (düzey-1 tablosu) veya 2 MB'lik bir
bölgeye (düzey-2 tablosu) atıfta bulunabilir. Örnek olarak, seviye-1 tablosu seviye-2
tablosundan ziyade 1-GB'lık bir bölgeye atıfta bulunuyorsa, düşük seviyeli 30 bit (Şekil
9.26'da 0-29 bitleri) bu 1-GB'lık bir ofset olarak kullanılır. bölge. Benzer şekilde, seviye-2
tablosu seviye-3 tablosundan ziyade 2-MB'lik bir bölgeye atıfta bulunuyorsa, düşük
seviyeli 21 bit (Şekil 9.26'da 0–20 bitleri) bu 2-MB bölgesindeki ofseti ifade eder.
ARM mimarisi ayrıca iki TLB seviyesini destekler . İç düzeyde iki mikro TLB vardır -
bir TLB veri için ve diğeri talimatlar için. Mikro TLB , ASID'leri de destekler . Dış seviyede
tek bir ana TLB bulunur. Adres çevirisi mikro-TLB düzeyinde başlar. Bir ıskalama
durumunda, ana TLB daha sonra kontrol edilir. Her iki TLB de ıska verirse , donanımda
bir sayfa tablosu yürüyüşü gerçekleştirilmelidir.

9.8 Özet
• Bellek, modern bir bilgisayar sisteminin işleyişinin merkezinde yer alır ve her biri kendi
adresine sahip çok sayıda bayttan oluşur.

• Her işleme bir adres alanı tahsis etmenin bir yolu, taban ve limit kayıtlarının
kullanılmasıdır. Temel kayıt, en küçük yasal fiziksel bellek adresini tutar ve sınır,
aralığın boyutunu belirtir.

seviye 0 1. seviye seviye 2 seviye 3


telafi etmek
indeksi indeks indeksi indeksi

3. seviye
masa
2. seviye
masa
1. seviye 4-KB
masa
seviye 0 sayfa

tablosu

TTBR

kaydı

1 GB 2 MB

bölge bölge

Şekil 9.27 ARM dört seviyeli hiyerarşik çağrı.


Alıştırmalar 385
Machine Translated by Google
• Gerçek fiziksel adreslere bağlanan sembolik adres referansları (1) derleme, (2)
yükleme veya (3) yürütme süresi sırasında meydana gelebilir.
• CPU tarafından oluşturulan bir adres, bellek yönetim biriminin (MMU) bellekteki
fiziksel bir adrese çevirdiği mantıksal adres olarak bilinir.

• Bellek ayırmaya yönelik bir yaklaşım, farklı boyutlardaki bitişik bellek bölümlerinin
ayrılmasıdır. Bu bölümler üç olası stratejiye göre ayrılabilir: (1) ilk uyum, (2) en
iyi uyum ve (3) en kötü uyum.
• Modern işletim sistemleri, belleği yönetmek için sayfalamayı kullanır. Bu
süreçte fiziksel bellek çerçeve adı verilen sabit boyutlu bloklara ve mantıksal
bellek sayfa adı verilen aynı boyuttaki bloklara bölünür.
• Sayfalama kullanıldığında, mantıksal bir adres iki bölüme ayrılır: bir sayfa numarası
ve bir sayfa ofseti. Sayfa numarası, sayfayı tutan fiziksel bellekteki çerçeveyi
içeren işlem başına sayfa tablosunda bir dizin görevi görür. Ofset, referans
alınan çerçevedeki belirli konumdur. • Bir çeviri önbelleği (TLB) , sayfa

tablosunun bir donanım önbelleğidir.


Her TLB girişi, bir sayfa numarası ve buna karşılık gelen çerçeveyi içerir.

• Çağrı sistemleri için adres çevirisinde TLB kullanılması , mantıksal adresten sayfa
numarasının alınmasını ve sayfa çerçevesinin TLB'de olup olmadığının kontrol
edilmesini içerir . Eğer öyleyse, çerçeve TLB'den elde edilir. Çerçeve TLB'de
mevcut değilse , sayfa tablosundan alınmalıdır. • Hiyerarşik sayfalama, mantıksal

bir adresin, her biri farklı sayfa tabloları seviyelerine atıfta bulunan birden çok
parçaya bölünmesini içerir. Adresler 32 bitin ötesine genişledikçe, hiyerarşik
seviyelerin sayısı artabilir. Bu sorunu ele alan iki strateji, karma sayfa tabloları ve
ters çevrilmiş sayfa tablolarıdır.

• Değiştirme, sistemin bir işleme ait sayfaları diske taşımasını sağlar


çoklu programlamanın derecesini artırmak için.

• Intel 32 bit mimarisinde iki sayfa tablosu düzeyi bulunur ve 4 KB veya 4 MB sayfa
boyutlarını destekler. Bu mimari ayrıca 32 bit işlemcilerin 4 GB'den büyük bir
fiziksel adres alanına erişmesine izin veren sayfa adresi uzantısını da destekler .
x86-64 ve ARMv9 mimarileri, hiyerarşik sayfalama kullanan 64 bit mimarilerdir.

Alıştırmalar

9.1 Mantıksal ve fiziksel adresler arasındaki iki farkı adlandırın.

9.2 Sayfa boyutları neden her zaman 2'nin katıdır?

9.3 Bir programın iki bölüme ayrılabileceği bir sistem düşünün: kod ve veri. CPU ,
bir talimat (talimat getirme) veya veri (veri alma veya saklama) isteyip
istemediğini bilir. Bu nedenle, iki temel limit kayıt çifti sağlanır: biri talimatlar
için ve diğeri veriler için. Talimat
386 Bölüm
Machine Translated by Google 9 Ana Bellek
base –limit register çifti otomatik olarak salt okunurdur, böylece programlar
farklı kullanıcılar arasında paylaşılabilir. Bu planın avantajlarını ve
dezavantajlarını tartışın.
9.4 Her biri 1.024 sözcükten oluşan 64 sayfalık, 32 çerçevelik bir fiziksel belleğe
eşlenmiş mantıksal bir adres alanı düşünün.
a. Mantıksal adreste kaç bit var?
b. Fiziksel adreste kaç bit var?
9.5 Bir sayfa tablosundaki iki girişin bellekte aynı sayfa çerçevesini göstermesine
izin vermenin etkisi nedir? Büyük miktarda belleği bir yerden diğerine
kopyalamak için gereken süreyi azaltmak için bu etkinin nasıl
kullanılabileceğini açıklayın. Bir sayfadaki bazı baytları güncellemenin
diğer sayfada nasıl bir etkisi olur?
9.6 300 KB, 600 KB, 350 KB, 200 KB, 750 KB ve 125 KB'lik (sırasıyla) altı bellek
bölümü verildiğinde , ilk-uyum, en iyi-uyum ve en kötü-uyum algoritmaları
115 boyutlu süreçleri nasıl yerleştirir? KB, 500 KB, 358 KB, 200 KB ve 375
KB (sırayla)?
9.7 1 KB'lık bir sayfa boyutu varsayıldığında , aşağıdaki adres referansları için
sayfa numaraları ve ofsetler nelerdir (ondalık sayılar olarak sağlanır):
a. 3085
b. 42095
c. 215201
d. 650000
e. 2000001

9.8 BTV işletim sistemi 21 bit sanal adrese sahiptir , ancak bazı gömülü cihazlarda
yalnızca 16 bit fiziksel adrese sahiptir. Ayrıca 2 KB sayfa boyutuna sahiptir.
Aşağıdakilerin her birinde kaç giriş var?
a. Geleneksel, tek düzeyli bir sayfa tablosu b.
Tersine çevrilmiş bir sayfa tablosu BTV işletim
sisteminde maksimum fiziksel bellek miktarı nedir ?

9.9 64 karelik bir fiziksel belleğe eşlenmiş, 4 KB sayfa boyutunda 256 sayfalık bir
mantıksal adres alanı düşünün .
a. Mantıksal adreste kaç bit gereklidir?
b. Fiziksel adreste kaç bit gereklidir?
9.10 32 bit mantıksal adrese ve 4 KB sayfa boyutuna sahip bir bilgisayar sistemi
düşünün . Sistem 512 MB'a kadar fiziksel belleği destekler. Aşağıdakilerin
her birinde kaç giriş var?
a. Geleneksel, tek düzeyli bir sayfa tablosu b.
Ters çevrilmiş bir sayfa tablosu
Machine Translated by Google

bibliyografya 387

Daha fazla okuma


Sayfalama kavramı Atlas sisteminin tasarımcılarına atfedilebilir.
[Kilburn et al. (1961)] ve [Howarth et al.
(1961)].
[Hennessy ve Patterson (2012)] TLB'lerin donanım özelliklerini açıklar,
önbellekler ve MMU'lar. [Jacob ve Mudge (2001)] yönetim tekniklerini tanımlar.
TLB . [Fang et al. (2001)] büyük sayfalar için desteği değerlendirir.
Windows sistemleri için PAE desteği http://msdn.microsoft.co adresinde tartışılmaktadır.
m/en-us/library/windows/hardware/gg487512.aspx ARM'ye genel bakış
mimari http://www.arm.com/products/processors/cortex a/cortex-a9.php adresinde
sağlanmaktadır.

bibliyografya

[Fang et al. (2001)] Z. Fang, L. Zhang, JB Carter, WC Hsieh ve SA McKee,


“Donanım Desteği ile Çevrimiçi Süper Sayfa Promosyonunun Yeniden
Değerlendirilmesi”, Uluslararası Yüksek Performanslı Bilgisayar Mimarisi Sempozyumu Bildirileri,
Cilt 50, Sayı 5 (2001).

[Hennessy ve Patterson (2012)] J. Hennessy ve D. Patterson, Computer Architecture: A


Quantitative Approach, Fifth Edition, Morgan Kaufmann (2012).

[Howarth et al. (1961)] DJ Howarth, RB Payne ve FH Sumner, “The


Manchester University Atlas İşletim Sistemi, Bölüm II: Kullanıcının Açıklaması”,
Computer Journal, Cilt 4, Sayı 3 (1961), sayfa 226–229.

[Jacob ve Mudge (2001)] B. Jacob ve T. Mudge, “TLB'ler Olmadan Tek İşlemcili Sanal
Bellek”, Bilgisayarlarda IEEE İşlemleri, Cilt 50, Sayı 5 (2001).

[Kilburn et al. (1961)] T. Kilburn, DJ Howarth, RB Payne ve FH Sumner,


“Manchester Üniversitesi Atlas İşletim Sistemi, Bölüm I: Dahili Organizasyon”,
Computer Journal, Cilt 4, Sayı 3 (1961), sayfa 222–225.
Egzersizler EX-32
Machine Translated by Google
Bölüm 9 Alıştırmalar

9.11 İç ve dış parçalanma arasındaki farkı açıklayın.

9.12 İkili dosyalar oluşturmak için aşağıdaki süreci göz önünde bulundurun. Bireysel
modüller için nesne kodunu oluşturmak için bir derleyici kullanılır ve birden çok
nesne modülünü tek bir program ikili dosyasında birleştirmek için bir bağlayıcı kullanıl
Bağlayıcı, talimatların ve verilerin bellek adreslerine bağlanmasını nasıl değiştirir?
Bağlayıcının bellek bağlama görevlerini kolaylaştırmak için derleyiciden
bağlayıcıya hangi bilgilerin iletilmesi gerekir?

9.13 100 MB, 170 MB, 40 MB, 205 MB, 300 MB ve 185 MB'lik (sırasıyla) altı bellek bölümü
verildiğinde , ilk-uyum, en iyi-uyum ve en-kötü-uyum algoritmaları 200 boyutlu
süreçleri nasıl yerleştirir? MB, 15 MB, 185 MB, 75 MB, 175 MB ve 80 MB (sırayla)?
Varsa, hangi isteklerin karşılanamayacağını belirtin. Algoritmaların her birinin
belleği ne kadar verimli yönettiği hakkında yorum yapın.

9.14 Çoğu sistem, bir programın yürütme sırasında adres alanına daha fazla bellek
ayırmasına izin verir. Programların yığın bölümlerinde veri tahsisi, bu tür tahsis
edilmiş belleğe bir örnektir. Aşağıdaki şemalarda dinamik bellek ayırmayı
desteklemek için ne gereklidir?

a. Bitişik bellek tahsisi b. Sayfalama 9.15

Bitişik bellek tahsisi ve sayfalamanın

bellek organizasyon şemalarını aşağıdaki konulara göre karşılaştırın:

a. Dış parçalanma b. İç

parçalanma c. İşlemler

arasında kod paylaşma yeteneği 9.16 Disk

belleği olan bir sistemde bir işlem, sahip olmadığı belleğe erişemez. Neden? Niye?
İşletim sistemi ek belleğe erişime nasıl izin verebilir? Neden olmalı veya olmamalı?

9.17 iOS ve Android gibi mobil işletim sistemlerinin neden takası desteklemediğini açıklayın.

9.18 Android, önyükleme diskinde değiştirmeyi desteklemese de, ayrı bir SD kalıcı bellek
kartı kullanarak bir takas alanı kurmak mümkündür . Android neden önyükleme
diskinde takasa izin vermiyor, ancak ikincil bir diskte buna izin veriyor?

9.19 TLB'lerde adres alanı tanımlayıcılarının (ASID'ler) neden kullanıldığını açıklayın.

9.20 Birçok sistemdeki program ikili dosyaları tipik olarak aşağıdaki gibi yapılandırılmıştır.
Kod, 0 gibi küçük, sabit bir sanal adresle başlayarak depolanır. Kod bölümünü,
program değişkenlerini depolamak için kullanılan veri bölümü izler. Program
çalışmaya başladığında, yığın sanal adres alanının diğer ucunda tahsis edilir ve
daha düşük sanal adreslere doğru büyümesine izin verilir. Aşağıdaki şemalar için
bu yapının önemi nedir?
Machine Translated by Google

EX-33

a. Bitişik bellek tahsisi b. Sayfalama

9.21 1 KB'lık bir sayfa boyutu

varsayıldığında , aşağıdaki adres referansları için sayfa numaraları ve ofsetler


nelerdir (ondalık sayılar olarak sağlanır)?
a. 21205

b. 164250

c. 121357

d. 16479315
e. 27253187

9.22 MPV işletim sistemi gömülü sistemler için tasarlanmıştır ve 24 bit sanal adrese,
20 bit fiziksel adrese ve 4 KB sayfa boyutuna sahiptir.
Aşağıdakilerin her birinde kaç giriş var?

a. Geleneksel, tek seviyeli bir sayfa tablosu

b. Ters çevrilmiş bir sayfa tablosu

MPV işletim sistemindeki maksimum fiziksel bellek miktarı nedir ?

9.23 512 çerçevelik bir fiziksel belleğe eşlenmiş, 4 KB sayfa boyutunda 2.048 sayfalık
bir mantıksal adres alanı düşünün .

a. Mantıksal adreste kaç bit gereklidir? b. Fiziksel adreste

kaç bit gereklidir?

9.24 32 bit mantıksal adrese ve 8 KB sayfa boyutuna sahip bir bilgisayar sistemi
düşünün . Sistem 1 GB'a kadar fiziksel belleği destekler. Aşağıdakilerin her
birinde kaç giriş var?

a. Geleneksel, tek seviyeli bir sayfa tablosu

b. Tersine çevrilmiş bir sayfa


tablosu 9.25 Sayfa tablosunun bellekte saklandığı bir çağrı sistemi düşünün.

a. Bir bellek başvurusu 50 nanosaniye sürüyorsa, disk belleğine alınmış bir


bellek başvurusu ne kadar sürer? b. TLB'leri eklersek ve tüm sayfa

tablosu referanslarının yüzde 75'i TLB'lerde bulunursa, etkin bellek referans


süresi nedir? (Giriş varsa, TLB'lerde bir sayfa tablosu girişi bulmanın 2
nanosaniye sürdüğünü varsayın.)

9.26 Sayfa tablolarını sayfalamanın amacı nedir?


9.27 Şekil 9.22'de gösterilen IA-32 adres-çeviri şemasını göz önünde bulundurun .

a. Mantıksal bir adresi fiziksel bir adrese çevirmek için IA-32 tarafından atılan
tüm adımları açıklayın . b. Bu kadar karmaşık bellek çevirisi sağlayan
donanımın işletim sisteminin avantajları nelerdir?
Egzersizler EX-34
Machine Translated by Google

c. Bu adres-çeviri sisteminin herhangi bir dezavantajı var mı? Eğer


öyleyse, bunlar nelerdir? Değilse, bu şema neden her üretici
tarafından kullanılmıyor?
Machine Translated by Google

Programlama Projeleri P-48

Programlama Sorunları

9.28 Bir sistemin 4 KB sayfa boyutunda 32 bit sanal adresi olduğunu varsayın.
Komut satırına sanal bir adres (ondalık olarak) geçirilen bir C programı yazın
ve verilen adres için sayfa numarası ve ofset çıktısını almasını sağlayın. Örnek
olarak, programınız aşağıdaki gibi çalışır:
./adresler 19986

Programınız çıktı verir:


19986 adresi şunları içerir: sayfa
numarası = 4 offset = 3602

Bu programın yazılması, 32 bit depolamak için uygun veri tipinin kullanılmasını


gerektirecektir. İmzasız veri türlerini de kullanmanızı öneririz .

Programlama Projeleri

Bitişik Bellek Tahsisi


Bölüm 9.2'de, bitişik bellek tahsisi için farklı algoritmalar sunduk. Bu proje,
adreslerin 0 ... MAX 1 aralığında olabileceği, MAX boyutunda bitişik bir bellek
bölgesinin yönetilmesini içerecektir. Programınız dört farklı isteğe yanıt vermelidir:

1. Bitişik bir bellek bloğu talebi 2. Bitişik bir bellek


bloğunun serbest bırakılması 3. Kullanılmayan
bellek deliklerini tek bir bloğa sıkıştırın
4. Boş ve ayrılmış bellek bölgelerini bildirin

Programınız başlangıçta başlangıçtaki bellek miktarını geçirecektir. Örneğin,


aşağıdakiler programı 1 MB (1.048.576 bayt) bellekle başlatır:

./ayırıcı 1048576

Programınız başladığında, kullanıcıya aşağıdaki komut istemini sunacaktır:

tahsisatçı>

Ardından aşağıdaki komutlara yanıt verecektir: RQ (istek), RL (sürüm), C (kompakt),


STAT (durum raporu) ve X (çıkış).
40.000 baytlık bir istek aşağıdaki gibi görünecektir:
ayırıcı>RQ P0 40000 W
Machine Translated by Google

P-49 Bölüm 9 Ana Bellek


RQ komutunun ilk parametresi , bellek gerektiren yeni işlem, ardından talep edilen bellek miktarı
ve son olarak stratejidir. (Bu durumda, “W” en kötü uyumu ifade eder.)

Benzer şekilde, bir sürüm şu şekilde görünecektir:

ayırıcı>RL P0

Bu komut, P0 işlemi için ayrılmış olan belleği serbest bırakacaktır .


Sıkıştırma komutu şu şekilde girilir:

ayırıcı>C

Bu komut, kullanılmayan bellek deliklerini bir bölgeye sıkıştıracaktır.


Son olarak, hafızanın durumunu raporlamak için STAT komutu girilir.
olarak:

ayırıcı>STAT

Bu komut verildiğinde, programınız tahsis edilen hafıza bölgelerini ve kullanılmayan bölgeleri


rapor edecektir. Örneğin, olası bir bellek tahsisi düzenlemesi aşağıdaki gibi olacaktır:

Adresler [0:315000] Proses P1 Adresleri [315001:


512500] Proses P3 Adresleri [512501:625575] Kullanılmayan
Adresler [625575:725100] Proses P6 Adresleri [725001] .

. .

Bellek Ayırma

Programınız, RQ komutuna iletilen bayrağa bağlı olarak, Bölüm 9.2.2'de vurgulanan üç


yaklaşımdan birini kullanarak bellek tahsis edecektir . Bayraklar:

• F—ilk uyum

• B—en uygun

• W—en kötü uyum

Bu, programınızın mevcut belleği temsil eden farklı delikleri takip etmesini gerektirecektir.
Bir bellek talebi geldiğinde, tahsisat stratejisine göre belleği mevcut deliklerden birinden tahsis
edecektir.
Bir isteğe tahsis etmek için yeterli bellek yoksa, bir hata mesajı verir ve isteği reddeder.

Programınızın ayrıca, hangi işlem için hangi bellek bölgesinin tahsis edildiğini takip etmesi
gerekecektir. Bu, STAT komutunu desteklemek için gereklidir ve ayrıca, belleği serbest bırakma
işlemi bu komuta iletildiğinden, bellek RL komutu aracılığıyla serbest bırakıldığında da gereklidir .
Serbest bırakılan bir bölme mevcut bir deliğe bitişikse, iki deliği tek bir delikte birleştirdiğinizden
emin olun.
Machine Translated by Google

bibliyografya P-50

Sıkıştırma

Kullanıcı C komutunu girerse, programınız delikler grubunu daha büyük bir deliğe
sıkıştıracaktır. Örneğin, 550 KB, 375 KB, 1.900 KB ve 4.500 KB boyutunda dört ayrı
deliğiniz varsa , programınız bu dört deliği 7.325 KB boyutunda tek bir büyük
delikte birleştirecektir.
Sıkıştırmayı uygulamak için, biri Bölüm 9.2.3'te önerilen birkaç strateji vardır.
Sıkıştırmadan etkilenen tüm süreçlerin başlangıç adresini güncellediğinizden emin
olun.
Machine Translated by Google
Machine Translated by Google

10 BÖLÜM
Sanal
Hafıza

9. Bölümde, bilgisayar sistemlerinde kullanılan çeşitli bellek yönetimi


stratejilerini tartıştık. Tüm bu stratejilerin amacı aynı: çoklu programlamaya
izin vermek için birçok işlemi aynı anda bellekte tutmak. Ancak,
yürütülebilmesi için tüm bir işlemin bellekte olmasını gerektirme eğilimindedirler.
Sanal bellek, tamamen bellekte olmayan işlemlerin yürütülmesine izin
veren bir tekniktir. Bu şemanın önemli bir avantajı, programların fiziksel
bellekten daha büyük olabilmesidir. Ayrıca, sanal bellek, ana belleği,
programcı tarafından görüntülendiği şekliyle mantıksal belleği fiziksel
bellekten ayırarak, son derece geniş, tek biçimli bir depolama dizisine
soyutlar. Bu teknik, programcıları bellek-depolama sınırlamaları
endişelerinden kurtarır. Sanal bellek, süreçlerin dosya ve kitaplıkları
paylaşmasına ve paylaşılan belleği uygulamasına da olanak tanır. Ayrıca,
süreç oluşturma için verimli bir mekanizma sağlar. Ancak sanal belleğin
uygulanması kolay değildir ve dikkatsizce kullanılırsa performansı önemli
ölçüde azaltabilir. Bu bölümde, sanal belleğe ayrıntılı bir genel bakış
sunacak, nasıl uygulandığını inceleyecek ve karmaşıklığını ve faydalarını keşfedeceğiz.

BÖLÜM HEDEFLERİ

• Sanal belleği tanımlayın ve faydalarını açıklayın. • Talep

çağrısını kullanarak sayfaların belleğe nasıl yüklendiğini gösterin. • FIFO, optimal ve

LRU sayfa değiştirme algoritmalarını uygulayın . • Bir sürecin çalışma grubunu tanımlayın

ve bunun program yeri ile nasıl ilişkili olduğunu açıklayın. • Linux, Windows 10 ve Solaris'in sanal
belleği nasıl yönettiğini açıklayın. • C programlama alanında bir sanal bellek yöneticisi

simülasyonu tasarlayın

ölçü.

10.1 Arkaplan

Bölüm 9'da özetlenen bellek yönetimi algoritmaları, tek bir temel


gereksinim nedeniyle gereklidir: yürütülmekte olan komutlar
389
Machine Translated by Google

390 Bölüm 10 Sanal Bellek


fiziksel hafıza. Bu gereksinimi karşılamaya yönelik ilk yaklaşım, mantıksal adres alanının
tamamını fiziksel belleğe yerleştirmektir. Dinamik bağlantı, bu kısıtlamayı hafifletmeye yardımcı
olabilir, ancak genellikle özel önlemler ve programcı tarafından ek çalışma gerektirir.

Talimatların yürütülebilmesi için fiziksel bellekte olması gerekliliği hem gerekli hem de
makul görünmektedir; ama aynı zamanda talihsiz bir durumdur, çünkü bir programın boyutunu
fiziksel belleğin boyutuyla sınırlar. Aslında, gerçek programların incelenmesi bize birçok
durumda programın tamamının gerekli olmadığını gösterir. Örneğin, aşağıdakileri göz
önünde bulundurun:

• Programlar genellikle olağandışı hata durumlarını işlemek için koda sahiptir. Bu hatalar
pratikte nadiren meydana geldiğinden, bu kod neredeyse hiç yürütülmez. • Diziler, listeler

ve tablolar genellikle ihtiyaç duyduklarından daha fazla bellek tahsis edilir. Bir dizi, nadiren
10'a 10 elemandan daha büyük olmasına rağmen 100'e 100 eleman olarak bildirilebilir.

• Bir programın belirli seçenekleri ve özellikleri nadiren kullanılabilir. Örneğin, ABD devlet
bilgisayarlarındaki bütçeyi dengeleyen rutinler uzun yıllardır kullanılmamaktadır.

Tüm programın gerekli olduğu durumlarda bile, hepsine aynı anda ihtiyaç duyulmayabilir.

Yalnızca kısmen bellekte olan bir programı yürütme yeteneği birçok fayda sağlar:

• Bir program artık mevcut fiziksel bellek miktarıyla kısıtlanmayacaktır. Kullanıcılar ,


programlama görevini basitleştirerek, son derece büyük bir sanal adres alanı için
programlar yazabilecektir . • Her program daha az fiziksel bellek kullanabildiğinden, aynı

anda daha fazla program çalıştırılabilir, buna karşılık gelen CPU kullanımı ve çıktı artışı
sağlanır, ancak yanıt süresinde veya geri dönüş süresinde artış olmaz.

• Programların bölümlerini yüklemek veya değiştirmek için daha az G/Ç gerekli olacaktır.
bellek, böylece her program daha hızlı çalışacaktı.

Bu nedenle, tamamen bellekte olmayan bir programı çalıştırmak hem sisteme hem de
kullanıcılarına fayda sağlayacaktır.
Sanal bellek , geliştiriciler tarafından algılandığı şekliyle mantıksal belleğin fiziksel bellekten
ayrılmasını içerir. Bu ayrım, yalnızca daha küçük bir fiziksel bellek mevcut olduğunda
programcılar için son derece büyük bir sanal belleğin sağlanmasına olanak tanır (Şekil 10.1).
Sanal bellek, programlama işini çok daha kolaylaştırır, çünkü programcının artık mevcut fiziksel
bellek miktarı hakkında endişelenmesine gerek yoktur; bunun yerine çözülmesi gereken
problemi programlamaya konsantre olabilir.

Bir işlemin sanal adres alanı , bir işlemin bellekte nasıl depolandığının mantıksal (veya
sanal) görünümüne atıfta bulunur. Tipik olarak, bu görüş, bir işlemin belirli bir mantıksal adreste
(örneğin, adres 0) başladığı ve Şekil 10.2'de gösterildiği gibi bitişik bellekte var olduğu
şeklindedir. Bölüm 9'dan, aslında fiziksel belleğin sayfa çerçevelerinde düzenlendiğini ve bir
işleme atanan fiziksel sayfa çerçevelerinin bitişik olmayabileceğini hatırlayın. Hafızaya kalmış-
Machine Translated by Google

10.1 Arkaplan 391

sayfa 0

Sayfa 1

sayfa 2



hafıza
haritası

Destek deposu
sayfa v fiziksel
hafıza
sanal
hafıza

Şekil 10.1 Fiziksel bellekten daha büyük sanal belleği gösteren diyagram.

mantıksal sayfaları bellekteki fiziksel sayfa çerçevelerine eşlemek için yönetim birimi
(MMU) .
Şekil 10.2'de, yığının dinamik bellek tahsisi için kullanıldığı için bellekte yukarı
doğru büyümesine izin verdiğimize dikkat edin. Benzer şekilde, ardışık işlev çağrıları
yoluyla yığının bellekte aşağı doğru büyümesine izin veriyoruz. Yığın ve yığın
arasındaki büyük boş alan (veya delik), sanal adres alanının bir parçasıdır, ancak yalnızca
yığın veya yığın büyürse gerçek fiziksel sayfalar gerektirir.
Delikler içeren sanal adres alanları, seyrek adres alanları olarak bilinir.
Seyrek bir adres alanı kullanmak faydalıdır, çünkü yığın veya yığın segmentleri
büyüdükçe veya program yürütme sırasında kitaplıkları (veya muhtemelen diğer
paylaşılan nesneleri) dinamik olarak bağlamak istiyorsak delikler doldurulabilir.

maksimum

yığın

yığın

veri

Metin

Şekil 10.2 Bellekteki bir işlemin sanal adres alanı.


Machine Translated by Google

392
Bölüm 10 Sanal Bellek

yığın yığın

paylaşılan
paylaşılan kitaplık paylaşılan kitaplık
sayfalar

yığın yığın

veri veri

Metin Metin

Şekil 10.3 Sanal bellek kullanan paylaşılan kitaplık.

Sanal bellek, mantıksal belleği fiziksel bellekten ayırmaya ek olarak, dosyaların


ve belleğin sayfa paylaşımı yoluyla iki veya daha fazla işlem tarafından paylaşılmasına
izin verir (Bölüm 9.3.4). Bu, aşağıdaki avantajlara yol açar:

• Standart C kitaplığı gibi sistem kitaplıkları, paylaşılan nesnenin sanal bir adres
alanına eşlenmesi yoluyla birkaç işlem tarafından paylaşılabilir. Her proses
kütüphaneleri kendi sanal adres uzayının bir parçası olarak görse de,
kütüphanelerin fiziksel bellekte bulunduğu gerçek sayfalar tüm prosesler
tarafından paylaşılır (Şekil 10.3). Tipik olarak, bir kitaplık, onunla bağlantılı her
işlemin alanına salt okunur olarak eşlenir.
• Benzer şekilde, süreçler hafızayı paylaşabilir. Bölüm 3'ten iki veya daha fazla
işlemin paylaşılan bellek kullanımı yoluyla iletişim kurabileceğini hatırlayın.
Sanal bellek, bir işlemin başka bir işlemle paylaşabileceği bir bellek bölgesi
oluşturmasına izin verir. Bu bölgeyi paylaşan işlemler, onu sanal adres alanlarının
bir parçası olarak kabul eder, ancak Şekil 10.3'te gösterildiği gibi, belleğin
gerçek fiziksel sayfaları paylaşılır.
• Sayfalar, süreç oluşturma sırasında fork() sistem çağrısı ile paylaşılabilir, böylece
süreç oluşturma hızlandırılır.

Bu bölümün ilerleyen kısımlarında sanal belleğin bu ve diğer yararlarını daha


ayrıntılı olarak keşfedeceğiz. İlk olarak, talep sayfalama yoluyla sanal belleğin
uygulanmasını tartışıyoruz.

10.2 Talep Çağrısı

Yürütülebilir bir programın ikincil depolamadan belleğe nasıl yüklenebileceğini


düşünün. Bir seçenek, tüm programı, program yürütme zamanında fiziksel belleğe
yüklemektir. Ancak, bu yaklaşımla ilgili bir sorun,
Machine Translated by Google

10.2 Talep Çağrısı 393

başlangıçta tüm programın bellekte olmasına ihtiyacımız olmayabilir . Bir programın,


kullanıcının seçeceği mevcut seçeneklerin bir listesiyle başladığını varsayalım.
Programın tamamını belleğe yüklemek , sonuçta bir seçeneğin seçilip
seçilmediğine bakılmaksızın tüm seçenekler için yürütülebilir kodun yüklenmesiyle sonuçlanır.
kullanıcı.

Alternatif bir strateji, sayfaları yalnızca gerektiği kadar yüklemektir. Bu teknik,


talep sayfalama olarak bilinir ve sanal bellek sistemlerinde yaygın olarak kullanılır.
Talep sayfalı sanal bellek ile sayfalar yalnızca program yürütme sırasında
istendiğinde yüklenir . Asla erişilmeyen sayfalar bu nedenle asla fiziksel belleğe
yüklenmez. Talep çağrı sistemi, işlemlerin ikincil bellekte (genellikle bir HDD veya
NVM aygıtı) bulunduğu takaslı bir çağrı sistemine benzer (Kısım 9.5.2 ). Talep
sayfalama, sanal belleğin başlıca faydalarından birini açıklar: Programların yalnızca
gerekli olan kısımlarını yükleyerek bellek daha verimli kullanılır.

10.2.1 Temel Kavramlar


Talep sayfalamanın ardındaki genel kavram, belirtildiği gibi, bir sayfayı yalnızca
gerektiğinde belleğe yüklemektir. Sonuç olarak, bir işlem yürütülürken bazı
sayfalar bellekte, bazıları ise ikincil depolamada olacaktır. Bu nedenle, ikisi arasında
ayrım yapmak için bir tür donanım desteğine ihtiyacımız var. Bu amaçla Bölüm
9.3.3'te açıklanan geçerli – geçersiz bit şeması kullanılabilir. Bu

0 A 2
geçerli-geçersiz
1 B bit 3
çerçeve

2 C 4 A
04 v

3 D 1 i 5
62 v
4 E 6 C AB
3 i

5 F 4 i 7
59 v C D E
6 G 8
6 i
7 H 7 i 9 F FGH

sayfa tablosu
10
mantıksal bellek
11

12
Destek deposu
13

14

15

fiziksel hafıza

Şekil 10.4 Bazı sayfalar ana bellekte olmadığında sayfa tablosu.


Machine Translated by Google

394
Bölüm 10 Sanal Bellek
bununla birlikte, bit "geçerli" olarak ayarlandığında, ilişkili sayfa hem yasal hem
de bellektedir. Bit "geçersiz" olarak ayarlanırsa sayfa ya geçerli değildir (yani
işlemin mantıksal adres alanında değildir) ya da geçerlidir ancak şu anda ikincil
depolamadadır. Belleğe getirilen bir sayfanın sayfa tablosu girişi her zamanki
gibi ayarlanır, ancak o anda bellekte olmayan bir sayfanın sayfa tablosu girişi
geçersiz olarak işaretlenir. Bu durum Şekil 10.4'te gösterilmektedir.
(Sürecin o sayfaya asla erişmeye çalışmaması durumunda, bir sayfayı geçersiz olarak işaretlemenin
hiçbir etkisi olmayacağına dikkat edin.)
Ancak süreç belleğe alınmamış bir sayfaya erişmeye çalışırsa ne olur?
Geçersiz olarak işaretlenen bir sayfaya erişim, sayfa hatasına neden olur.
Sayfalama donanımı, adresi sayfa tablosu aracılığıyla çevirirken, geçersiz bitin
ayarlandığını fark edecek ve işletim sistemine bir tuzak kurulmasına neden
olacaktır. Bu tuzak, işletim sisteminin istenen sayfayı belleğe getirememesinin
sonucudur. Bu sayfa hatasını işleme prosedürü basittir (Şekil 10.5):

1. Referansın geçerli mi yoksa geçersiz bir bellek erişimi mi olduğunu


belirlemek için bu işlem için dahili bir tabloyu (genellikle işlem kontrol
bloğunda tutulur) kontrol ederiz.
2. Referans geçersiz ise işlemi sonlandırıyoruz. Geçerliyse, ancak henüz o
sayfayı getirmediysek, şimdi onu sayfaya alıyoruz.
3. Boş bir çerçeve buluruz (örneğin, serbest çerçeve listesinden birini alarak).

sayfa destek
3
mağazasında

işletim
sistemi
2
referans
tuzak kurmak

yük M i

tekrar başlat sayfa tablosu


talimat
ücretsiz çerçeve

5 4 Destek deposu

sayfa tablosunu eksik


sıfırla sayfayı getir

fiziksel
hafıza

Şekil 10.5 Bir sayfa hatasının ele alınmasındaki adımlar.


Machine Translated by Google

10.2 Talep Çağrısı 395

4. İstenen sayfayı okumak için ikincil bir depolama işlemi planlıyoruz.


yeni tahsis edilen çerçeve.

5. Depolama okuması tamamlandığında, işlemle birlikte tutulan dahili tabloyu ve sayfa


tablosunu sayfanın artık bellekte olduğunu gösterecek şekilde değiştiririz.

6. Tuzak tarafından kesilen talimatı yeniden başlatıyoruz. İşlem artık sayfaya her zaman
bellekteymiş gibi erişebilir.

Aşırı durumda, bellekte sayfa olmayan bir işlemi yürütmeye başlayabiliriz . İşletim sistemi,
bellekte yerleşik olmayan bir sayfada bulunan işlemin ilk talimatına talimat işaretçisini
ayarladığında, işlem hemen sayfa için hata verir. Bu sayfa belleğe getirildikten sonra, ihtiyaç
duyduğu her sayfa belleğe gelene kadar işlem gerektiği gibi hata vererek yürütülmeye devam
eder. Bu noktada, daha fazla hata olmadan çalışabilir. Bu şema saf talep çağrıdır: gerekli olana
kadar asla bir sayfayı belleğe getirmeyin.

Teorik olarak, bazı programlar, her talimatın yürütülmesiyle birkaç yeni bellek sayfasına
erişebilir (yönerge için bir sayfa ve veriler için çoğu sayfa), bu da muhtemelen talimat başına
birden çok sayfa hatasına neden olabilir. Bu durum, kabul edilemez sistem performansına neden
olur. Neyse ki, çalışan süreçlerin analizi, bu davranışın son derece olası olmadığını gösteriyor.
Programlar , Bölüm 10.6.1'de açıklanan ve talep çağrısından makul bir performansla sonuçlanan
referans yerelliğine sahip olma eğilimindedir .

Talep çağrısını destekleyen donanım, çağrı ve takas donanımıyla aynıdır:

• Sayfa tablosu. Bu tablo, geçerli bir geçersiz bit veya özel bir koruma biti değeri aracılığıyla
bir girişi geçersiz olarak işaretleme yeteneğine sahiptir.

• İkincil bellek. Bu bellek, ana bellekte bulunmayan sayfaları tutar. İkincil bellek genellikle
yüksek hızlı bir disk veya NVM aygıtıdır. Takas cihazı olarak bilinir ve bu amaçla kullanılan
depolama bölümü takas alanı olarak bilinir. Takas alanı tahsisi Bölüm 11'de tartışılmaktadır.

Talep çağrısı için çok önemli bir gereksinim, bir sayfa hatasından sonra herhangi bir
talimatı yeniden başlatma yeteneğidir. Sayfa hatası oluştuğunda kesilen işlemin durumunu
(kayıtlar, koşul kodu, talimat sayacı) kaydettiğimiz için , istenen sayfanın artık bellekte olması
dışında işlemi tam olarak aynı yer ve durumda yeniden başlatabilmemiz gerekir. ve erişilebilir.
Çoğu durumda, bu gereksinimin karşılanması kolaydır. Herhangi bir bellek referansında bir
sayfa hatası meydana gelebilir. Talimat getirmede sayfa hatası oluşursa, talimatı tekrar getirerek
yeniden başlatabiliriz. Bir işleneni getirirken bir sayfa hatası meydana gelirse, komutu tekrar
getirmeli ve kodunu çözmeli ve ardından işleneni getirmeliyiz.

En kötü durum örneği olarak, sonucu C'ye yerleştirerek A'nın içeriğini B'ye ADD gibi üç
adresli bir talimatı düşünün . Bu talimatı yürütmek için gereken adımlar şunlardır:

1. Yönergeyi alın ve kodunu çözün (EKLE).

2. A'yı getir.
Machine Translated by Google

396 Bölüm 10 Sanal Bellek


3. B'yi getir.

4. A ve B'yi ekleyin.

5. Toplamı C'de saklayın.

C'ye kaydetmeye çalıştığımızda hata yaparsak (çünkü C şu anda bellekte olmayan bir sayfada),
istenen sayfayı almamız, getirmemiz, sayfa tablosunu düzeltmemiz ve talimatı yeniden başlatmamız
gerekecek. Yeniden başlatma, talimatın tekrar getirilmesini, tekrar kodunun çözülmesini, iki işlenenin
tekrar getirilmesini ve ardından tekrar eklenmesini gerektirecektir. Ancak, çok fazla tekrarlanan
çalışma yoktur (bir tam talimattan daha az) ve tekrar sadece bir sayfa hatası olduğunda gereklidir.

meydana gelmek.

En büyük zorluk, bir komutun birkaç farklı konumu değiştirebildiği zaman ortaya çıkar.
Örneğin, bir konumdan diğerine (muhtemelen örtüşen) bir konuma 256 bayta kadar hareket
edebilen IBM System 360/370 MVC (karakter taşıma) talimatını düşünün. Bloklardan biri (kaynak
veya hedef) bir sayfa sınırını aşıyorsa, taşıma kısmen yapıldıktan sonra bir sayfa hatası meydana
gelebilir. Ek olarak, eğer kaynak ve hedef bloklar çakışırsa, kaynak blok değiştirilmiş olabilir, bu
durumda komutu basitçe yeniden başlatamayız.

Bu problem iki farklı şekilde çözülebilir. Bir çözümde, mikro kod hesaplar ve her iki bloğun
her iki ucuna da erişmeye çalışır. Bir sayfa hatası meydana gelecekse, herhangi bir değişiklik
yapılmadan önce bu adımda gerçekleşecektir.
Hareket daha sonra gerçekleşebilir; ilgili tüm sayfalar hafızada olduğundan sayfa hatası
oluşamayacağını biliyoruz. Diğer çözüm, üzerine yazılan konumların değerlerini tutmak için
geçici kayıtlar kullanır. Bir sayfa hatası varsa, tuzak oluşmadan önce tüm eski değerler belleğe
yazılır. Bu eylem, talimatın tekrarlanabilmesi için belleği talimat başlatılmadan önceki durumuna
geri yükler.

Bu, talep çağrılarına izin vermek için mevcut bir mimariye sayfalama eklenmesinden
kaynaklanan tek mimari sorun değildir, ancak ilgili bazı zorlukları göstermektedir. Bir bilgisayar
sisteminde CPU ile bellek arasına sayfalama eklenir . Bir süreç için tamamen şeffaf olmalıdır.

Bu nedenle, insanlar genellikle sayfalamanın herhangi bir sisteme eklenebileceğini varsayar. Bu


varsayım, bir sayfa hatasının önemli bir hatayı temsil ettiği, talep edilmeyen bir sayfalama ortamı
için doğru olsa da, bir sayfa hatasının yalnızca belleğe ek bir sayfa getirilmesi ve işlemin yeniden
başlatılması gerektiği anlamına geldiği durumlarda doğru değildir.

10.2.2 Serbest Çerçeve Listesi

Bir sayfa hatası oluştuğunda, işletim sistemi istenen sayfayı ikincil depolamadan ana belleğe
getirmelidir. Sayfa hatalarını çözmek için çoğu işletim sistemi, bu tür istekleri karşılamak için bir
serbest çerçeve listesi, bir serbest çerçeve havuzu bulundurur (Şekil 10.6). (Serbest çerçeveler, bir
süreçteki yığın veya yığın segmentleri genişlediğinde de tahsis edilmelidir.) İşletim sistemleri
tipik olarak

kafa 7 97 15 126 ... 75

Şekil 10.6 Serbest çerçevelerin listesi.


Machine Translated by Google

10.2 Talep Çağrısı 397

İsteğe bağlı olarak sıfır doldurma olarak bilinen bir teknik kullanarak ücretsiz çerçeveler
oluşturun . İsteğe bağlı sıfır doldurma çerçeveleri, tahsis edilmeden önce "sıfırlanır", böylece
önceki içerikleri silinir. ( Yeniden atamadan önce bir çerçevenin içeriğini temizlememenin olası
güvenlik sonuçlarını göz önünde bulundurun .)
Bir sistem başlatıldığında, kullanılabilir tüm bellek boş çerçeve listesine yerleştirilir. Serbest
çerçeveler talep edildiğinden (örneğin, talep sayfalama yoluyla), serbest çerçeve listesinin boyutu
küçülür. Bir noktada, liste ya sıfıra düşer ya da belirli bir eşiğin altına düşer, bu noktada yeniden
doldurulması gerekir. Bu durumların her ikisi için de stratejileri Bölüm 10.4'te ele alıyoruz.

10.2.3 Talep Çağrısının Performansı


Talep çağrısı, bir bilgisayar sisteminin performansını önemli ölçüde etkileyebilir.
Nedenini görmek için, istek sayfalı bir bellek için etkin erişim süresini hesaplayalım. Ma ile gösterilen
bellek erişim süresinin 10 nanosaniye olduğunu varsayın. Sayfa hatamız olmadığı sürece etkin
erişim süresi, bellek erişim süresine eşittir. Ancak bir sayfa hatası meydana gelirse, önce ikincil
depodan ilgili sayfayı okumalı ve ardından istenen kelimeye erişmeliyiz.

p , bir sayfa hatası olasılığı olsun (0 p 1). p'nin sıfıra yakın olmasını beklerdik, yani sadece
birkaç sayfa hatası olmasını beklerdik . Etkin erişim süresi daha sonra

etkin erişim süresi = (1 p) × ma + p × sayfa hata süresi.

Etkili erişim süresini hesaplamak için, bir sayfa hatasına hizmet vermek için ne kadar zamana
ihtiyaç olduğunu bilmeliyiz. Bir sayfa hatası aşağıdaki sıranın
meydana gelmek:

1. İşletim sistemine tuzak kurun.

2. Kayıtları ve işlem durumunu kaydedin.

3. Kesmenin bir sayfa hatası olduğunu belirleyin.

4. Sayfa referansının yasal olup olmadığını kontrol edin ve sayfanın konumunu belirleyin.
ikincil depolamadaki sayfa.

5. Depolamadan boş bir çerçeveye bir okuma yayınlayın:

a. Okuma isteğine hizmet verilene kadar kuyrukta bekleyin. b. Cihaz

arama ve/veya gecikme süresini bekleyin. c. Sayfayı boş bir çerçeveye

aktarmaya başlayın.

6. Beklerken, CPU çekirdeğini başka bir işleme ayırın.

7. Depolama G/Ç alt sisteminden bir kesme alın (G/Ç tamamlandı).

8. Diğer işlem için kayıtları ve işlem durumunu kaydedin (adım 6 ise


uygulanmış).

9. Kesmenin ikincil depolama aygıtından geldiğini belirleyin.

10. İstenen sayfanın doğru olduğunu göstermek için sayfa tablosunu ve diğer tabloları düzeltin.
şimdi hafızamda.

11. CPU çekirdeğinin bu işleme yeniden atanmasını bekleyin .


Machine Translated by Google

398 Bölüm 10 Sanal Bellek


12. Kayıtları, işlem durumunu ve yeni sayfa tablosunu geri yükleyin ve ardından kesintiye
uğrayan talimata devam edin.

Bu adımların tümü her durumda gerekli değildir. Örneğin, 6. adımda, G/Ç gerçekleşirken
CPU'nun başka bir işleme tahsis edildiğini varsayıyoruz .
Bu düzenleme, çoklu programlamanın CPU kullanımını sürdürmesine izin verir, ancak G/Ç
aktarımı tamamlandığında sayfa hatası hizmet rutinini sürdürmek için ek süre gerektirir.

Her durumda, sayfa hatası hizmet süresinin üç ana görev bileşeni vardır:

1. Sayfa hatası kesmesine hizmet verin.

2. Sayfayı okuyun.

3. İşlemi yeniden başlatın.

Birinci ve üçüncü görevler, dikkatli kodlama ile birkaç yüz talimata indirgenebilir. Bu
görevlerin her biri 1 ila 100 mikrosaniye arasında sürebilir.
Disk belleği cihazı olarak kullanılan HDD'leri ele alalım . Sayfa değiştirme süresi muhtemelen
8 milisaniyeye yakın olacaktır. (Tipik bir sabit diskin ortalama gecikme süresi 3 milisaniye,
arama süresi 5 milisaniye ve aktarım süresi 0,05 milisaniyedir. Bu nedenle, toplam sayfalama
süresi donanım ve yazılım süresi dahil yaklaşık 8 milisaniyedir.) sadece cihaz servis zamanına
bakarak. Cihaz için bir işlem sırası bekliyorsa, sayfalama cihazının isteğimize hizmet etmek
için ücretsiz olmasını beklerken sıraya girme süresini eklememiz gerekir, bu da sayfaya girme
süresini daha da artırır.

8 milisaniyelik ortalama sayfa hatası servis süresi ve bir bellek ile


200 nanosaniye erişim süresi, nanosaniye cinsinden etkin erişim süresi

etkin erişim süresi = (1 - p) × (200) + p (8 milisaniye) = (1 - p) × 200 +


p × 8.000.000 = 200 + 7.999.800 × p.

O halde etkin erişim süresinin sayfa hata oranıyla doğru orantılı olduğunu görüyoruz .
1000 erişimden biri sayfa hatasına neden oluyorsa, etkin erişim süresi 8,2 mikrosaniyedir.
Bilgisayar, talep çağrısı nedeniyle 40 kat yavaşlayacak! Performans düşüşünün yüzde 10'dan
az olmasını istiyorsak, sayfa hatası olasılığını aşağıdaki düzeyde tutmamız gerekir:

220 > 200 + 7.999.800 × p, 20


> 7.999.800 × p, p < 0.0000025.

Yani, sayfalamadan kaynaklanan yavaşlamayı makul bir düzeyde tutmak için, 399.990'dan
daha az bir bellek erişimine sayfa hatasına izin verebiliriz. Özetle, bir talep çağrı sisteminde
sayfa hata oranını düşük tutmak önemlidir. Aksi takdirde, etkin erişim süresi artar ve işlemin
yürütülmesini önemli ölçüde yavaşlatır.
Talep sayfalamanın ek bir yönü, takas alanının ele alınması ve genel kullanımıdır. Alanı
değiştirmek için G/Ç genellikle dosya sistemine göre daha hızlıdır. Takas alanı çok daha
büyük bloklarda tahsis edildiğinden ve dosya aramaları ve dolaylı tahsis yöntemleri
kullanılmadığından daha hızlıdır (Bölüm 11). için bir seçenek
Machine Translated by Google

10.3 Yazma Üzerine Kopya 399

Sistemin daha iyi sayfalama çıktısı elde etmesi için, işlem başlangıcında tüm dosya
görüntüsünü takas alanına kopyalamak ve ardından takas alanından talep sayfalama
gerçekleştirmektir. Bu yaklaşımın bariz dezavantajı, program başlangıcında dosya
görüntüsünün kopyalanmasıdır. İkinci bir seçenek - ve Linux ve Windows dahil
olmak üzere birkaç işletim sistemi tarafından uygulanan - başlangıçta dosya
sisteminden sayfa talep etmek, ancak sayfaları değiştirildikçe takas alanı için
yazmaktır. Bu yaklaşım, dosya sisteminden yalnızca gerekli sayfaların okunmasını,
ancak sonraki tüm sayfalamaların takas alanından yapılmasını sağlayacaktır.
Bazı sistemler, ikili yürütülebilir dosyaların talep sayfalaması yoluyla kullanılan
takas alanı miktarını sınırlamaya çalışır. Bu tür dosyalar için talep sayfaları doğrudan
dosya sisteminden getirilir. Ancak, sayfa değişimi istendiğinde, bu çerçevelerin
üzerine basitçe yazılabilir (çünkü asla değiştirilmezler) ve gerekirse sayfalar dosya
sisteminden tekrar okunabilir.
Bu yaklaşımı kullanarak, dosya sisteminin kendisi destek deposu olarak hizmet eder.
Ancak, bir dosyayla ilişkili olmayan sayfalar için takas alanı yine de kullanılmalıdır
( anonim bellek olarak bilinir); bu sayfalar bir işlem için yığın ve yığın içerir.
Bu yöntem iyi bir uzlaşma gibi görünüyor ve Linux ve BSD UNIX dahil olmak üzere çeşitli
sistemlerde kullanılıyor.
Bölüm 9.5.3'te açıklandığı gibi, mobil işletim sistemleri tipik olarak takası
desteklemez. Bunun yerine, bu sistemler dosya sisteminden sayfa talep eder ve bellek
kısıtlanırsa uygulamalardan salt okunur sayfaları (kod gibi) geri alır. Bu tür veriler,
daha sonra ihtiyaç duyulursa dosya sisteminden talep-sayfalanabilir. iOS altında ,
uygulama sonlandırılmadıkça veya belleği açıkça serbest bırakmadıkça, bir
uygulamadan anonim bellek sayfaları hiçbir zaman geri alınmaz. Bölüm 10.7'de,
mobil sistemlerde takasa yaygın olarak kullanılan bir alternatif olan sıkıştırılmış
belleği ele alıyoruz.

10.3 Yazma Üzerine Kopya

Bölüm 10.2'de, ilk talimatı içeren sayfada talep çağrısı yaparak bir sürecin nasıl hızlı
bir şekilde başlayabileceğini gösterdik. Bununla birlikte, fork() sistem çağrısı
kullanılarak süreç oluşturma, sayfa paylaşımına benzer bir teknik kullanarak (Bölüm
9.3.4'te ele alınmıştır) başlangıçta talep sayfalama ihtiyacını atlayabilir. Bu teknik, hızlı
süreç oluşturmayı sağlar ve yeni oluşturulan sürece ayrılması gereken yeni sayfa
sayısını en aza indirir.
fork() sistem çağrısının, ebeveyninin kopyası olan bir alt süreç oluşturduğunu
hatırlayın . Geleneksel olarak, fork() , ebeveyne ait sayfaları çoğaltarak, çocuk için
ebeveynin adres alanının bir kopyasını oluşturarak çalıştı.
Ancak, birçok alt işlemin oluşturulduktan hemen sonra exec() sistem çağrısını
çağırdığı düşünüldüğünde, ebeveynin adres alanının kopyalanması gereksiz olabilir.
Bunun yerine, üst ve alt süreçlerin başlangıçta aynı sayfaları paylaşmasına izin
vererek çalışan , yazma üzerine kopyalama olarak bilinen bir teknik kullanabiliriz . Bu
paylaşılan sayfalar, yazıldığında kopyalanabilen sayfalar olarak işaretlenir, yani her
iki işlem de paylaşılan bir sayfaya yazarsa, paylaşılan sayfanın bir kopyası oluşturulur.
Yazma üzerine kopyalama, işlem 1'in C sayfasını değiştirmesinden önceki ve sonraki
fiziksel belleğin içeriğini gösteren Şekil 10.7 ve 10.8'de gösterilmektedir.
Örneğin, alt sürecin, sayfaların yazıldığında kopyalanacak şekilde ayarlandığı
yığının bölümlerini içeren bir sayfayı değiştirmeye çalıştığını varsayalım. İşletim
sistemi, serbest çerçeve listesinden bir çerçeve alacak ve bir kopya oluşturacaktır.
400
Bölüm
Machine Translated by Google 10 Sanal Bellek
fiziksel
süreç1 hafıza süreç2

sayfa A

B sayfası

sayfa C

Şekil 10.7 İşlem 1, sayfa C'yi değiştirmeden önce.

bu sayfanın alt sürecin adres alanıyla eşleştirilmesi. Alt süreç daha sonra
kopyalanan sayfasını değiştirir ve üst sürece ait sayfayı değiştirmez. Açıkçası,
yazma üzerine kopyalama tekniği kullanıldığında, yalnızca her iki işlem
tarafından değiştirilen sayfalar kopyalanır; değiştirilmemiş tüm sayfalar üst ve
alt süreçler tarafından paylaşılabilir. Ayrıca, yalnızca değiştirilebilen sayfaların
yazma üzerine kopya olarak işaretlenmesi gerektiğini unutmayın.
Değiştirilemeyen sayfalar (yürütülebilir kod içeren sayfalar) ebeveyn ve çocuk
tarafından paylaşılabilir. Yazma üzerine kopyalama, Windows, Linux ve macOS
dahil olmak üzere çeşitli işletim sistemleri tarafından kullanılan yaygın bir tekniktir .
UNIX'in çeşitli sürümleri (Linux, macOS ve BSD UNIX dahil) , yazma üzerine
kopyalama ile fork() 'tan farklı şekilde çalışan fork() sistem çağrısının (vfork()
( sanal bellek çatalı için) bir varyasyonunu sağlar. vfork() ile ana süreç askıya
alınır ve alt süreç ebeveynin adres alanını kullanır. vfork () yazma üzerine
kopyalama kullanmadığından, alt süreç ebeveynin adres alanının herhangi bir
sayfasını değiştirirse, değiştirilen sayfalar devam ettirildiğinde üst öğe
tarafından görülebilir. Bu nedenle, alt sürecin ebeveynin adres alanını
değiştirmemesini sağlamak için vfork() dikkatli kullanılmalıdır. vfork() , alt
süreç oluşturulduktan hemen sonra exec()' i çağırdığında kullanılmak üzere
tasarlanmıştır . Sayfaların kopyalanması olmadığı için vfork()

fiziksel
süreç 1 hafıza süreç 2

sayfa A

B sayfası

sayfa C

C sayfasının kopyası

Şekil 10.8 İşlem 1, C sayfasını değiştirdikten sonra.


Machine Translated by Google

10.4 Sayfa Değiştirme 401

son derece verimli bir süreç oluşturma yöntemidir ve bazen UNIX komut satırı kabuk
arabirimlerini uygulamak için kullanılır.

10.4 Sayfa Değiştirme

Sayfa hatası oranıyla ilgili daha önceki tartışmamızda, her sayfaya ilk başvurulduğunda en
fazla bir kez hata verdiğini varsaymıştık. Ancak bu temsil kesin olarak doğru değildir. On
sayfalık bir işlem aslında bunların yalnızca yarısını kullanıyorsa, talep sayfalama , hiç
kullanılmayan beş sayfayı yüklemek için gereken G/Ç'den tasarruf sağlar. İki kat daha fazla
işlem çalıştırarak çoklu programlama derecemizi de artırabiliriz. Böylece, kırk çerçevemiz
olsaydı, her biri on çerçeve gerektiriyorsa (beş tanesi hiç kullanılmamış) çalışabilecek dört
işlem yerine sekiz işlem çalıştırabilirdik.

Çoklu programlama derecemizi arttırırsak, belleği aşırı tahsis etmiş oluruz. Her biri on
sayfa boyutunda olan ancak aslında yalnızca beş sayfa kullanan altı işlem çalıştırırsak,
yedeklenecek on çerçeve ile daha yüksek CPU kullanımı ve verimi elde ederiz. Bununla
birlikte, belirli bir veri kümesi için bu işlemlerin her birinin birdenbire on sayfasının tümünü
kullanmaya çalışması ve yalnızca kırk tane mevcutken altmış çerçeveye ihtiyaç duyulmasına
neden olması mümkündür.
Ayrıca, sistem belleğinin yalnızca program sayfalarını tutmak için kullanılmadığını göz
önünde bulundurun. G/Ç için arabellekler de önemli miktarda bellek tüketir. Bu kullanım,
bellek yerleştirme algoritmaları üzerindeki yükü artırabilir. G/Ç'ye ne kadar bellek ayrılacağına
ve sayfaların ne kadar programlanacağına karar vermek önemli bir zorluktur. Bazı sistemler,
G/Ç arabellekleri için sabit bir bellek yüzdesi ayırırken , diğerleri hem işlemlerin hem de G/Ç
alt sisteminin tüm sistem belleği için rekabet etmesine izin verir. Bölüm 14.6, G/Ç arabellekleri
ve sanal bellek teknikleri arasındaki tümleşik ilişkiyi tartışır .

Aşırı bellek tahsisi kendini şu şekilde gösterir. Bir işlem yürütülürken bir sayfa hatası
oluşur. İşletim sistemi, istenen sayfanın ikincil depolamada nerede bulunduğunu belirler,
ancak daha sonra serbest çerçeve listesinde boş çerçeve olmadığını tespit eder; tüm bellek
kullanımda. Bu durum Şekil 10.9'da gösterilmektedir, burada boş çerçeve olmadığı gerçeği
bir soru işareti ile gösterilmektedir.

İşletim sistemi bu noktada birkaç seçeneğe sahiptir. Süreci sonlandırabilir. Ancak,


talep sayfalama, işletim sisteminin bilgisayar sisteminin kullanımını ve verimini iyileştirme
girişimidir. Kullanıcılar, süreçlerinin disk belleği olan bir sistemde çalıştığının farkında
olmamalıdır; sayfalama, kullanıcı için mantıksal olarak şeffaf olmalıdır. Yani bu seçenek en iyi
seçim değil.
İşletim sistemi bunun yerine standart takas ve bir işlemi takas ederek tüm çerçevelerini
serbest bırakabilir ve çoklu program ming seviyesini azaltabilir. Ancak, Bölüm 9.5'te
tartışıldığı gibi, bellek ve takas alanı arasındaki tüm süreçlerin kopyalanmasından
kaynaklanan ek yük nedeniyle standart takas artık çoğu işletim sistemi tarafından
kullanılmamaktadır. Çoğu işletim sistemi artık sayfa değiştirmeyi sayfa değiştirme ile
birleştiriyor , bu bölümün geri kalanında ayrıntılı olarak açıkladığımız bir teknik.

10.4.1 Temel Sayfa Değiştirme

Sayfa değiştirme aşağıdaki yaklaşımı benimser. Hiçbir çerçeve boş değilse, şu anda
kullanılmayan bir çerçeve bulur ve onu serbest bırakırız. Bir çerçeveyi yazarak serbest bırakabiliriz.
Machine Translated by Google

402
Bölüm 10 Sanal Bellek

Şekil 10.9 Sayfa değiştirme ihtiyacı.

içeriği değiştirmek ve sayfa tablosunu (ve diğer tüm tabloları) sayfanın artık bellekte olmadığını
belirtmek için değiştirmek (Şekil 10.10). Artık işlemin hatalı olduğu sayfayı tutmak için serbest
bırakılan çerçeveyi kullanabiliriz. Sayfa hatası hizmeti rutinini, sayfa değiştirmeyi içerecek şekilde
değiştiririz:

1. İkincil depolamada istenen sayfanın konumunu bulun.


2. Boş bir çerçeve bulun:

a. Boş bir çerçeve varsa, onu kullanın.

b. Boş çerçeve yoksa, seçmek için bir sayfa değiştirme algoritması kullanın.
bir kurban çerçevesi.

c. Kurban çerçevesini ikincil belleğe yazın (gerekirse); değiştirmek


buna göre sayfa ve çerçeve tabloları.

3. İstediğiniz sayfayı yeni serbest bırakılan çerçeveye okuyun; sayfayı değiştir ve


çerçeve masaları.

4. Sayfa hatasının oluştuğu yerden işleme devam edin.

Hiçbir çerçeve boş değilse, iki sayfa aktarımının (biri sayfa çıkışı ve diğeri sayfa girişi için) gerekli
olduğuna dikkat edin. Bu durum, sayfa hatası hizmet süresini etkin bir şekilde ikiye katlar ve buna
bağlı olarak etkin erişim süresini artırır.
Bu ek yükü bir değişiklik biti (veya kirli bit) kullanarak azaltabiliriz. Bu şema kullanıldığında,
her sayfa veya çerçeve, donanımda kendisiyle ilişkilendirilmiş bir değiştirme bitine sahiptir. Bir
sayfanın değiştirme biti, sayfadaki herhangi bir bayt yazıldığında, sayfanın değiştirildiğini
belirten donanım tarafından ayarlanır. Değiştirilecek bir sayfa seçtiğimizde, değiştirme bitini
inceleriz. Bit ayarlanmışsa,
10.4 Sayfa Değiştirme 403
Machine Translated by Google

çerçeve geçerli-geçersiz bit

sayfa çıkışı
kurbanı
geçersiz
2 sayfa
0 ben olarak değiştir
1
f v

4 f kurban

için sayfa
tablosunu sıfırla
sayfa tablosu 3
yeni sayfa
istenen
sayfa
sayfa

Destek deposu

fiziksel
hafıza

Şekil 10.10 Sayfa değiştirme.

İkincil depodan okunduğundan sayfanın değiştirildiğini biliyoruz. Bu durumda


sayfayı depoya yazmalıyız. Ancak değiştirme biti ayarlanmazsa , sayfa belleğe
okunduğundan beri değiştirilmemiştir. Bu durumda hafıza sayfasını depoya
yazmamız gerekmez: zaten oradadır. Bu teknik, salt okunur sayfalar için de geçerlidir
(örneğin, ikili kod sayfaları).
Bu tür sayfalar değiştirilemez; bu nedenle istendiğinde atılabilirler.
Bu şema, sayfa değiştirilmemişse G/Ç süresini yarı yarıya azalttığından, bir sayfa
hatasına hizmet vermek için gereken süreyi önemli ölçüde azaltabilir .
Sayfa değiştirme, sayfalama talep etmek için temeldir. Mantıksal bellek ile
fiziksel bellek arasındaki ayrımı tamamlar. Bu mekanizma ile programcılar için daha
küçük bir fiziksel bellek üzerinde devasa bir sanal bellek sağlanabilir. Talep çağrısı
olmadan, mantıksal adresler fiziksel adreslerle eşlenir ve iki adres grubu farklı
olabilir. Bununla birlikte, bir işlemin tüm sayfaları hala fiziksel bellekte olmalıdır.
Talep sayfalama ile mantıksal adres alanının boyutu artık fiziksel bellek tarafından
kısıtlanmaz.
Yirmi sayfalık bir işlemimiz varsa, bunu yalnızca isteğe bağlı sayfalamayı kullanarak
ve gerektiğinde boş bir çerçeve bulmak için bir değiştirme algoritması kullanarak
on karede yürütebiliriz. Değiştirilen bir sayfa değiştirilecekse, içeriği ikincil depoya
kopyalanır. Bu sayfaya daha sonra atıfta bulunulması, sayfa hatasına neden olacaktır.
O zaman, sayfa belleğe geri getirilecek, belki de süreçteki başka bir sayfanın yerini
alacak.
Talep çağrısını uygulamak için iki ana problemi çözmeliyiz: bir çerçeve tahsis
algoritması ve bir sayfa değiştirme algoritması geliştirmeliyiz.
Yani, hafızada birden fazla işlemimiz varsa, her bir işleme kaç çerçeve ayrılacağına
karar vermeliyiz; ve sayfa değişimi gerektiğinde değiştirilecek çerçeveleri
seçmeliyiz. Bu sorunları çözmek için uygun algoritmalar tasarlamak önemli bir
görevdir, çünkü ikincil depolama
Machine Translated by Google

404 Bölüm 10 Sanal Bellek

G/Ç çok pahalıdır. Talep sayfalama yöntemlerindeki küçük iyileştirmeler bile sistem performansında
büyük kazanımlar sağlar.
Birçok farklı sayfa değiştirme algoritması vardır. Her işletim sisteminin
muhtemelen kendi değiştirme planı vardır. Belirli bir değiştirme algoritmasını nasıl
seçeriz? Genel olarak, sayfa hatası oranı en düşük olanı istiyoruz.

Bir algoritmayı, belirli bir bellek referansları dizisinde çalıştırarak ve sayfa


hatalarının sayısını hesaplayarak değerlendiririz. Bellek referansları dizisine referans
dizisi denir . Referans dizilerini yapay olarak üretebiliriz (örneğin bir rastgele sayı
üreteci kullanarak) veya belirli bir sistemi izleyebilir ve her bir hafıza referansının
adresini kaydedebiliriz. İkinci seçenek, çok sayıda veri üretir (saniyede 1 milyon
adres mertebesinde). Veri sayısını azaltmak için iki gerçek kullanıyoruz.

İlk olarak, belirli bir sayfa boyutu için (ve sayfa boyutu genellikle donanım veya
sistem tarafından sabitlenir), adresin tamamı yerine yalnızca sayfa numarasını dikkate
almamız gerekir. İkincisi, eğer bir p sayfasına referansımız varsa, o zaman hemen
takip eden p sayfasına yapılan referanslar asla bir sayfa hatasına neden olmaz. Sayfa
p , ilk referanstan sonra hafızada olacak, bu nedenle hemen takip eden referanslar
arızalanmayacaktır.
Örneğin, belirli bir işlemi izlersek, aşağıdaki adres sırasını kaydedebiliriz:

0100, 0432, 0101, 0612, 0102, 0103, 0104, 0101, 0611, 0102, 0103,
0104, 0101, 0610, 0102, 0103, 0104, 0101, 0609, 0102, 0105

Sayfa başına 100 baytta bu sıra, aşağıdaki referans dizesine indirgenir:

1, 4, 1, 6, 1, 6, 1, 6, 1, 6, 1

Belirli bir referans dizgisi ve sayfa değiştirme algoritması için sayfa hatalarının
sayısını belirlemek için, mevcut sayfa çerçevelerinin sayısını da bilmemiz gerekir.
Açıktır ki, mevcut çerçeve sayısı arttıkça sayfa hatalarının sayısı azalır. Daha önce ele
alınan referans dizisi için, örneğin, üç veya daha fazla çerçevemiz olsaydı, yalnızca
üç hatamız olurdu - her sayfaya ilk referans için bir hata. Buna karşılık, yalnızca bir
çerçeve mevcut olduğunda, her referansta bir yenisini alırdık ve bu da on bir hatayla
sonuçlanırdı. Genel olarak, Şekil 10.11'deki gibi bir eğri bekliyoruz. Çerçeve sayısı
arttıkça, sayfa hatalarının sayısı bir miktar minimum seviyeye düşer. Elbette fiziksel
bellek eklemek çerçeve sayısını artırır.

Daha sonra birkaç sayfa değiştirme algoritmasını göstereceğiz. Bunu yaparken


referans dizesini kullanırız
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1

üç çerçeveli bir hafıza için.

10.4.2 FIFO Sayfasının Değiştirilmesi

En basit sayfa değiştirme algoritması, ilk giren ilk çıkar (FIFO) algoritmasıdır. Bir FIFO
değiştirme algoritması, her sayfa ile o sayfanın belleğe getirildiği zamanı ilişkilendirir.
Bir sayfanın değiştirilmesi gerektiğinde, en eski sayfa seçilir. Bir
Machine Translated by Google

10.4 Sayfa Değiştirme 405

16

14

12

10

8
6
4

123 456
çerçeve sayısı

Şekil 10.11 Çerçeve sayısına karşı sayfa hatalarının grafiği.

sayfa getirilir. Tüm sayfaları hafızada tutmak için bir FIFO kuyruğu oluşturabiliriz.
Kuyruğun başındaki sayfayı değiştiriyoruz. Bir sayfa belleğe getirildiğinde onu
kuyruğun sonuna ekliyoruz.
Örnek referans dizimiz için, üç çerçevemiz başlangıçta boştur. İlk üç referans
(7, 0, 1) sayfa hatalarına neden olur ve bu boş çerçevelere getirilir. Sonraki referans
(2), sayfa 7'nin yerini alır, çünkü sayfa 7 önce getirilir. 0 sonraki referans ve 0 zaten
hafızada olduğundan, bu referans için bir hatamız yok. 3'e yapılan ilk referans,
şimdi ilk sırada olduğundan, sayfa 0'ın değiştirilmesiyle sonuçlanır. Bu değiştirme
nedeniyle, 0'a bir sonraki referans hata verecektir. Sayfa 1 daha sonra sayfa 0 ile
değiştirilir. Bu işlem Şekil 10.12'de gösterildiği gibi devam eder. Her hata
oluştuğunda, üç karemizde hangi sayfaların olduğunu gösteriyoruz. Toplamda on
beş kusur var.
FIFO sayfa değiştirme algoritmasının anlaşılması ve programlanması kolaydır .
Ancak performansı her zaman iyi değildir. Bir yandan değiştirilen sayfa, uzun
zaman önce kullanılan ve artık ihtiyaç duyulmayan bir başlatma modülü olabilir. Öte
yandan, erken başlatılmış ve sürekli kullanımda olan, yoğun olarak kullanılan bir
değişken içerebilir.
Dikkat edin, aktif kullanımda olan bir sayfayı değiştirmeyi seçsek bile her şey
hala düzgün çalışıyor. Aktif bir sayfayı yenisiyle değiştirdikten sonra

referans dizisi
7012030423 0 3 212 0 1 7 0 1

77 7 2 2 2 4 4 4 0 0 0 7 7 7
0 0 0 3 3 3 2 2 2 1 1 1 0 0
1 1 1 0 0 0 3 3 3 2 2 2 1

sayfa çerçeveleri

Şekil 10.12 FIFO sayfa değiştirme algoritması.


Machine Translated by Google

406 Bölüm 10 Sanal Bellek

16

14

12

10

8
6
4

123 4567
çerçeve sayısı

Şekil 10.13 Bir referans dizisinde FIFO değişimi için sayfa hatası eğrisi.

bir, aktif sayfayı almak için neredeyse anında bir hata meydana gelir. Etkin sayfayı
belleğe geri getirmek için başka bir sayfanın değiştirilmesi gerekir. Bu nedenle, hatalı
bir değiştirme seçeneği sayfa hatası oranını artırır ve işlemin yürütülmesini yavaşlatır.
Bununla birlikte, yanlış yürütmeye neden olmaz.
FIFO sayfa değiştirme ile olası sorunları göstermek için
algoritma, aşağıdaki referans dizesini göz önünde bulundurun:

1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5

Şekil 10.13, bu referans dizisi için sayfa hatalarının eğrisini, mevcut çerçevelerin sayısına
karşı gösterir. Dört çerçevenin (on) hata sayısının, üç çerçevenin (dokuz) hata sayısından
daha fazla olduğuna dikkat edin! Bu en beklenmedik sonuç, Belady'nin anomalisi olarak
bilinir : bazı sayfa değiştirme algoritmaları için, ayrılan çerçeve sayısı arttıkça sayfa
hatası oranı artabilir . Bir işleme daha fazla bellek vermenin performansını iyileştirmesini
beklerdik. Bazı erken araştırmalarda, araştırmacılar bu varsayımın her zaman doğru
olmadığını fark ettiler. Sonuç olarak Belady'nin anomalisi keşfedildi.

10.4.3 Optimum Sayfa Değiştirme

Belady'nin anomalisinin keşfinin bir sonucu, optimal bir sayfa değiştirme algoritması
arayışıydı - tüm algoritmalar arasında en düşük sayfa hatası oranına sahip olan ve
Belady'nin anomalisinden asla zarar görmeyecek olan algoritma. Böyle bir algoritma
mevcuttur ve OPT veya MIN olarak adlandırılmıştır. Bu basitçe şudur:

En uzun süre kullanılmayacak sayfayı değiştirin.

Bu sayfa değiştirme algoritmasının kullanılması, sabit sayıda çerçeve için mümkün


olan en düşük sayfa hatası oranını garanti eder.
Örneğin, örnek referans dizimizde, en uygun sayfa değiştirme algoritması, Şekil
10.14'te gösterildiği gibi dokuz sayfa hatası verir. İlk üç referans, üç boş çerçeveyi
dolduran hatalara neden olur. Sayfa 2'ye yapılan atıf, sayfa 7'nin yerini alır, çünkü sayfa
7, referans 18'e kadar kullanılmayacaktır, oysa
Machine Translated by Google

10.4 Sayfa Değiştirme 407

referans dizisi
7012030423 0 3 212 0 1 7 0 1

77 7 2 2 2 2 2 7
0 0 0 0 4 0 0 0
1 1 3 3 3 1 1

sayfa çerçeveleri

Şekil 10.14 En uygun sayfa değiştirme algoritması.

sayfa 0, 5'te ve sayfa 1, 14'te kullanılacaktır. Sayfa 1, bellekteki üç sayfanın sonuncusu


olacağından, sayfa 3'e yapılan referans, sayfa 1'in yerini alır. Yalnızca dokuz sayfa hatasıyla
optimum değiştirme, on beş hatayla sonuçlanan bir FIFO algoritmasından çok daha
iyidir . (Bütün algoritmaların maruz kalması gereken ilk üçünü göz ardı edersek, optimal
değiştirme FIFO değiştirmeden iki kat daha iyidir.) Aslında, hiçbir değiştirme algoritması
bu referans dizisini dokuzdan az hatayla üç çerçevede işleyemez.

Ne yazık ki, optimal sayfa değiştirme algoritmasını uygulamak zordur, çünkü referans
dizgisi hakkında gelecekte bilgi sahibi olmayı gerektirir.
(Bölüm 5.3.2'de SJF CPU-zamanlama algoritması ile benzer bir durumla karşılaştık .) Sonuç
olarak, karşılaştırma çalışmaları için en uygun algoritma kullanılmaktadır. Örneğin, yeni
bir algoritma optimal olmasa da, en kötü ihtimalle yüzde 12,3 ve ortalama yüzde 4,7 içinde
olduğunu bilmek faydalı olabilir.

10.4.4 LRU Sayfa Değiştirme

Optimal algoritma uygulanabilir değilse, belki de optimal algoritmanın bir tahmini


mümkündür. FIFO ve OPT algoritmaları arasındaki temel ayrım (zamanda geriye ve ileriye
bakmak dışında) FIFO algoritmasının bir sayfanın belleğe getirildiği zamanı kullanması,
oysa OPT algoritmasının bir sayfanın kullanılacağı zamanı kullanmasıdır. . Yakın geçmişi
yakın geleceğin bir tahmini olarak kullanırsak, o zaman en uzun süredir kullanılmayan
sayfayı değiştirebiliriz. Bu yaklaşım en az kullanılan (LRU) algoritmadır.

LRU değiştirme, her sayfayla o sayfanın son kullanım zamanını ilişkilendirir.


Bir sayfanın değiştirilmesi gerektiğinde, LRU en uzun süredir kullanılmayan sayfayı seçer.
Bu stratejiyi, ileriye değil, zamanda geriye bakan en uygun sayfa değiştirme algoritması
olarak düşünebiliriz.
(Garip bir şekilde, SR'nin bir referans dizisi S'nin tersi olmasına izin verirsek , o zaman S
üzerindeki OPT algoritması için sayfa hatası oranı, SR üzerindeki OPT algoritması için sayfa
hatası oranı ile aynıdır . Benzer şekilde, sayfa hatası oranı S üzerindeki LRU algoritmasının
hızı , SR üzerindeki LRU algoritmasının sayfa hatası oranı ile aynıdır .)
Örnek referans dizimize LRU değiştirme uygulamasının sonucu Şekil 10.15'te
gösterilmektedir. LRU algoritması on iki hata üretir . İlk beş hatanın optimum değiştirme
için olanlarla aynı olduğuna dikkat edin. Ancak, 4. sayfaya başvuru yapıldığında, LRU
değişimi, bellekteki üç çerçeveden 2. sayfanın en yakın zamanda kullanıldığını görür.
Böylece, LRU algoritması, 2. sayfanın kullanılmak üzere olduğunu bilmeden 2. sayfayı
değiştirir. Daha sonra arızalandığında
Machine Translated by Google

408 Bölüm 10 Sanal Bellek


referans dizisi
7012030423 0 3 212 0 1 7 0 1

77 7 2 2 4 4 4 0 1 1 1
0 0 0 0 0 0 3 3 3 0 0
1 1 3 3 2 2 2 2 2 7

sayfa çerçeveleri

Şekil 10.15 LRU sayfa değiştirme algoritması.

2. sayfa için, LRU algoritması 3. sayfanın yerini alır, çünkü artık bellekteki üç sayfa
arasında en az kullanılanıdır. Bu sorunlara rağmen, on iki arızalı LRU değiştirme,
on beş arızalı FIFO değiştirmeden çok daha iyidir .
LRU politikası genellikle bir sayfa değiştirme algoritması olarak kullanılır ve iyi
olduğu düşünülür . En büyük sorun, LRU değişiminin nasıl uygulanacağıdır .
Bir LRU sayfa değiştirme algoritması, önemli ölçüde donanım yardımı gerektirebilir.
Sorun, son kullanım zamanına göre tanımlanan çerçeveler için bir sıra belirlemektir.
İki uygulama mümkündür:

• Sayaçlar. En basit durumda, her sayfa tablosu girişiyle bir kullanım süresi alanı
ilişkilendiririz ve CPU'ya bir mantıksal saat veya sayaç ekleriz. Her bellek referansı
için saat artırılır. Bir sayfaya atıfta bulunulduğunda, saat kaydının içeriği o
sayfanın sayfa tablosu girişindeki kullanım süresi alanına kopyalanır. Bu şekilde,
her zaman her sayfaya yapılan son referansın “zamanına” sahibiz. Sayfayı en
küçük zaman değeriyle değiştiriyoruz. Bu şema, LRU sayfasını bulmak için
sayfa tablosunun aranmasını ve her bellek erişimi için belleğe (sayfa
tablosundaki kullanım süresi alanına) bir yazma gerektirir. Sayfa tabloları
değiştirildiğinde ( CPU zamanlaması nedeniyle) zamanlar da korunmalıdır .
Saatin taşması dikkate alınmalıdır.

• Yığın. LRU değiştirmeyi uygulamaya yönelik başka bir yaklaşım, bir sayfa
numarası yığını tutmaktır. Bir sayfaya atıfta bulunulduğunda, yığından çıkarılır
ve en üste konur. Bu şekilde, en son kullanılan sayfa her zaman yığının en
üstünde ve en az kullanılan sayfa her zaman en altta olur (Şekil 10.16). Girişlerin
yığının ortasından kaldırılması gerektiğinden, bu yaklaşımı bir baş işaretçi ve
bir kuyruk işaretçisi ile çift bağlantılı bir liste kullanarak uygulamak en iyisidir.
Bir sayfayı kaldırmak ve yığının en üstüne koymak, en kötü ihtimalle altı
işaretçiyi değiştirmeyi gerektirir. Her güncelleme biraz daha pahalıdır, ancak
değiştirme arayışı yoktur; kuyruk işaretçisi, LRU sayfası olan yığının altını
gösterir . Bu yaklaşım, özellikle LRU değişiminin yazılım veya mikro kod
uygulamaları için uygundur.

Optimal değiştirme gibi, LRU değiştirme de Belady'nin anomalisinden


etkilenmez. Her ikisi de, Belady'nin anormalliğini asla gösteremeyen yığın
algoritmaları adı verilen bir sayfa değiştirme algoritmaları sınıfına aittir . Yığın
algoritması, n çerçeve için bellekteki sayfalar kümesinin her zaman n ile bellekte
olacak sayfalar kümesinin bir alt kümesi olduğunun gösterilebildiği bir algoritmadır.
10.4 Sayfa Değiştirme 409
Machine Translated by Google

referans dizisi
4707101212 2 7 1

2 7
ab
1 2

0 1

7 0

4 4

önce b'den
yığın sonra
a yığın

Şekil 10.16 En son sayfa referanslarını kaydetmek için bir yığın kullanımı.

+ 1 çerçeve. LRU değişimi için, bellekteki sayfalar en son başvurulan n sayfa


olacaktır. Çerçeve sayısı artırılırsa, bu n sayfa en son başvurulan sayfa olmaya devam
edecek ve bu nedenle bellekte kalmaya devam edecektir.
Standart TLB kayıtlarının ötesinde donanım yardımı olmadan LRU'nun hiçbir
uygulamasının düşünülemeyeceğine dikkat edin . Her bellek referansı için saat
alanlarının veya yığının güncellenmesi yapılmalıdır . Yazılımın bu tür veri yapılarını
güncellemesine izin vermek için her başvuru için bir kesme kullanacak olsaydık, her
bellek referansını en az on kat yavaşlatır, dolayısıyla her işlemi on kat yavaşlatırdı.
Çok az sistem, bellek yönetimi için bu düzeydeki ek yükü tolere edebilir.

10.4.5 LRU-Yaklaşıklık Sayfasının Değiştirilmesi

Pek çok bilgisayar sistemi, gerçek LRU sayfa değişimi için yeterli donanım desteği
sağlamaz . Aslında, bazı sistemler donanım desteği sağlamaz ve diğer sayfa
değiştirme algoritmaları ( FIFO algoritması gibi) kullanılmalıdır.
Bununla birlikte, birçok sistem bir referans biti şeklinde bir miktar yardım sağlar.
Bir sayfanın referans biti, o sayfaya her başvuru yapıldığında donanım tarafından
belirlenir (sayfadaki herhangi bir bayta okuma veya yazma). Referans bitleri, sayfa
tablosundaki her girişle ilişkilendirilir.
Başlangıçta, tüm bitler işletim sistemi tarafından (0'a kadar) temizlenir. Bir işlem
yürütülürken, başvurulan her sayfayla ilişkili bit donanım tarafından (1'e) ayarlanır.
Bir süre sonra, kullanım sırasını bilmesek de referans bitlerini inceleyerek hangi
sayfaların kullanıldığını ve hangilerinin kullanılmadığını belirleyebiliriz . Bu bilgi,
LRU değişimine yaklaşan birçok sayfa değiştirme algoritmasının temelidir .

10.4.5.1 Ek-Referans-Bits Algoritması Referans

bitlerini düzenli aralıklarla kaydederek ek sıralama bilgisi elde edebiliriz. Bellekte bir
tablodaki her sayfa için 8 bitlik bir bayt tutabiliriz.
Düzenli aralıklarla (örneğin, her 100 milisaniyede bir), bir zamanlayıcı kesmesi,
kontrolü işletim sistemine aktarır. İşletim sistemi, her sayfanın referans bitini,
diğer bitleri sağa kaydırarak, 8 bitlik baytın yüksek sıralı bitine kaydırır.
Machine Translated by Google

410 Bölüm 10 Sanal Bellek


1 bit ile ve düşük dereceli bitin atılması. Bu 8 bitlik kaydırma kayıtları, son sekiz zaman dilimi
için sayfa kullanımının geçmişini içerir. Örneğin, vardiya kaydı 00000000 içeriyorsa, sayfa
sekiz zaman periyodu boyunca kullanılmamıştır.
Her periyotta en az bir kez kullanılan bir sayfanın kaydırmalı kayıt değeri 11111111'dir.
Geçmiş kayıt değeri 11000100 olan bir sayfa 01110111 değerinden daha yakın zamanda
kullanılmıştır. Bu 8 bitlik baytları şu şekilde yorumlarsak işaretsiz tamsayılar için, en düşük
numaralı sayfa LRU sayfasıdır ve değiştirilebilir. Bununla birlikte, sayıların benzersiz olmasının
garanti edilmediğine dikkat edin.
Tüm sayfaları en küçük değerle değiştirebilir (takas edebilir) veya aralarından seçim yapmak
için FIFO yöntemini kullanabiliriz.
Kaydırma yazmacına dahil edilen geçmiş bitlerinin sayısı elbette değiştirilebilir ve
güncellemeyi olabildiğince hızlı yapmak için (mevcut donanıma bağlı olarak) seçilir. Aşırı
durumda, sayı sıfıra indirgenebilir ve yalnızca referans biti bırakılabilir. Bu algoritmaya ikinci
şans sayfası değiştirme algoritması denir .

10.4.5.2 İkinci Şans Algoritması İkinci şans

değiştirmenin temel algoritması, bir FIFO değiştirme algoritması ritmidir. Ancak bir sayfa
seçildiğinde, onun referans bitini inceleriz. Değer 0 ise bu sayfayı değiştirmeye geçiyoruz;
ancak referans biti 1'e ayarlanmışsa, sayfaya ikinci bir şans veriyoruz ve bir sonraki FIFO
sayfasını seçmeye geçiyoruz.
Bir sayfaya ikinci bir şans verildiğinde, referans biti temizlenir ve varış zamanı mevcut zamana
sıfırlanır. Bu nedenle, ikinci bir şans verilen bir sayfa, diğer tüm sayfalar değiştirilene (veya
ikinci bir şans verilene) kadar değiştirilmeyecektir. Ek olarak, bir sayfa referans bitini korumak
için yeterince sık kullanılıyorsa, asla değiştirilmeyecektir.

İkinci şans algoritmasını (bazen saat algoritması olarak anılır ) uygulamanın bir yolu
dairesel bir kuyruktur. Bir işaretçi (yani, saatteki bir el), sonraki hangi sayfanın değiştirileceğini
gösterir. Bir çerçeve gerektiğinde, işaretçi 0 referans biti olan bir sayfa bulana kadar ilerler.
İlerledikçe referans bitlerini temizler (Şekil 10.17). Bir kurban sayfası bulunduğunda, sayfa
değiştirilir ve yeni sayfa o konumda dairesel kuyruğa eklenir.

En kötü durumda, tüm bitler ayarlandığında, işaretçinin tüm kuyruk boyunca dönüp her
sayfaya ikinci bir şans verdiğine dikkat edin. Değiştirilecek sonraki sayfayı seçmeden önce
tüm referans bitlerini temizler. Tüm bitler ayarlanmışsa, ikinci şans değiştirme, FIFO
değiştirmeye dönüşür.

10.4.5.3 Gelişmiş İkinci Şans Algoritması İkinci şans

algoritmasını, referans biti ve değiştirme bitini (Bölüm 10.4.1'de açıklanmıştır) sıralı bir çift
olarak dikkate alarak geliştirebiliriz. Bu iki bit ile aşağıdaki dört olası sınıfa sahibiz:

1. (0, 0) ne yakın zamanda kullanılmış ne de değiştirilmiş—değiştirilecek en iyi

sayfa 2. (0, 1) yakın zamanda kullanılmamış ancak değiştirilmiş—o kadar iyi değil çünkü
sayfanın değiştirilmeden önce yazılması gerekecek 3. (1 , 0) yakın zamanda kullanılmış

ama temiz—muhtemelen yakında tekrar kullanılacak


10.4 Sayfa Değiştirme 411
Machine Translated by Google
referans sayfalar referans sayfalar
bitleri bitleri

0 0

0 0

1 0
sonraki kurban

1 0

0 0

1 1

1 1

dairesel sayfa sırası dairesel sayfa sırası

(a) (b)

Şekil 10.17 İkinci şans (saat) sayfa değiştirme algoritması.

4. (1, 1) yakın zamanda kullanılmış ve değiştirilmiş—muhtemelen yakında tekrar


kullanılacak ve sayfanın değiştirilebilmesi için ikincil depolamaya yazılması
gerekecek

Her sayfa bu dört sınıftan birindedir. Sayfa değişimi istendiğinde, saat


algoritmasındakiyle aynı şemayı kullanırız; ancak işaret ettiğimiz sayfanın referans
bitinin 1'e ayarlanmış olup olmadığını incelemek yerine o sayfanın ait olduğu sınıfı
inceleriz. Boş olmayan en düşük sınıfta karşılaşılan ilk sayfayı değiştiriyoruz.
Değiştirilecek bir sayfa bulmadan önce dairesel kuyruğu birkaç kez taramamız
gerekebileceğine dikkat edin. Bu algoritma ile daha basit saat algoritması arasındaki
en büyük fark, burada gerekli I/O sayısını azaltmak için değiştirilmiş sayfaları tercih
etmemizdir .

10.4.6 Sayıma Dayalı Sayfa Değiştirme

Sayfa değiştirme için kullanılabilecek başka birçok algoritma vardır. Örneğin, her
sayfaya yapılan referansların sayısının bir sayacını tutabilir ve aşağıdaki iki şemayı
geliştirebiliriz.

• En az kullanılan (LFU) sayfa değiştirme algoritması, en küçük sayıya sahip


sayfanın değiştirilmesini gerektirir. Bu seçimin nedeni aktif olarak kullanılan
bir sayfanın referans sayısının fazla olmasıdır. Bununla birlikte, bir sayfa,
çalışmanın ilk aşamasında yoğun olarak kullanıldığında bir sorun ortaya çıkar.
Machine Translated by Google

412 Bölüm 10 Sanal Bellek

bir süreç ama sonra bir daha asla kullanılmaz. Yoğun olarak kullanıldığı için
sayıca çoktur ve artık ihtiyaç duyulmasa da hafızada kalır.
Bir çözüm, sayıları düzenli aralıklarla 1 bit sağa kaydırarak, katlanarak azalan bir
ortalama kullanım sayısı oluşturmaktır. • En sık kullanılan (MFU) sayfa değiştirme

algoritması, en küçük sayıya sahip sayfanın muhtemelen yeni getirildiği ve henüz


kullanılmadığı argümanına dayanır.

Tahmin edebileceğiniz gibi, ne MFU ne de LFU değişimi yaygın değildir. Bu


algoritmaların uygulanması pahalıdır ve OPT değiştirmeyi iyi tahmin etmezler.

10.4.7 Sayfa Arabelleğe Alma Algoritmaları

Belirli bir sayfa değiştirme algoritmasına ek olarak genellikle başka prosedürler de


kullanılır. Örneğin, sistemler genellikle boş çerçevelerden oluşan bir havuz tutar.
Bir sayfa hatası oluştuğunda, daha önce olduğu gibi bir kurban çerçevesi seçilir.
Ancak, kurban yazılmadan önce istenen sayfa havuzdan serbest bir çerçeveye
okunur. Bu prosedür, kurban sayfasının yazılmasını beklemeden sürecin mümkün
olan en kısa sürede yeniden başlatılmasını sağlar. Kurban daha sonra yazıldığında,
çerçevesi serbest çerçeve havuzuna eklenir.
Bu fikrin bir uzantısı, değiştirilmiş sayfaların bir listesini tutmaktır. Çağrı cihazı
boşta kaldığında, değiştirilmiş bir sayfa seçilir ve ikincil depolamaya yazılır.
Değiştirme biti daha sonra sıfırlanır. Bu şema, değiştirilmek üzere seçildiğinde bir
sayfanın temiz olma ve değiştirilmesi gerekmeme olasılığını artırır.
yazılmış.

Başka bir değişiklik, bir boş kare havuzu tutmak, ancak her karede hangi sayfanın
olduğunu hatırlamaktır. Çerçeve ikincil depolamaya yazıldığında çerçeve içeriği
değiştirilmediğinden, çerçeve yeniden kullanılmadan önce gerekirse eski sayfa
doğrudan serbest çerçeve havuzundan yeniden kullanılabilir. Bu durumda G/Ç'ye
gerek yoktur. Bir sayfa hatası oluştuğunda, öncelikle istenen sayfanın serbest çerçeve
havuzunda olup olmadığını kontrol ederiz. Değilse, boş bir çerçeve seçmeli ve onu
okumalıyız.
UNIX sisteminin bazı sürümleri, bu yöntemi ikinci şans algoritması ile birlikte
kullanır. Yanlış kurban sayfasının seçilmesi durumunda maruz kalınan cezayı azaltmak
için herhangi bir sayfa değiştirme algoritmasına faydalı bir ekleme olabilir. Bu ve
diğer değişiklikleri Bölüm 10.5.3'te açıklıyoruz.

10.4.8 Uygulamalar ve Sayfa Değiştirme


Bazı durumlarda, işletim sisteminin sanal belleği aracılığıyla verilere erişen
uygulamalar, işletim sisteminin hiç arabelleğe alma sağlamadığından daha kötü
performans gösterir. Tipik bir örnek, kendi bellek yönetimini ve G/Ç arabelleğini
sağlayan bir veritabanıdır . Bunun gibi uygulamalar, genel amaçlı kullanım için
algoritmalar uygulayan bir işletim sisteminden daha iyi bellek kullanımını ve depolama
kullanımını anlar. Ayrıca, işletim sistemi G/Ç'yi arabelleğe alıyorsa ve uygulama da
bunu yapıyorsa, bir G/Ç kümesi için iki kez bellek kullanılıyor demektir.

Başka bir örnekte, veri ambarları sıklıkla büyük ardışık depolama okumaları,
ardından hesaplamalar ve yazmalar gerçekleştirir. LRU algoritması _
10.5 Çerçevelerin Tahsisi 413
Machine Translated by Google

eski sayfaları silip yenilerini korurken, uygulamanın yeni sayfalardansa eski sayfaları okuması
daha olasıdır (sıralı okumalarını yeniden başlattığı için). Burada, MFU aslında LRU'dan daha
verimli olacaktır .
Bu tür sorunlar nedeniyle, bazı işletim sistemleri, özel programlara, herhangi bir
dosya sistemi veri yapısı olmaksızın, büyük bir ardışık mantıksal blok dizisi olarak
ikincil bir depolama bölümü kullanma yeteneği verir. Bu dizi bazen ham disk olarak
adlandırılır ve bu diziye yönelik G/Ç , ham G/Ç olarak adlandırılır. Ham G/Ç , dosya G/
Ç talep sayfalama, dosya kilitleme, önceden getirme, alan ayırma, dosya adları ve
dizinler gibi tüm dosya sistemi hizmetlerini atlar . Bazı uygulamaların kendi özel
amaçlı depolama hizmetlerini ham bir bölüm üzerinde uygularken daha verimli
olmasına rağmen, çoğu uygulamanın normal dosya sistemi hizmetlerini
kullandıklarında daha iyi performans gösterdiğine dikkat edin.

10.5 Çerçevelerin Tahsisi

Tahsis konusuna dönüyoruz. Sabit miktarda boş belleği çeşitli işlemler arasında
nasıl tahsis ederiz? 93 boş çerçevemiz ve iki işlemimiz varsa, her işlem kaç kare alır?

128 çerçeveli basit bir sistem durumu düşünün. İşletim sistemi, kullanıcı işlemi
için 93 çerçeve bırakarak 35 alabilir. Saf talep çağrısı altında, 93 çerçevenin tümü
başlangıçta serbest çerçeve listesine alınır. Bir kullanıcı işlemi yürütmeye
başladığında, bir dizi sayfa hatası üretecektir. İlk 93 sayfa hatalarının tümü, serbest
çerçeve listesinden ücretsiz çerçeveler alacaktır. Serbest çerçeve listesi
tükendiğinde, 94. sayfayla değiştirilecek 93 bellek içi sayfadan birini seçmek için
bir sayfa değiştirme algoritması kullanılır ve bu böyle devam eder. İşlem sona
erdiğinde, 93 kare bir kez daha serbest kare listesine yerleştirilir.

Bu basit stratejide birçok varyasyon var. İşletim sisteminin tüm arabellek ve


tablo alanını serbest çerçeve listesinden ayırmasını isteyebiliriz.
Bu alan işletim sistemi tarafından kullanılmadığında, kullanıcı çağrılarını
desteklemek için kullanılabilir. Serbest çerçeve listesinde her zaman üç boş
çerçeveyi ayırmaya çalışabiliriz. Böylece, bir sayfa hatası oluştuğunda, sayfaya
girilebilecek boş bir çerçeve vardır. Sayfa değiş tokuşu yapılırken, bir değiştirme
seçilebilir ve bu daha sonra kullanıcı işlemi yürütülmeye devam ederken depolama
cihazına yazılır. Diğer varyantlar da mümkündür, ancak temel strateji açıktır:
kullanıcı işlemine herhangi bir boş çerçeve tahsis edilir.

10.5.1 Minimum Çerçeve Sayısı

Çerçevelerin tahsisine yönelik stratejilerimiz çeşitli şekillerde sınırlandırılmıştır.


Örneğin, toplam kullanılabilir çerçeve sayısından fazlasını tahsis edemeyiz (sayfa
paylaşımı olmadığı sürece). Ayrıca en az minimum sayıda çerçeve tahsis etmeliyiz.
Burada, ikinci gereksinime daha yakından bakıyoruz.
En az minimum sayıda çerçeve ayırmanın bir nedeni performansla ilgilidir.
Açıktır ki, her işleme ayrılan çerçeve sayısı azaldıkça, sayfa hatası oranı artar, bu da
işlemin yürütülmesini yavaşlatır. Ayrıca, yürütme talimatı tamamlanmadan önce bir
sayfa hatası oluştuğunda, talimatın yeniden başlatılması gerektiğini unutmayın.
Sonuç olarak, herhangi bir komutun başvurabileceği tüm farklı sayfaları tutacak
yeterli çerçeveye sahip olmamız gerekir.
414 Bölüm 10 Sanal Bellek
Machine Translated by Google

Örneğin, tüm bellek referans yönergelerinin yalnızca bir bellek adresine


başvurabileceği bir makine düşünün. Bu durumda, talimat için en az bir çerçeveye
ve bellek referansı için bir çerçeveye ihtiyacımız var. Ek olarak, tek düzeyli dolaylı
adreslemeye izin verilirse (örneğin, çerçeve 16'daki bir yükleme talimatı, çerçeve
23'e dolaylı bir referans olan çerçeve 0'daki bir adrese başvurabilir), o zaman
sayfalama işlem başına en az üç çerçeve gerektirir. (Bir işlemin yalnızca iki çerçevesi
varsa ne olabileceğini düşünün.)
Minimum çerçeve sayısı bilgisayar mimarisi tarafından belirlenir.
Örneğin, belirli bir mimari için taşıma talimatı bazı adresleme modları için birden
fazla kelime içeriyorsa, talimatın kendisi iki çerçeveyi birleştirebilir. Ek olarak, iki
işlenenin her biri dolaylı referanslar olabilirse, toplam altı çerçeve gereklidir. Başka
bir örnek olarak, Intel 32- ve 64-bit mimarileri için taşıma talimatı, verilerin yalnızca
kayıttan kayda ve kayıtlar ile bellek arasında hareket etmesine izin verir; doğrudan
bellekten belleğe hareketine izin vermez, böylece bir işlem için gereken minimum
çerçeve sayısını sınırlar.

İşlem başına minimum çerçeve sayısı mimari tarafından tanımlanırken,


maksimum sayı kullanılabilir fiziksel bellek miktarı ile tanımlanır. Arada, çerçeve
tahsisinde hala önemli bir seçimimiz var.

10.5.2 Tahsis Algoritmaları

m çerçeveyi n süreç arasında bölmenin en kolay yolu, herkese eşit bir pay, m/n
çerçeve vermektir (şu an için işletim sisteminin ihtiyaç duyduğu çerçeveleri yok
sayarak). Örneğin, 93 çerçeve ve 5 süreç varsa, her süreç 18 çerçeve alacaktır. Kalan
3 çerçeve, serbest çerçeve arabellek havuzu olarak kullanılabilir.
Bu şemaya eşit tahsis denir .
Bir alternatif, çeşitli işlemlerin farklı miktarlarda belleğe ihtiyaç duyacağını
kabul etmektir. 1 KB çerçeve boyutuna sahip bir sistem düşünün . 10 KB'lık küçük bir
öğrenci süreci ve 127 KB'lık etkileşimli bir veritabanı, 62 boş çerçeveli bir sistemde
çalışan iki süreç ise, her sürece 31 çerçeve vermek pek mantıklı değil. Öğrenci
süreci 10'dan fazla çerçeveye ihtiyaç duymaz, bu nedenle diğer 21'i kesinlikle boşa
harcanır.
Bu sorunu çözmek için , her işleme boyutuna göre kullanılabilir belleği
ayırdığımız orantılı tahsisi kullanabiliriz. pi işlemi için sanal belleğin boyutu si olsun
ve tanımla

S= si .

Ardından, mevcut çerçevelerin toplam sayısı m ise, ai'nin yaklaşık olarak pi işlemi
olduğu yere ai çerçevelerini tahsis ederiz ,

ai = si /S × m.

Elbette, her ai'yi , toplamı m'yi aşmayan, talimat kümesinin gerektirdiği minimum
çerçeve sayısından daha büyük bir tam sayı olacak şekilde ayarlamamız gerekir .

Orantılı tahsis ile 62 kareyi, biri 10 sayfadan biri 127 sayfadan biri olmak üzere
iki işlem arasında sırasıyla 4 kare ve 57 kare ayırarak bölerdik.
10.5 Çerçevelerin Tahsisi 415
Machine Translated by Google
10/137 × 62 4 ve
127/137 × 62 57.

Bu şekilde, her iki süreç de mevcut çerçeveleri eşit olarak değil “ihtiyaçlarına” göre
paylaşır.
Hem eşit hem de orantılı tahsiste, elbette tahsis, çoklu programlama seviyesine
göre değişebilir. Çoklu programlama seviyesi artırılırsa, her işlem yeni işlem için
gereken belleği sağlamak için bazı çerçeveleri kaybeder. Tersine, çoklu
programlama seviyesi düşerse, ayrılan sürece tahsis edilen çerçeveler kalan süreçlere
yayılabilir.

Eşit veya orantılı tahsisle, yüksek öncelikli bir sürecin düşük öncelikli bir süreçle
aynı şekilde ele alındığına dikkat edin. Bununla birlikte, tanımı gereği, düşük
öncelikli süreçlerin zararına, yürütmesini hızlandırmak için yüksek öncelikli sürece
daha fazla bellek vermek isteyebiliriz. Bir çözüm, çerçeve oranının, süreçlerin
göreceli boyutlarına değil, daha çok süreçlerin önceliklerine veya bir boyut ve
öncelik kombinasyonuna bağlı olduğu bir orantılı tahsis şeması kullanmaktır.

10.5.3 Küresel ve Yerel Tahsis

Çerçevelerin çeşitli süreçlere atanma biçimindeki bir diğer önemli faktör de sayfa
değiştirmedir. Çerçeveler için yarışan birden çok süreçle, sayfa değiştirme
algoritmalarını iki geniş kategoride sınıflandırabiliriz: genel değiştirme ve yerel
değiştirme. Genel değiştirme, bir çerçevenin halihazırda başka bir işleme tahsis
edilmiş olsa bile, tüm çerçeveler kümesinden bir yedek çerçeve seçmesine izin verir;
yani, bir süreç diğerinden bir çerçeve alabilir. Yerel değiştirme, her işlemin yalnızca
kendi tahsis edilmiş çerçeve kümesinden seçim yapmasını gerektirir.

Örneğin, yüksek öncelikli süreçlerin, değiştirme için düşük öncelikli


süreçlerden çerçeveleri seçmesine izin verdiğimiz bir tahsis şemasını düşünün.
Bir süreç, kendi çerçeveleri arasından veya daha düşük öncelikli herhangi bir sürecin
çerçeveleri arasından bir değiştirme seçebilir. Bu yaklaşım, yüksek öncelikli bir
sürecin, düşük öncelikli bir süreç pahasına çerçeve tahsisini artırmasına izin verir.
Yerel değiştirme stratejisinde, bir sürece tahsis edilen çerçevelerin sayısı
değişmezken, genel değiştirme ile, bir işlem yalnızca diğer işlemlere tahsis edilen
çerçeveleri seçebilir ve böylece kendisine tahsis edilen çerçevelerin sayısını artırabilir
(diğer işlemlerin çerçevelerini değiştirmek için seçmeyin ) .

Genel değiştirme algoritmasıyla ilgili bir sorun, bir işlem için bellekteki sayfa
kümesinin yalnızca o işlemin sayfalama davranışına değil, aynı zamanda diğer
işlemlerin sayfalama davranışına da bağlı olmasıdır. Bu nedenle, tamamen dış
koşullar nedeniyle aynı işlem oldukça farklı şekilde çalışabilir (örneğin, bir yürütme
için 0,5 saniye ve bir sonraki yürütme için 4,3 saniye sürme). Yerel değiştirme
algoritmasında durum böyle değildir. Yerel değiştirme altında, bir işlem için
bellekteki sayfalar kümesi, yalnızca o işlemin sayfalama davranışından etkilenir. Yerel
değiştirme, ancak daha az kullanılan bellek sayfalarını kullanıma sunmayarak bir
süreci engelleyebilir.
Bu nedenle, genel değiştirme genellikle daha fazla sistem verimi ile sonuçlanır. Bu
nedenle daha yaygın olarak kullanılan yöntemdir.
Machine Translated by Google

416 Bölüm 10 Sanal Bellek

BÜYÜK VE KÜÇÜK SAYFA HATALARI

Bölüm 10.2.1'de açıklandığı gibi, bir sayfa açılmadığında bir sayfa hatası oluşur.
bir işlemin adres alanında geçerli bir eşlemeye sahip olmak. İşletim sistemleri
genellikle iki tür sayfa hatası arasında ayrım yapar: büyük ve küçük
hatalar. (Windows, büyük ve küçük hataları sert ve yumuşak hatalar olarak ifade eder,
sırasıyla.) Bir sayfaya atıfta bulunulduğunda büyük bir sayfa hatası oluşur ve
sayfa hafızada değil. Büyük bir sayfa hatasına hizmet vermek, aşağıdakilerin okunmasını gerektirir:
destek mağazasından istenen sayfa ücretsiz bir çerçeveye dönüştürülür ve sayfa güncellenir
masa. Talep sayfalama genellikle başlangıçta yüksek oranda ana sayfa oluşturur
hatalar.
Bir işlemin mantıksal eşlemesi olmadığında küçük sayfa hataları oluşur
bir sayfaya, ancak o sayfa bellekte. İkisinden biri için küçük arızalar meydana gelebilir
sebepler. İlk olarak, bir işlem bellekteki paylaşılan bir kitaplığa başvurabilir, ancak
işlemin sayfa tablosunda bir eşlemesi yoktur. Bu durumda,
içindeki mevcut sayfaya atıfta bulunmak için sadece sayfa tablosunu güncellemek gerekir.
hafıza. Küçük hataların ikinci nedeni, bir sayfa geri alındığında ortaya çıkar.
bir süreçten alınmış ve serbest çerçeve listesine yerleştirilmiş, ancak sayfa henüz
sıfırlandı ve başka bir işleme tahsis edildi. Bu tür bir hata olduğunda
oluşursa, çerçeve serbest çerçeve listesinden kaldırılır ve çerçeveye yeniden atanır.
işlem. Beklenebileceği gibi, küçük bir sayfa hatasını çözmek genellikle
büyük bir sayfa hatasını çözmekten daha az zaman alır.
Bir Linux'ta büyük ve küçük sayfa hatalarının sayısını gözlemleyebilirsiniz.
çıktı veren ps -eo min flt,maj flt,cmd komutunu kullanan sistem
küçük ve büyük sayfa hatalarının sayısı ve ayrıca aşağıdaki komut
süreci başlattı. Bu ps komutunun örnek bir çıktısı aşağıda görünür:

MINFL MAJFL CMD


186509 32 9 0 /usr/lib/systemd/systemd-logind
76822 14 /usr/sbin/sshd -D
1937 vim 10.tex
699 /sbin/denetim -n

Burada, çoğu komut için majör sayısının


sayfa hataları genellikle oldukça düşüktür, oysa küçük hataların sayısı çok fazladır.
daha yüksek. Bu, Linux süreçlerinin büyük olasılıkla önemli avantajlar elde ettiğini gösterir.
paylaşılan kitaplıkların sayısı, bir kitaplık belleğe yüklendikten sonra sonraki sayfa
hatalar sadece küçük hatalardır.

Ardından, bir stratejiyi uygulamak için kullanabileceğimiz olası bir stratejiye odaklanıyoruz.
genel sayfa değiştirme politikası. Bu yaklaşımla, tüm hafızayı tatmin ediyoruz.
serbest çerçeve listesinden istekler, ancak listenin düşmesini beklemek yerine
değiştirilecek sayfaları seçmeye başlamadan önce sıfır, liste belirli bir eşiğin altına düştüğünde
sayfa değiştirmeyi tetikleriz. Bu strateji,
yeni istekleri karşılamak için her zaman yeterli boş bellek olduğundan emin olun.
Böyle bir strateji Şekil 10.18'de gösterilmektedir. Stratejinin amacı,
boş bellek miktarını minimum eşiğin üzerinde tutun. düştüğünde
Machine Translated by Google

10.5 Çerçevelerin Tahsisi 417

çekirdek askıya alınır


sayfaları
geri almak

b d maksimum
eşik

asgari
eşik

a c

zaman

çekirdek özgeçmişleri

sayfaları
geri almak

Şekil 10.18 Sayfaları geri alma.

bu eşiğin altında, sayfaları geri almaya başlayan bir çekirdek rutini tetiklenir
sistemdeki tüm işlemlerden (genellikle çekirdek hariç). Böyle bir çekirdek
rutinler genellikle biçerdöverler olarak bilinir ve Bölüm 10.4'te ele alınan sayfa
değiştirme algoritmalarından herhangi birini uygulayabilirler. ücretsiz miktar ne zaman
bellek maksimum eşiğe ulaşır, orak makinesi rutini askıya alınır, yalnızca
boş hafıza tekrar minimum eşiğin altına düştüğünde devam etmek için.
Şekil 10.18'de, a noktasında boş hafıza miktarının düştüğünü görüyoruz.
minimum eşiğin altında ve çekirdek sayfaları geri almaya başlar ve
onları serbest çerçeve listesine ekleyerek. Maksimum eşik olana kadar devam eder.
ulaşıldı (b noktası). Zamanla, bellek için ek istekler vardır ve
c noktası, boş bellek miktarı tekrar minimum eşiğin altına düşer.
Sayfa geri alma işlemi devam eder, yalnızca ücretsiz
bellek maksimum eşiğe ulaşır (d noktası). Bu süreç şu şekilde devam ediyor
sistem çalıştığı sürece.
Yukarıda bahsedildiği gibi, çekirdek reaper rutini herhangi bir sayfa değiştirme
algoritmasını benimseyebilir, ancak tipik olarak bir tür LRU yaklaşımı kullanır.
Yine de, orak makinesi rutini sürdürülemezse ne olabileceğini bir düşünün.
minimum eşiğin altındaki boş çerçevelerin listesi. Bu şartlar altında
Machine Translated by Google

418
Bölüm 10 Sanal Bellek
duruşlar, orak makinesi rutini sayfaları daha agresif bir şekilde geri almaya
başlayabilir. Örneğin, belki ikinci şans algoritmasını askıya alacak ve saf FIFO
kullanacak. Bir başka, daha uç örnek, Linux'ta görülür; boş bellek miktarı çok düşük
seviyelere düştüğünde, yetersiz bellek (OOM) öldürücü olarak bilinen bir rutin,
sonlandırmak için bir işlem seçer ve böylece belleği boşaltır. Linux hangi işlemin
sonlandırılacağını nasıl belirler? Her işlem, OOM skoru olarak bilinen şeye sahiptir
ve daha yüksek bir skor, işlemin OOM katil rutini tarafından sonlandırılma olasılığını
artırır . OOM puanları, bir işlemin kullandığı bellek yüzdesine göre hesaplanır;
yüzde ne kadar yüksek olursa, OOM puanı da o kadar yüksek olur. (OOM puanları /
proc dosya sisteminde görüntülenebilir; burada pid 2500'e sahip bir işlemin puanı /
proc/2500/oom puanı olarak görüntülenebilir.)

Genel olarak, orakçı rutinleri hafızayı ne kadar agresif bir şekilde geri
kazandıklarını değiştirmekle kalmaz, aynı zamanda minimum ve maksimum
eşiklerin değerleri de değiştirilebilir. Bu değerler varsayılan değerlere
ayarlanabilir, ancak bazı sistemler sistem yöneticisinin sistemdeki fiziksel bellek
miktarına göre bunları yapılandırmasına izin verebilir.

10.5.4 Tekdüze Olmayan Bellek Erişimi Şimdiye kadar

sanal bellek kapsamımızda, tüm ana belleğin eşit yaratıldığını veya en azından eşit
olarak erişildiğini varsaydık. Birden çok CPU'ya sahip tek tip olmayan bellek erişimi
(NUMA) sistemlerinde (Bölüm 1.3.2 ), durum böyle değildir. Bu sistemlerde, belirli
bir CPU , ana belleğin bazı bölümlerine diğerlerine erişebildiğinden daha hızlı
erişebilir. Bu performans farklılıkları , sistemde CPU'ların ve belleğin birbirine nasıl
bağlı olduğundan kaynaklanır. Böyle bir sistem , her biri kendi yerel belleğine
sahip birden fazla CPU'dan oluşur (Şekil 10.19). CPU'lar , paylaşılan bir sistem ara
bağlantısı kullanılarak düzenlenir ve beklediğiniz gibi, bir CPU yerel belleğine
başka bir CPU'nun yerel belleğinden daha hızlı erişebilir . NUMA sistemleri istisnasız
olarak ana belleğe tüm erişimlerin eşit muamele gördüğü sistemlerden daha
yavaştır. Ancak, Bölüm 1.3.2'de açıklandığı gibi, NUMA sistemleri daha fazla CPU'yu
barındırabilir ve bu nedenle daha yüksek verim ve paralellik seviyelerine ulaşabilir.

hafıza0 hafıza1

ara bağlantı

CPU0 CPU1

CPU2 CPU3

hafıza2 hafıza3

Şekil 10.19 NUMA çoklu işlem mimarisi.


Machine Translated by Google

10.6 Çarpma 419

Hangi konumlarda hangi sayfa çerçevelerinin depolandığını yönetmek, NUMA


sistemlerinde performansı önemli ölçüde etkileyebilir. Belleği böyle bir sistemde tek
tip olarak ele alırsak, CPU'lar , bellek ayırma algoritmalarını NUMA'yı hesaba katacak
şekilde değiştirmemize kıyasla bellek erişimi için önemli ölçüde daha uzun süre
bekleyebilir . Bu değişikliklerin bazılarını Bölüm 5.5.4'te açıkladık. Amaçları , işlemin
üzerinde çalıştığı CPU'ya "mümkün olduğunca yakın" tahsis edilmiş bellek
çerçevelerine sahip olmaktır . ( Kapatmanın tanımı, tipik olarak CPU ile aynı sistem
kartında anlamına gelen "minimum gecikmeyle"dir ). Bu nedenle, bir işlem bir sayfa
hatasına neden olduğunda, NUMA uyumlu bir sanal bellek sistemi, bu işlemi, işlemin
üzerinde çalıştığı CPU'ya mümkün olduğunca yakın bir çerçeve tahsis edecektir .
NUMA'yı hesaba katmak için, zamanlayıcı her işlemin üzerinde çalıştığı son
CPU'yu izlemelidir . Zamanlayıcı, her işlemi önceki CPU'suna programlamaya çalışırsa
ve sanal bellek sistemi, planlandığı CPU'ya yakın işlem için çerçeveler ayırmaya
çalışırsa , iyileştirilmiş önbellek isabetleri ve azalan bellek erişim süreleri sonuçlanacaktır.

Konular eklendikten sonra resim daha karmaşıktır. Örneğin, birçok çalışan iş


parçacığına sahip bir işlem, birçok farklı sistem kartında programlanan iş
parçacıklarıyla sonuçlanabilir. Bu durumda bellek nasıl tahsis edilmelidir?

Bölüm 5.7.1'de tartıştığımız gibi, Linux bu durumu, çekirdeğin bir zamanlama


etki alanları hiyerarşisi tanımlamasını sağlayarak yönetir. Linux CFS zamanlayıcı, iş
parçacıklarının farklı etki alanları arasında taşınmasına izin vermez ve bu nedenle
bellek erişimi cezalarına neden olur. Linux ayrıca her NUMA düğümü için ayrı bir
serbest çerçeve listesine sahiptir, böylece bir iş parçacığının üzerinde çalıştığı
düğümden bellek tahsis edilmesini sağlar. Solaris, çekirdekte lgroups ("yerel gruplar"
için) oluşturarak sorunu benzer şekilde çözer . Her lgroup , CPU'ları ve belleği bir
araya toplar ve bu gruptaki her bir CPU , tanımlanmış bir gecikme aralığı içinde
gruptaki herhangi bir belleğe erişebilir. Ayrıca, Linux'taki zamanlama alanları
hiyerarşisine benzer şekilde, gruplar arasındaki gecikme miktarına dayalı bir lgroups
hiyerarşisi vardır. Solaris, bir işlemin tüm iş parçacıklarını zamanlamaya ve bir işlemin
tüm belleğini bir grup içinde ayırmaya çalışır. Bu mümkün değilse, ihtiyaç duyulan
kaynakların geri kalanı için yakındaki grupları seçer. Bu uygulama, genel bellek
gecikmesini en aza indirir ve CPU önbellek isabet oranlarını en üst düzeye çıkarır.

10.6 Çarpma

Bir işlemin "yeterli" çerçeveleri yoksa, yani çalışma kümesindeki sayfaları desteklemek
için ihtiyaç duyduğu minimum çerçeve sayısına sahip değilse ne olacağını düşünün.
İşlem hızlı bir şekilde sayfa hatası olacaktır. Bu noktada, bazı sayfaları değiştirmelidir.
Ancak tüm sayfaları aktif kullanımda olduğu için bir an önce yeniden ihtiyaç duyulacak
bir sayfanın yerini alması gerekir. Sonuç olarak, hemen geri getirmesi gereken sayfaları
değiştirerek hızla tekrar ve tekrar hata verir.
Bu yüksek çağrı etkinliğine thrashing denir . Bir süreç, sayfalama yapmak için
yürütmekten daha fazla zaman harcıyorsa çöküyor. Tahmin edebileceğiniz gibi,
thrashing ciddi performans sorunlarına neden olur.

10.6.1 Thrashing'in Nedeni

Erken çağrı sistemlerinin fiili davranışına dayanan aşağıdaki senaryoyu düşünün.


İşletim sistemi CPU kullanımını izler . CPU kullanılıyorsa- _
Machine Translated by Google

420
Bölüm 10 Sanal Bellek
çok düşükse, sisteme yeni bir süreç ekleyerek çoklu programlamanın derecesini
arttırıyoruz. Genel bir sayfa değiştirme algoritması kullanılır; ait oldukları sürece
bakılmaksızın sayfaları değiştirir. Şimdi, bir sürecin yürütülmesinde yeni bir aşamaya
girdiğini ve daha fazla çerçeveye ihtiyaç duyduğunu varsayalım. Faylanmaya ve
çerçeveleri diğer süreçlerden uzaklaştırmaya başlar. Ancak bu süreçlerin bu sayfalara
ihtiyacı vardır ve bu nedenle diğer süreçlerden çerçeveler alarak hata yaparlar. Bu
arızalı işlemler, sayfaları içeri ve dışarı değiştirmek için çağrı cihazını kullanmalıdır.
Çağrı cihazı için sıraya girdiklerinde, hazır kuyruk boşalır. İşlemler sayfalama cihazını
beklerken CPU kullanımı azalır.
CPU zamanlayıcı , azalan CPU kullanımını görür ve sonuç olarak çoklu programlama
derecesini artırır . Yeni işlem, çalışan işlemlerden çerçeveler alarak başlamaya çalışır,
bu da daha fazla sayfa hatasına ve sayfalama aygıtı için daha uzun bir kuyruğa neden
olur. Sonuç olarak, CPU kullanımı daha da düşer ve CPU zamanlayıcısı çoklu
programlamanın derecesini daha da artırmaya çalışır. Thrashing meydana geldi ve
sistem verimi düşüyor. Sayfa hata oranı muazzam bir şekilde artar. Sonuç olarak, etkin
bellek erişim süresi artar. Hiçbir iş yapılmıyor, çünkü süreçler tüm zamanlarını
sayfalamaya harcıyor.

Bu fenomen, CPU kullanımının çoklu programlama derecesine karşı çizildiği Şekil


10.20'de gösterilmektedir. Çoklu programlama derecesi arttıkça, maksimuma ulaşılana
kadar daha yavaş olsa da CPU kullanımı da artar. Çoklu programlamanın derecesi daha
da artırılırsa, çöküş başlar ve CPU kullanımı keskin bir şekilde düşer. Bu noktada CPU
kullanımını artırmak ve thrashing'i durdurmak için çoklu programlamanın derecesini
azaltmalıyız .

Yerel bir değiştirme algoritması (veya öncelikli değiştirme algoritması) kullanarak


thrashing'in etkilerini sınırlayabiliriz . Daha önce belirtildiği gibi, yerel değiştirme, her
işlemin yalnızca kendi tahsis edilmiş çerçeveler kümesinden seçim yapmasını gerektirir.
Bu nedenle, bir işlem thrash etmeye başlarsa, başka bir işlemden kareleri çalamaz ve
ikincisinin de thrash'e neden olmasına neden olmaz. Ancak sorun tamamen çözülmüş
değil. İşlemler hızlanıyorsa, çoğu zaman çağrı cihazı için kuyrukta olacaklardır. Bir
sayfa hatası için ortalama hizmet süresi artacak

hırpalama

çoklu programlama derecesi

Şekil 10.20 Thrashing.


10.6 Çarpma 421
Machine Translated by Google

çağrı cihazı için daha uzun ortalama kuyruk nedeniyle. Böylece thrash olmayan bir
işlem için bile efektif erişim süresi artacaktır.
Thrash'i önlemek için, ihtiyaç duyduğu kadar çok çerçeve içeren bir süreç
sağlamalıyız. Ama kaç tane çerçeveye "ihtiyacı olduğunu" nasıl bileceğiz? Bir
strateji, bir sürecin gerçekte kaç çerçeve kullandığına bakarak başlar. Bu yaklaşım,
süreç yürütmenin yerellik modelini tanımlar .
Yerellik modeli, bir süreç yürütülürken yerellikten yerelliğe doğru hareket
ettiğini belirtir. Yerellik, birlikte aktif olarak kullanılan bir sayfalar kümesidir. Çalışan
bir program genellikle üst üste binebilen birkaç farklı bölgeden oluşur. Örneğin,
bir işlev çağrıldığında yeni bir yerellik tanımlar. Bunda

34

32

30

28

26

24

22

20

18
(a) (b)
uygulama vakti

Şekil 10.21 Bir bellek referans modelinde yerellik.


Machine Translated by Google

422 Bölüm 10 Sanal Bellek


sayfa referans
tablosu . . . 2 6 1 5 7 7 7 7 5 1 6 2 3 4 1 2 3 4 4 4 3 4 3 4 4 4 1 3 2 3 4 4 4 3 4 4 4 .. .

Δ Δ

t1 t2
WS(t1) = {1,2,5,6,7} WS(t2) = {3,4}

Şekil 10.22 Çalışma seti modeli.

yerellik, bellek referansları, işlev çağrısının talimatlarına, yerel değişkenlerine ve


global değişkenlerin bir alt kümesine yapılır. Fonksiyondan çıktığımızda,
fonksiyonun yerel değişkenleri ve talimatları artık aktif kullanımda olmadığı için
proses bu lokaliteden ayrılır. Bu bölgeye daha sonra dönebiliriz.
Şekil 10.21, yerellik kavramını ve bir sürecin yerelliğinin zaman içinde nasıl
değiştiğini göstermektedir. (a) zamanında , yerellik {18, 19, 20, 21, 22, 23, 24, 29,
30, 33} sayfalarının kümesidir. (b) zamanında , yer {18, 19, 20, 24, 25, 26, 27, 28,
29, 31, 32, 33} olarak değişir. Bazı sayfalar (örneğin, 18, 19 ve 20) her iki konumun
da parçası olduğundan örtüşmeye dikkat edin.
Böylece, yerelliklerin program yapısı ve veri yapıları tarafından tanımlandığını
görüyoruz. Yerellik modeli, tüm programların bu temel bellek referans yapısını
sergileyeceğini belirtir. Yerellik modelinin, bu kitapta şu ana kadar önbelleğe
alma tartışmalarının ardındaki belirtilmeyen ilke olduğuna dikkat edin. Herhangi
bir veri türüne erişim desenli değil rastgele olsaydı, önbelleğe alma işe yaramazdı.
Bir sürece, mevcut konumunu yerleştirmek için yeterli çerçeve ayırdığımızı
varsayalım. Tüm bu sayfalar hafızaya alınana kadar kendi mahallindeki sayfalar
için hata verecektir; o zaman, yerleri değiştirene kadar tekrar hata vermeyecektir.
Geçerli konumun boyutunu barındırmak için yeterli çerçeve tahsis etmezsek,
işlem etkin olarak kullandığı tüm sayfaları bellekte tutamayacağından işlem
çöker.

10.6.2 Çalışma Kümesi Modeli Çalışma

kümesi modeli , yerellik varsayımına dayanmaktadır. Bu model, çalışma kümesi


penceresini tanımlamak için bir parametre, Δ kullanır . Buradaki fikir, en son Δ
sayfa referanslarını incelemektir. En son Δ sayfa referanslarındaki sayfa seti,
çalışma setidir (Şekil 10.22). Bir sayfa aktif kullanımda ise çalışma setinde olacaktır.
Artık kullanılmıyorsa, son referansından sonra çalışma kümesi Δ zaman
birimlerinden düşecektir. Bu nedenle, çalışma seti, programın yerelliğinin bir
tahminidir.
Örneğin, Şekil 10.22'de gösterilen bellek referansları dizisi verildiğinde, eğer
Δ = 10 hafıza referansı ise, o zaman t1 anındaki çalışma seti {1, 2, 5, 6, 7}'dir. t2
zamanında , çalışma kümesi {3, 4} olarak değişmiştir.
Çalışma setinin doğruluğu Δ seçimine bağlıdır. Δ çok küçükse, tüm yerelliği
kapsamayacaktır; Δ çok büyükse, birkaç yerle örtüşebilir. En uçta, Δ sonsuz ise,
çalışma kümesi, işlem yürütmesi sırasında dokunulan sayfalar kümesidir.

O halde çalışma kümesinin en önemli özelliği boyutudur. Sistemdeki her


işlem için çalışma kümesi boyutunu, WSSi hesaplarsak , bunu düşünebiliriz.
Machine Translated by Google

10.6 Çarpma 423

D= WSSi ,

burada D , çerçeveler için toplam taleptir. Her süreç kendi çalışma setindeki sayfaları
aktif olarak kullanmaktadır. Bu nedenle, işlem i'nin WSSi çerçevelerine ihtiyacı var.
Toplam talep, mevcut çerçevelerin toplam sayısından (D > m) daha büyükse, bazı
işlemler yeterli çerçeveye sahip olmayacağından, çarpma meydana gelir.
Δ seçildikten sonra, çalışma seti modelinin kullanımı basittir. İşletim sistemi, her
işlemin çalışma grubunu izler ve çalışma kümesi boyutunu sağlamak için bu çalışma
kümesine yeterli çerçeveyi tahsis eder. Yeterli ekstra çerçeve varsa, başka bir işlem
başlatılabilir. Çalışma kümesi boyutlarının toplamı, kullanılabilir çerçevelerin toplam
sayısını aşacak şekilde artarsa, işletim sistemi askıya alınacak bir işlem seçer. İşlemin
sayfaları yazılır (değiştirilir) ve çerçeveleri diğer işlemlere yeniden tahsis edilir. Askıya
alınan işlem daha sonra yeniden başlatılabilir.

Bu çalışma seti stratejisi, çoklu programlamanın derecesini mümkün olduğu kadar


yüksek tutarken bozulmayı önler. Böylece CPU kullanımını optimize eder. Çalışma
kümesi modelinin zorluğu, çalışma kümesinin kaydını tutmaktır. bu

ÇALIŞMA SETLERİ VE SAYFA HATA ORANLARI

Bir sürecin çalışma grubu ile sayfa hata oranı arasında doğrudan bir ilişki vardır.
Tipik olarak, Şekil 10.22'de gösterildiği gibi, veri ve kod bölümlerine yapılan
referanslar bir bölgeden diğerine hareket ettikçe, bir sürecin çalışma seti zamanla
değişir. Bir işlemin çalışma kümesini depolamak için yeterli bellek olduğunu
varsayarsak (yani, işlem çökmüyor), işlemin sayfa hata oranı zaman içinde tepeler
ve vadiler arasında geçiş yapacaktır. Bu genel davranış aşağıda gösterilmiştir:

çalışma seti

sayfa
hata
oranı

0
zaman

Yeni bir yerellik için talep-çağrı yapmaya başladığımızda, sayfa hata oranında
bir zirve meydana gelir. Ancak, bu yeni konumun çalışma kümesi belleğe
alındığında, sayfa hatası oranı düşer. İşlem yeni bir çalışma grubuna geçtiğinde,
sayfa hatası oranı bir kez daha zirveye doğru yükselir ve yeni çalışma grubu
belleğe yüklendiğinde daha düşük bir orana döner. Bir tepe noktasının başlangıcı
ile bir sonraki tepe noktasının başlangıcı arasındaki zaman aralığı, bir çalışma
kümesinden diğerine geçişi temsil eder.
Machine Translated by Google

424 Bölüm 10 Sanal Bellek

çalışma kümesi penceresi hareketli bir penceredir. Her bellek referansında, bir uçta
yeni bir referans görünür ve diğer uçta en eski referans düşer.
Çalışma kümesi penceresinde herhangi bir yere başvuruluyorsa, bir sayfa çalışma
kümesindedir.
Çalışma kümesi modeline sabit aralıklı bir zamanlayıcı kesmesi ve bir referans biti
ile yaklaşabiliriz. Örneğin, Δ'nin 10.000 referansa eşit olduğunu ve her 5.000 referansta
bir zamanlayıcı kesintisine neden olabileceğimizi varsayalım. Bir zamanlayıcı kesmesi
aldığımızda, her sayfa için referans bit değerlerini kopyalayıp temizliyoruz. Böylece,
bir sayfa hatası meydana gelirse, bir sayfanın son 10.000 ila 15.000 referans arasında
kullanılıp kullanılmadığını belirlemek için mevcut referans bitini ve iki bellek içi biti
inceleyebiliriz. Kullanılmışsa, bu bitlerden en az biri açık olacaktır.
Kullanılmamışsa, bu bitler kapalı olacaktır. En az bir biti olan sayfalar çalışma kümesinde
kabul edilecektir.
Bu düzenlemenin tamamen doğru olmadığına dikkat edin, çünkü 5.000'lik bir
aralık içinde bir referansın nerede meydana geldiğini söyleyemeyiz. Geçmiş bitlerinin
sayısını ve kesintilerin sıklığını artırarak belirsizliği azaltabiliriz (örneğin, her 1000
referansta bir 10 bit ve kesintiler). Bununla birlikte, bu daha sık kesintilere hizmet
vermenin maliyeti, buna bağlı olarak daha yüksek olacaktır.

10.6.3 Sayfa-Hata Frekansı

Çalışma seti modeli başarılıdır ve çalışma seti bilgisi ön sayfalama için faydalı olabilir
(Bölüm 10.9.1), ancak bu, yığılmayı kontrol etmenin beceriksiz bir yolu gibi
görünmektedir. Sayfa hatası frekansını (PFF) kullanan bir strateji daha doğrudan bir
yaklaşım benimser.
Spesifik sorun, thrash'in nasıl önleneceğidir. Thrashing'in yüksek sayfa hatası
oranı vardır. Böylece sayfa hata oranını kontrol etmek istiyoruz. Çok yüksek olduğunda,
işlemin daha fazla kareye ihtiyacı olduğunu biliyoruz. Tersine, sayfa hata oranı çok
düşükse, işlemin çok fazla çerçevesi olabilir. İstenen sayfa-hata oranı üzerinde alt ve
üst sınır oluşturabiliriz (Şekil 10.23).
Gerçek sayfa hata oranı üst sınırı aşarsa, işlemi tahsis ederiz.

çerçeve sayısını
artır
üst sınır

alt sınır çerçeve


sayısını azalt

çerçeve sayısı

Şekil 10.23 Sayfa hatası frekansı.


Machine Translated by Google

10.7 Bellek Sıkıştırma 425

başka bir çerçeve. Sayfa hata oranı alt sınırın altına düşerse, bir
süreçten kare. Böylece, thrash'i önlemek için sayfa hata oranını doğrudan ölçebilir ve
kontrol edebiliriz.
Çalışma seti stratejisinde olduğu gibi, bir süreci değiştirmemiz gerekebilir. Eğer
sayfa hata oranı artar ve boş çerçeve yok, bazılarını seçmeliyiz
işleyin ve destek mağazasına değiştirin. Serbest bırakılan çerçeveler daha sonra dağıtılır
yüksek sayfa hatası oranlarına sahip işlemlere.

10.6.4 Mevcut Uygulama

Pratik olarak konuşursak, dövülme ve sonuçta ortaya çıkan takas, hoş olmayan bir şekilde
performans üzerinde yüksek etkisi. uygulanmasında mevcut en iyi uygulama
bilgisayar sistemi, mümkün olduğunda yeterli fiziksel bellek içerecektir,
thrashing ve takas önlemek için. Akıllı telefonlardan büyük sunucular aracılığıyla,
tüm çalışma setlerini aynı anda bellekte tutacak kadar bellek sağlamak,
aşırı koşullar dışında, en iyi kullanıcı deneyimini sağlar.

10.7 Bellek Sıkıştırma

Disk belleğine bir alternatif, bellek sıkıştırmadır. Burada, sayfalamak yerine


alanı değiştirmek için değiştirilmiş çerçeveler dışında, birkaç kareyi tek bir kareye sıkıştırırız.
çerçeveye başvurmadan sistemin bellek kullanımını azaltmasını sağlar.
sayfaları değiş tokuş etmek.

Şekil 10.24'te serbest çerçeve listesi altı çerçeve içermektedir. Diyelim ki bu


boş çerçeve sayısı, sayfa değiştirmeyi tetikleyen belirli bir eşiğin altına düşer. Değiştirme
algoritması (örneğin, bir LRU yaklaşımı algoritması)
dört kare (15, 3, 35 ve 26) serbest kare listesine eklenir. ilk sırada yer alır
bu çerçeveler değiştirilmiş çerçeve listesinde. Tipik olarak, değiştirilmiş çerçeve listesi
sonra, çerçeveleri serbest çerçeve için kullanılabilir hale getirerek, alanı takas etmek için yazılmalıdır.
liste. Alternatif bir strateji, birkaç kareyi (örneğin üç) sıkıştırmaktır.
ve sıkıştırılmış sürümlerini tek bir sayfa çerçevesinde saklayın.
Şekil 10.25'te, çerçeve 7 serbest çerçeve listesinden kaldırılmıştır. çerçeveler 15,
3 ve 35 sıkıştırılır ve çerçeve 7'de depolanır, bu daha sonra çerçeve içinde depolanır.
sıkıştırılmış çerçevelerin listesi. 15, 3 ve 35 numaralı çerçeveler artık
serbest çerçeve listesi. Sıkıştırılmış üç çerçeveden birine daha sonra başvurulursa, bir sayfa
hata oluşur ve sıkıştırılmış çerçevenin sıkıştırması açılır, üç
15, 3 ve 35. sayfalar bellekte.

serbest çerçeve listesi

kafa 7 2 9 21 27 16

değiştirilmiş çerçeve listesi

kafa 15 3 35 26

Şekil 10.24 Sıkıştırma öncesi serbest çerçeve listesi.


Machine Translated by Google

426
Bölüm 10 Sanal Bellek
serbest çerçeve listesi

kafa 2 9 21 27 16 15 3 35

değiştirilmiş çerçeve listesi

kafa 26

sıkıştırılmış çerçeve listesi


kafa 7

Şekil 10.25 Sıkıştırma sonrası serbest çerçeve listesi

Belirttiğimiz gibi, mobil sistemler genellikle standart değiştirme veya sayfa


değiştirmeyi desteklemez. Bu nedenle, bellek sıkıştırması ayrılmaz bir
çoğu mobil işletim sistemi için bellek yönetimi stratejisinin bir parçası,
Android ve iOS dahil. Ayrıca hem Windows 10 hem de macOS desteği
bellek sıkıştırma Windows 10 için Microsoft, Evrensel'i geliştirdi.
Mobil cihazlar da dahil olmak üzere Windows 10 çalıştıran cihazlar için ortak bir uygulama
platformu sağlayan Windows Platformu (UWP) mimarisi. UWP uygulamaları
mobil cihazlarda çalışmak, bellek sıkıştırmaya adaydır. Mac os işletim sistemi
ilk olarak işletim sisteminin 10.9 Sürümü ile desteklenen bellek sıkıştırması, önce boş
bellek yetersiz olduğunda LRU sayfalarının sıkıştırılması ve ardından sayfalama
eğer bu sorunu çözmezse. Performans testleri, bellek sıkıştırmanın dizüstü bilgisayardaki
SSD ikincil depolamaya bile sayfalamadan daha hızlı olduğunu gösteriyor ve
masaüstü macOS sistemleri.
Bellek sıkıştırması, boş çerçeveler ayırmayı gerektirse de
sıkıştırılmış sayfaları tutun, önemli bir bellek tasarrufu gerçekleştirilebilir,
sıkıştırma algoritması tarafından elde edilen azalmalara bağlı olarak. (İçinde
yukarıdaki örnekte, üç kare orijinallerinin üçte birine düşürülmüştür.
boyutu.) Herhangi bir veri sıkıştırma biçiminde olduğu gibi, aralarında bir çekişme vardır.
sıkıştırma algoritmasının hızı ve olabilecek azalma miktarı
elde edilir ( sıkıştırma oranı olarak bilinir ). Genel olarak, daha yüksek sıkıştırma
oranlar (daha büyük azalmalar) daha yavaş, daha hesaplamalı olarak elde edilebilir
pahalı algoritmalar Günümüzde kullanılan çoğu algoritma bu iki faktörü dengeler.
hızlı algoritmalar kullanarak nispeten yüksek sıkıştırma oranları elde etmek. Ek olarak,
sıkıştırma algoritmaları, çoklu bilgi işlem çekirdeğinden yararlanarak ve sıkıştırmayı
paralel olarak gerçekleştirerek gelişmiştir. Örneğin, Microsoft'un
Xpress ve Apple'ın WKdm sıkıştırma algoritmaları hızlı kabul edilir ve
sayfaları orijinal boyutlarının yüzde 30 ila 50'sine kadar sıkıştırdıklarını bildiriyorlar.

10.8 Çekirdek Belleği Ayırma

Kullanıcı modunda çalışan bir işlem ek bellek istediğinde, sayfalar


çekirdek tarafından sağlanan boş sayfa çerçeveleri listesinden ayrılır. Bu liste
genellikle Bölüm 10.4'te tartışılanlar gibi bir sayfa değiştirme algoritması kullanılarak
doldurulur ve büyük olasılıkla her yere dağılmış ücretsiz sayfalar içerir
fiziksel bellek, daha önce açıklandığı gibi. Şunu da unutmayın, eğer bir kullanıcı işlemi
tek bir bayt bellek isterse, dahili parçalanma
işleme tam bir sayfa çerçevesi verilecektir.
Machine Translated by Google

10.8 Çekirdek Belleği Ayırma 427

Çekirdek belleği genellikle, sıradan kullanıcı modu işlemlerini karşılamak için


kullanılan listeden farklı bir boş bellek havuzundan ayrılır. Bunun başlıca iki nedeni
vardır:

1. Çekirdek, bazıları bir sayfadan daha küçük olan çeşitli boyutlardaki veri yapıları
için bellek ister. Sonuç olarak, çekirdek belleği muhafazakar bir şekilde
kullanmalı ve parçalanma nedeniyle israfı en aza indirmeye çalışmalıdır. Bu
özellikle önemlidir çünkü birçok işletim sistemi çekirdek kodunu veya verilerini
sayfalama sistemine tabi tutmaz.

2. Kullanıcı modu süreçlerine ayrılan sayfaların mutlaka bitişik fiziksel bellekte


olması gerekmez. Bununla birlikte, belirli donanım aygıtları, sanal bellek
arabiriminin yararı olmadan doğrudan fiziksel bellekle etkileşime girer ve sonuç
olarak fiziksel olarak bitişik sayfalarda bulunan belleği gerektirebilir.

Aşağıdaki bölümlerde, çekirdek süreçlerine atanan boş belleği yönetmek için iki
stratejiyi inceleyeceğiz: “arkadaş sistemi” ve slab tahsisi.

10.8.1 Arkadaş Sistemi

Arkadaşlık sistemi, fiziksel olarak bitişik sayfalardan oluşan sabit boyutlu bir bölümden
bellek ayırır. Bu bölümden bellek, 2'nin gücü (4 KB, 8 KB, 16 KB vb.) olarak
boyutlandırılmış birimlerde talepleri karşılayan , 2'nin gücünde bir ayırıcı kullanılarak
ayrılır. Uygun boyutta olmayan birimlerdeki bir istek, bir sonraki en yüksek güç olan
2'ye yuvarlanır. Örneğin, 11 KB'lık bir istek, 16 KB'lık bir segmentle karşılanır .

Basit bir örnek düşünelim. Bir bellek bölümünün boyutunun başlangıçta 256 KB
olduğunu ve çekirdeğin 21 KB bellek istediğini varsayalım. Segment başlangıçta
her biri 128 KB boyutunda olan AL ve AR olarak adlandıracağımız iki arkadaşa
bölünmüştür . Bu arkadaşlardan biri ayrıca 64 KB'lık iki arkadaşa bölünmüştür: BL ve
BR. Bununla birlikte, 21 KB'den 2'nin bir sonraki en yüksek gücü 32 KB'dir , bu nedenle
BL veya BR tekrar iki 32 KB'lik arkadaşlara, CL ve CR'ye bölünür . Bu arkadaşlardan biri
21 KB'lik isteği karşılamak için kullanılır. Bu şema, Şekil 10.26'da gösterilmektedir,
burada CL , 21-KB isteğine tahsis edilen segmenttir .
Arkadaşlık sisteminin bir avantajı, birleştirme olarak bilinen bir teknik kullanılarak
bitişik arkadaşların daha büyük bölümler oluşturmak için ne kadar hızlı bir şekilde
birleştirilebileceğidir. Şekil 10.26'da, örneğin, çekirdek tahsis edilen CL birimini
serbest bıraktığında, sistem CL ve CR'yi 64 KB'lık bir segmentte birleştirebilir. Bu
segment, BL, 128 KB'lık bir segment oluşturmak için arkadaşı BR ile birleştirilebilir .
Sonuç olarak, orijinal 256 KB segmenti elde edebiliriz.
Buddy sisteminin bariz dezavantajı, bir sonraki en yüksek güç olan 2'ye
yuvarlamanın, tahsis edilen segmentler içinde parçalanmaya neden olma olasılığının
çok yüksek olmasıdır. Örneğin, 33 KB'lık bir istek yalnızca 64 KB'lık bir segmentle karşılanabilir.
Aslında, tahsis edilen birimin yüzde 50'sinden daha azının dahili parçalanma nedeniyle
boşa harcanacağını garanti edemeyiz. Aşağıdaki bölümde, parçalanma nedeniyle
alan kaybının olmadığı bir bellek ayırma şemasını inceleyeceğiz.

10.8.2 Döşeme Tahsisi

Çekirdek belleği tahsis etmek için ikinci bir strateji, levha tahsisi olarak bilinir . Bir
levha , bir veya daha fazla fiziksel olarak bitişik sayfadan oluşur. Bir önbellek oluşur
Machine Translated by Google

428
Bölüm 10 Sanal Bellek
fiziksel olarak bitişik sayfalar

256 KB

128 KB 128 KB
AL AR

64 KB 64 KB
BL BR

32 KB 32 KB
CL CR

Şekil 10.26 Buddy sistem tahsisi.

bir veya daha fazla levhadan. Her benzersiz çekirdek veri yapısı için tek bir önbellek vardır;
örneğin, işlem tanımlayıcılarını temsil eden veri yapısı için ayrı bir önbellek, dosya nesneleri
için ayrı bir önbellek, semaforlar için ayrı bir önbellek vb. Her önbellek, önbelleğin temsil
ettiği çekirdek veri yapısının örnekleri olan nesnelerle doldurulur . Örneğin, semaforları
temsil eden önbellek, semafor nesnelerinin örneklerini depolar, süreç tanımlayıcılarını
temsil eden önbellek, süreç tanımlayıcı nesnelerinin örneklerini depolar ve benzerleri.

Döşemeler, önbellekler ve nesneler arasındaki ilişki Şekil 10.27'de gösterilmektedir. Şekil ,


her biri ayrı bir önbellekte depolanan, 3 KB boyutunda iki çekirdek nesnesini ve 7 KB
boyutunda üç nesneyi göstermektedir.

çekirdek nesneleri önbellekler levhalar

3 KB

nesneler

fiziksel olarak
bitişik sayfalar

7 KB

nesneler

Şekil 10.27 Döşeme tahsisi.


10.8 Çekirdek Belleği Ayırma 429
Machine Translated by Google

Döşeme tahsisi algoritması, çekirdek nesnelerini depolamak için önbellekleri kullanır. Bir
önbellek oluşturulduğunda, başlangıçta ücretsiz olarak işaretlenen bir dizi nesne önbelleğe
tahsis edilir. Önbellekteki nesnelerin sayısı, ilişkili döşemenin boyutuna bağlıdır. Örneğin, 12
KB'lık bir levha (üç bitişik 4 KB sayfadan oluşan) altı adet 2 KB'lık nesne depolayabilir . Başlangıçta,
önbellekteki tüm nesneler ücretsiz olarak işaretlenir. Bir çekirdek veri yapısı için yeni bir nesneye
ihtiyaç duyulduğunda, ayırıcı, talebi karşılamak için önbellekten herhangi bir boş nesne atayabilir.
Önbellekten atanan nesne kullanılmış olarak işaretlenir.

Çekirdeğin, bir süreç tanımlayıcısını temsil eden bir nesne için levha ayırıcıdan bellek talep
ettiği bir senaryoyu ele alalım. Linux sistemlerinde, bir süreç tanımlayıcısı, yaklaşık 1,7 KB bellek
gerektiren struct task struct türündedir . Linux çekirdeği yeni bir görev oluşturduğunda ,
önbelleğinden struct task struct nesnesi için gerekli belleği talep eder. Önbellek, bir döşemede
önceden tahsis edilmiş ve boş olarak işaretlenmiş bir struct görevi struct nesnesini kullanarak
talebi yerine getirecektir .

Linux'ta bir levha üç olası durumdan birinde olabilir:

1. Dolu. Döşemedeki tüm nesneler kullanılmış olarak işaretlenir.

2. Boş. Döşemedeki tüm nesneler serbest olarak işaretlenir.

3. Kısmi. Döşeme hem kullanılmış hem de serbest nesnelerden oluşur.

Döşeme ayırıcı, önce talebi kısmi bir döşemede serbest bir nesneyle karşılamaya çalışır. Hiçbiri
yoksa, boş bir levhadan serbest bir nesne atanır. Boş levha yoksa, bitişik fiziksel sayfalardan yeni
bir levha tahsis edilir ve bir önbelleğe atanır; nesne için bellek bu levhadan tahsis edilir.

Döşeme ayırıcısı iki ana fayda sağlar:

1. Parçalanma nedeniyle bellek boşa harcanmaz. Parçalanma bir sorun değildir, çünkü her
benzersiz çekirdek veri yapısı ilişkili bir önbelleğe sahiptir ve her önbellek, temsil edilen
nesnelerin boyutundaki parçalara bölünmüş bir veya daha fazla levhadan oluşur. Bu
nedenle, çekirdek bir nesne için bellek istediğinde, levha ayırıcı, nesneyi temsil etmek için
gereken tam bellek miktarını döndürür.

2. Bellek istekleri hızlı bir şekilde karşılanabilir. Döşeme tahsis şeması, bu nedenle, genellikle
çekirdekten gelen taleplerde olduğu gibi, nesneler sıklıkla tahsis edildiğinde ve yeniden
tahsis edildiğinde, belleği yönetmek için özellikle etkilidir. Belleği ayırma ve serbest
bırakma eylemi zaman alıcı bir süreç olabilir. Ancak nesneler önceden oluşturulur ve bu
nedenle önbellekten hızlı bir şekilde tahsis edilebilir. Ayrıca, çekirdek bir nesneyi bitirip onu
serbest bıraktığında, özgür olarak işaretlenir ve önbelleğine geri döner, böylece
çekirdekten gelen sonraki istekler için hemen kullanılabilir hale gelir.

Döşeme ayırıcısı ilk olarak Solaris 2.4 çekirdeğinde ortaya çıktı. Genel amaçlı doğası
nedeniyle, bu ayırıcı artık Solaris'te belirli kullanıcı modu bellek istekleri için de kullanılmaktadır.
Linux başlangıçta buddy sistemini kullandı; ancak, Sürüm 2.2'den başlayarak, Linux çekirdeği slab
ayırıcıyı benimsemiştir. Linux
430 Bölüm
Machine Translated by Google 10 Sanal Bellek
SLAB olarak döşeme uygulamasına atıfta bulunur . Linux'un son dağıtımları, diğer iki
çekirdek bellek ayırıcısını içerir: SLOB ve SLUB ayırıcıları.
SLOB ayırıcı, gömülü sistemler gibi sınırlı miktarda belleğe sahip sistemler için
tasarlanmıştır . SLOB ("basit blok listesi" anlamına gelir) üç nesne listesi tutar: küçük (256
bayttan küçük nesneler için), orta (1.024 bayttan küçük nesneler için) ve büyük (boyutundan
küçük diğer tüm nesneler için ). Bir sayfa). Bellek istekleri, ilk sığdırma ilkesi kullanılarak
uygun listedeki bir nesneden ayrılır.

Sürüm 2.6.24'ten itibaren, SLUB ayırıcı , Linux çekirdeği için varsayılan ayırıcı olarak
SLAB'ın yerini aldı . SLUB , SLAB tahsisatçısının gerektirdiği ek yükün çoğunu azalttı .
Örneğin, SLAB her kütük ile belirli meta verileri depolarken, SLUB bu verileri Linux
çekirdeğinin her sayfa için kullandığı sayfa yapısında depolar. Ayrıca, SLUB , SLAB ayırıcısının
her önbellekteki nesneler için tuttuğu CPU başına kuyrukları içermez . Çok sayıda işlemciye
sahip sistemler için bu kuyruklara ayrılan bellek miktarı önemlidir. Böylece SLUB , bir
sistemdeki işlemci sayısı arttıkça daha iyi performans sağlar.

10.9 Diğer Hususlar

Bir çağrı sistemi için verdiğimiz başlıca kararlar, bu bölümde daha önce tartıştığımız bir
değiştirme algoritması ve bir tahsis politikası seçimleridir. Başka birçok husus da var ve
bunlardan birkaçını burada tartışıyoruz.

10.9.1 Hazırlama
Saf talep sayfalamanın bariz bir özelliği, bir süreç başlatıldığında meydana gelen çok sayıda
sayfa hatasıdır. Bu durum, ilk yerelliği belleğe almaya çalışmaktan kaynaklanır. Ön
sayfalama , bu yüksek seviyedeki ilk sayfalamayı önleme girişimidir. Strateji, ihtiyaç duyulacak
sayfaların bir kısmını veya tamamını bir kerede belleğe getirmektir.

Örneğin, çalışma kümesi modelini kullanan bir sistemde, her işlemle, çalışma
kümesindeki sayfaların bir listesini tutabiliriz. Bir işlemi askıya almamız gerekirse (boş
çerçevelerin olmaması nedeniyle), bu işlem için çalışma setini hatırlarız.
İşlem devam ettirileceğinde ( G/Ç bittiğinden veya yeterli boş çerçeve bulunduğundan),
işlemi yeniden başlatmadan önce tüm çalışma setini otomatik olarak belleğe geri getiririz.

Ön hazırlık bazı durumlarda avantaj sağlayabilir. Soru, basitçe, ön sayfalama


kullanmanın maliyetinin, ilgili sayfa hatalarını servis etme maliyetinden daha az olup
olmadığıdır. Ön sayfalama ile belleğe geri getirilen sayfaların çoğu kullanılmayacak olabilir.

s sayfalarının önceden sayfalandırıldığını ve bu s sayfalarının bir α kesrinin gerçekten


kullanıldığını varsayalım (0 α 1). Soru, s* α kaydedilen sayfa hatalarının maliyetinin, s*
(1 α) gereksiz sayfaları önceden sayfalamanın maliyetinden daha büyük veya daha az olup
olmadığıdır . α 0'a yakınsa, ön sayfalama kaybeder; α 1'e yakınsa, ön sayfalama kazanır.
Ayrıca, tam olarak hangi sayfaların getirilmesi gerektiği belirsiz olabileceğinden,
yürütülebilir bir programın hazırlanmasının zor olabileceğini unutmayın. Dosyalara genellikle
sırayla erişildiğinden, bir dosyanın hazırlanması daha öngörülebilir olabilir. Linux
Machine Translated by Google

10.9 Diğer Hususlar 431

readahead() sistem çağrısı, bir dosyanın içeriğini belleğe önceden


getirir, böylece dosyaya sonraki erişimler ana bellekte gerçekleşir.

10.9.2 Sayfa Boyutu

Mevcut bir makine için bir işletim sistemi tasarımcılarının nadiren sayfa boyutuyla
ilgili bir seçeneği vardır. Ancak, yeni makineler tasarlanırken, en iyi sayfa boyutuna
ilişkin bir karar verilmelidir. Tahmin edebileceğiniz gibi, tek bir en iyi sayfa boyutu
yoktur. Bunun yerine, çeşitli boyutları destekleyen bir dizi faktör vardır. Sayfa
boyutları her zaman 2'nin katıdır ve genellikle 4.096 (212) ile 4.194.304 (222) bayt
arasında değişir.
Sayfa boyutunu nasıl seçeriz? Bir endişe, sayfa tablosunun boyutudur. Belirli bir
sanal bellek alanı için sayfa boyutunu azaltmak, sayfa sayısını ve dolayısıyla sayfa
tablosunun boyutunu artırır. Örneğin 4 MB (222) sanal bellek için 4.096 sayfa 1.024
bayt, ancak yalnızca 512 sayfa 8.192 bayt olacaktır. Her etkin işlemin kendi sayfa
tablosu kopyasına sahip olması gerektiğinden, büyük bir sayfa boyutu tercih edilir.

Bununla birlikte, bellek daha küçük sayfalarda daha iyi kullanılır. Bir işleme
00000 konumundan başlayan ve ihtiyaç duyduğu kadarına sahip olana kadar devam
eden bir bellek tahsis edilirse, muhtemelen tam olarak bir sayfa sınırında
bitmeyecektir. Bu nedenle, son sayfanın bir kısmı tahsis edilmelidir (çünkü sayfalar
tahsis birimleridir), ancak kullanılmayacaktır (iç parçalanma yaratarak). İşlem
boyutundan ve sayfa boyutundan bağımsız olduğunu varsayarsak, ortalama olarak
her işlemin son sayfasının yarısının boşa gitmesini bekleyebiliriz. Bu kayıp 512 baytlık
bir sayfa için yalnızca 256 bayt iken 8.192 baytlık bir sayfa için 4.096 bayttır. Dahili
parçalanmayı en aza indirmek için küçük bir sayfa boyutuna ihtiyacımız var.
Başka bir sorun, bir sayfayı okumak veya yazmak için gereken zamandır. Bölüm
11.1'de göreceğiniz gibi, depolama aygıtı bir HDD olduğunda, G/Ç süresi arama,
gecikme ve aktarım sürelerinden oluşur. Aktarım süresi, aktarılan miktarla (yani sayfa
boyutuyla) orantılıdır; bu, küçük bir sayfa boyutu için tartışılacak gibi görünen bir
gerçektir. Ancak, gecikme ve arama süresi normalde aktarım süresini cüce eder.
Saniyede 50 MB aktarım hızında, 512 bayt aktarımı yalnızca 0,01 milisaniye sürer.
Ancak gecikme süresi belki 3 milisaniyedir ve arama süresi 5 milisaniyedir. Toplam G/
Ç süresinin (8.01 milisaniye), bu nedenle, gerçek aktarıma yalnızca yaklaşık yüzde
0,1'i atfedilebilir. Sayfa boyutunu iki katına çıkarmak, G/Ç süresini yalnızca 8,02
milisaniyeye çıkarır. 1.024 baytlık tek bir sayfayı okumak 8.02 milisaniye, her biri 512
baytlık iki sayfayla aynı miktarda okumak 16.02 milisaniye sürer. Bu nedenle, G/Ç
süresini en aza indirme arzusu, daha büyük bir sayfa boyutu için tartışır.

Daha küçük bir sayfa boyutuyla, yerellik iyileştirileceğinden, toplam G/Ç


azaltılmalıdır. Daha küçük bir sayfa boyutu, her sayfanın program konumuyla daha
doğru bir şekilde eşleşmesini sağlar. Örneğin, yalnızca yarısı (100 KB) gerçekte bir
yürütmede kullanılan 200 KB boyutunda bir işlemi düşünün. Sadece bir büyük
sayfamız varsa, tüm sayfaya aktarmalıyız, aktarılan ve tahsis edilen toplam 200 KB .
Bunun yerine yalnızca 1 baytlık sayfalarımız olsaydı, yalnızca gerçekte kullanılan 100
KB'yi getirebilirdik, bu da yalnızca 100 KB'nin aktarılıp tahsis edilmesiyle sonuçlanırdı.
Daha küçük sayfa boyutuyla, daha iyi çözünürlüğe sahip oluyoruz ve bu da yalnızca
gerçekten ihtiyaç duyulan belleği ayırmamıza izin veriyor. Daha büyük bir sayfa
boyutuyla, sadece gerekli olanı değil, aynı zamanda başka her şeyi de tahsis etmeli ve aktarmalıyız.
Machine Translated by Google

432 Bölüm 10 Sanal Bellek


bu, gerekli olsun ya da olmasın, sayfada olur. Bu nedenle, daha küçük bir sayfa
boyutu daha az G/Ç ve daha az toplam ayrılan bellek ile sonuçlanmalıdır.
Ancak 1 baytlık bir sayfa boyutuyla her bayt için bir sayfa hatası alacağımızı fark
ettiniz mi? Bu belleğin yalnızca yarısını kullanan 200 KB'lik bir işlem, 200 KB sayfa
boyutunda yalnızca bir sayfa hatası, ancak sayfa boyutu 1 bayt olan 102.400 sayfa
hatası oluşturur. Her sayfa hatası, kesmenin işlenmesi, kayıtların kaydedilmesi, bir
sayfanın değiştirilmesi, sayfalama aygıtının sıraya alınması ve tabloların
güncellenmesi için gereken büyük miktarda ek yükü oluşturur. Sayfa hatalarının
sayısını en aza indirmek için büyük bir sayfa boyutuna ihtiyacımız var.
Diğer faktörler de dikkate alınmalıdır (sayfa boyutu ile sayfalama aygıtındaki
sektör boyutu arasındaki ilişki gibi). Sorunun en iyi cevabı yok. Gördüğümüz gibi,
bazı faktörler (iç parçalanma, yerellik) küçük bir sayfa boyutunu savunurken,
diğerleri (tablo boyutu, G/Ç süresi) büyük bir sayfa boyutu için tartışır. Bununla
birlikte, tarihsel eğilim, mobil sistemler için bile daha büyük sayfa boyutlarına
yöneliktir. Aslında, İşletim Sistemi Kavramları'nın (1983) ilk baskısı, sayfa boyutlarının
üst sınırı olarak 4.096 bayt kullanmıştır ve bu değer 1990'da en yaygın sayfa
boyutuydu. aşağıdaki bölüm.

10.9.3 TLB Erişimi

9. Bölümde , TLB'nin isabet oranını tanıttık . TLB için isabet oranının , sayfa
tablosundan ziyade TLB'de çözümlenen sanal adres çevirilerinin yüzdesini ifade
ettiğini hatırlayın. Açıkçası, isabet oranı TLB'deki giriş sayısı ile ilgilidir ve isabet
oranını artırmanın yolu, giriş sayısını artırmaktır. Ancak bu, TLB'yi oluşturmak için
kullanılan çağrışımsal bellek hem pahalı hem de güç tükettiği için ucuza gelmiyor .

İsabet oranıyla ilgili benzer bir ölçümdür: TLB erişimi. TLB erişimi , TLB'den
erişilebilen bellek miktarını ifade eder ve yalnızca sayfa boyutuyla çarpılan giriş
sayısıdır. İdeal olarak, bir işlem için çalışma seti TLB'de saklanır. Değilse, işlem TLB
yerine sayfa tablosundaki bellek referanslarını çözmek için önemli miktarda zaman
harcar . TLB'deki giriş sayısını ikiye katlarsak, TLB erişimini ikiye katlarız . Ancak, bazı
bellek yoğun uygulamalar için bu, çalışma setini depolamak için yine de yetersiz
olabilir.

TLB erişimini artırmaya yönelik başka bir yaklaşım , sayfa boyutunu artırmak
veya birden çok sayfa boyutu sağlamaktır. Sayfa boyutunu 4 KB'den 16 KB'ye
çıkarırsak, TLB erişimini dört katına çıkarırız. Ancak bu, bu kadar büyük sayfa boyutu
gerektirmeyen bazı uygulamalar için parçalanmanın artmasına neden olabilir.
Alternatif olarak, çoğu mimari birden fazla sayfa boyutu için destek sağlar ve bu
destekten yararlanmak için bir işletim sistemi yapılandırılabilir. Örneğin, Linux
sistemlerinde varsayılan sayfa boyutu 4 KB'dir; bununla birlikte, Linux ayrıca büyük
sayfalar da sağlar; bu özellik, daha büyük sayfaların (örneğin, 2 MB) kullanılabileceği
bir fiziksel bellek bölgesini belirtir .
ARMv8 mimarisinin farklı boyutlardaki sayfalar ve bölgeler için destek
sağladığını Bölüm 9.7'den hatırlayın. Ek olarak, ARMv8'deki her TLB girişi bitişik bir
bit içerir . Bu bit belirli bir TLB girişi için ayarlanmışsa, bu giriş bitişik (bitişik) bellek
bloklarını eşler. Üç olası düzenleme
Machine Translated by Google

10.9 Diğer Hususlar 433

bitişik bloklar tek bir TLB girişinde eşlenebilir , böylece


TLB erişimi:

1. 16 × 4 KB bitişik bloklardan oluşan 64 KB TLB girişi.

2. 32 × 32 MB bitişik bloklardan oluşan 1 GB TLB girişi.

3. 32 × 64 KB bitişik blokları veya 128 × 16 KB bitişik blokları içeren 2-MB TLB girişi .

Birden çok sayfa boyutu için destek sağlamak, TLB'yi yönetmek için donanım
yerine işletim sisteminin gerektirebilir . Örneğin, bir TLB girişindeki alanlardan biri,
girişe karşılık gelen sayfa çerçevesinin boyutunu belirtmelidir veya ARM mimarileri
durumunda, girişin bitişik bir bellek bloğuna atıfta bulunduğunu belirtmelidir. TLB'yi
donanımda değil yazılımda yönetmenin performansta bir maliyeti vardır. Ancak artan
isabet oranı ve TLB erişimi performans maliyetlerini dengeler.

10.9.4 Ters Sayfa Tabloları

Bölüm 9.4.3, tersine çevrilmiş sayfa tablosu kavramını tanıttı. Bu sayfa yönetimi
biçiminin amacı, sanaldan fiziksele adres çevirilerini izlemek için gereken fiziksel
bellek miktarını azaltmaktır. Bu tasarrufu, <işlem-kimliği, sayfa-numarası> çifti
tarafından indekslenen, fiziksel belleğin her sayfası için bir girişi olan bir tablo
oluşturarak gerçekleştiririz.
Her bir fiziksel çerçevede hangi sanal bellek sayfasının depolandığı hakkında
bilgi tuttukları için, ters çevrilmiş sayfa tabloları bu bilgiyi depolamak için gereken
fiziksel bellek miktarını azaltır. Ancak, tersine çevrilmiş sayfa tablosu artık bir işlemin
mantıksal adres alanı hakkında tam bilgi içermez ve başvurulan bir sayfa şu anda
bellekte değilse bu bilgi gereklidir. Talep sayfalama, sayfa hatalarını işlemek için bu
bilgiyi gerektirir. Bilginin mevcut olması için harici bir sayfa tablosu (işlem başına bir
tane) tutulmalıdır. Bu tür tabloların her biri geleneksel süreç başına sayfa tablosuna
benzer ve her bir sanal sayfanın nerede bulunduğuna ilişkin bilgileri içerir.

Ancak harici sayfa tabloları, ters çevrilmiş sayfa tablolarının faydasını olumsuzlar
mı? Bu tablolara yalnızca bir sayfa hatası oluştuğunda başvurulduğundan, hızlı bir
şekilde kullanılabilir olmaları gerekmez. Bunun yerine, gerektiği şekilde belleğe girip
çıkarlar. Ne yazık ki, bir sayfa hatası artık sanal bellek yöneticisinin, sanal sayfayı
yedekleme deposunda bulması için ihtiyaç duyduğu harici sayfa tablosunda sayfalar
oluştururken başka bir sayfa hatası oluşturmasına neden olabilir. Bu özel durum,
çekirdekte dikkatli işlem yapılmasını ve sayfa arama işleminde gecikme olmasını gerektirir.

10.9.5 Program Yapısı

Talep sayfalama, kullanıcı programı için şeffaf olacak şekilde tasarlanmıştır. Çoğu
durumda, kullanıcı belleğin disk belleği doğasından tamamen habersizdir. Ancak
diğer durumlarda, kullanıcı (veya derleyici) altta yatan talep sayfalama konusunda bir
farkındalığa sahipse sistem performansı geliştirilebilir.
Yapmacık ama bilgilendirici bir örneğe bakalım. Sayfaların boyutunun 128 kelime
olduğunu varsayın. İşlevi 128'e 128 dizinin her öğesini 0'a başlatmak olan bir C
programı düşünün. Aşağıdaki kod tipiktir:
434 Bölüm 10 Sanal Bellek
Machine Translated by Google

int i, j;
int[128][128] veri;

(j = 0; j < 128; j++) için


(i = 0; i < 128; i++) için data[i][j] =
0;

Dizinin ana satırda saklandığına dikkat edin; yani dizi depolanır data[0][0], data[0]
[1], ···, data[0][127], data[1][0], data[1][1] , ···, veri[127][127]. 128 kelimelik sayfalar için
her satır bir sayfa alır. Böylece, önceki kod her sayfada bir kelimeyi, ardından her
sayfada başka bir kelimeyi sıfırlar ve bu böyle devam eder. İşletim sistemi tüm
programa 128'den az çerçeve ayırırsa, yürütülmesi 128 × 128 = 16.384 sayfa hatasıyla
sonuçlanacaktır.
Buna karşılık, kodu şu şekilde değiştirdiğimizi varsayalım:

int i, j;
int[128][128] veri;

için (i = 0; i < 128; i++)


(j = 0; j < 128; j++) için data[i][j] =
0;

Bu kod, sonraki sayfaya başlamadan önce bir sayfadaki tüm kelimeleri sıfırlar ve sayfa
hatalarının sayısını 128'e düşürür.
Veri yapılarının ve programlama yapılarının dikkatli seçimi, yerelliği artırabilir ve
dolayısıyla sayfa hata oranını ve çalışma kümesindeki sayfa sayısını azaltabilir. Örneğin,
erişim her zaman en üste yapıldığından, bir yığın iyi bir konuma sahiptir. Buna karşılık,
bir karma tablo, referansları dağıtmak ve kötü yerellik üretmek için tasarlanmıştır.
Elbette, referansın yeri, bir veri yapısının kullanımının verimliliğinin sadece bir
ölçüsüdür. Diğer ağır ağırlıklı faktörler arasında arama hızı, toplam bellek referansı
sayısı ve dokunulan toplam sayfa sayısı yer alır.

Daha sonraki bir aşamada, derleyici ve yükleyici, sayfalama üzerinde önemli bir etkiye
sahip olabilir. Kodu ve verileri ayırmak ve yeniden giriş kodu oluşturmak, kod sayfalarının
salt okunur olabileceği ve dolayısıyla hiçbir zaman değiştirilemeyeceği anlamına gelir.
Temiz sayfaların değiştirilmeleri için sayfalarının çıkarılması gerekmez. Yükleyici, her bir
rutini tamamen tek bir sayfada tutarak rutinleri sayfa sınırlarının ötesine yerleştirmekten kaçınabi
Birbirini defalarca arayan rutinler aynı sayfaya sığdırılabilir.
Bu paketleme, yöneylem araştırmasının bin-paketleme probleminin bir çeşididir:
değişken boyutlu yük bölümlerini sabit boyutlu sayfalara yerleştirmeye çalışın,
böylece sayfalar arası referanslar en aza indirilir. Böyle bir yaklaşım, özellikle büyük
sayfa boyutları için kullanışlıdır.

10.9.6 G/Ç Kilidi ve Sayfa Kilitleme


Talep sayfalama kullanıldığında, bazen bazı sayfaların bellekte kilitlenmesine izin
vermemiz gerekir. Böyle bir durum , kullanıcı (sanal) belleğine veya bu bellekten G/Ç
yapıldığında ortaya çıkar. G/Ç genellikle ayrı bir G/Ç işlemcisi tarafından uygulanır.
Örneğin, bir USB depolama aygıtının denetleyicisine genellikle şu numara verilir:
Machine Translated by Google

10.9 Diğer Hususlar 435

aktarılacak bayt sayısı ve arabellek için bir bellek adresi (Şekil 10.28). Aktarım
tamamlandığında CPU kesintiye uğrar.
Aşağıdaki olaylar dizisinin meydana gelmediğinden emin olmalıyız: Bir işlem
bir G/Ç isteği yayınlar ve bu G/Ç aygıtı için kuyruğa alınır. Bu arada CPU diğer
işlemlere verilir. Bu işlemler sayfa hatalarına neden olur ve bunlardan biri, global bir
değiştirme algoritması kullanarak, bekleme işlemi için bellek arabelleğini içeren
sayfayı değiştirir. Sayfalar sayfalandırılmıştır. Bir süre sonra, G/Ç isteği aygıt
kuyruğunun başına geçtiğinde, belirtilen adrese G/Ç gerçekleşir. Ancak bu çerçeve
artık başka bir işleme ait farklı bir sayfa için kullanılıyor.

Bu sorunun iki ortak çözümü vardır. Bir çözüm, hiçbir zaman kullanıcı belleğine
G/Ç yürütmemektir. Bunun yerine, veriler her zaman sistem belleği ile kullanıcı
belleği arasında kopyalanır. G/Ç yalnızca sistem belleği ile G/Ç aygıtı arasında
gerçekleşir. Bu yüzden teyp üzerine bir blok yazmak için önce bloğu sistem
belleğine kopyalıyoruz ve sonra teybe yazıyoruz. Bu fazladan kopyalama, kabul
edilemez derecede yüksek ek yüke neden olabilir.
Başka bir çözüm, sayfaların belleğe kilitlenmesine izin vermektir. Burada, her
çerçeve ile bir kilit biti ilişkilendirilir. Çerçeve kilitliyse, değiştirilmek üzere seçilemez.
Bu yaklaşım altında, diske bir blok yazmak için, bloğu içeren sayfaları belleğe
kilitleriz. Sistem daha sonra her zamanki gibi devam edebilir.
Kilitli sayfalar değiştirilemez. G/Ç tamamlandığında , sayfalar
kilidi açıldı.
Kilit bitleri çeşitli durumlarda kullanılır. Sıklıkla, işletim sistemi çekirdeğinin bir
kısmı veya tamamı belleğe kilitlenir. Çoğu işletim sistemi, çekirdekten veya bellek
yönetimini gerçekleştiren de dahil olmak üzere belirli bir çekirdek modülünden
kaynaklanan bir sayfa hatasına tahammül edemez. Kullanıcı işlemlerinin ayrıca
sayfaları belleğe kilitlemesi gerekebilir. Bir veritabanı işlemi, örneğin blokları ikincil
depolama ve depolama arasında taşımak gibi bir bellek yığınını yönetmek isteyebilir.

tampon

disk sürücüsü

Şekil 10.28 G/Ç için kullanılan çerçevelerin neden bellekte olması gerektiğinin nedeni.
Machine Translated by Google

436 Bölüm 10 Sanal Bellek

belleğin kendisidir, çünkü verilerini nasıl kullanacağına dair en iyi bilgiye sahiptir.
Sayfaların bellekte bu şekilde sabitlenmesi oldukça yaygındır ve çoğu işletim
sisteminde, bir uygulamanın mantıksal adres alanının bir bölgesinin sabitlenmesini
istemesine izin veren bir sistem çağrısı vardır. Bu özelliğin kötüye kullanılabileceğini
ve bellek yönetimi algoritmalarında strese neden olabileceğini unutmayın. Bu
nedenle, bir uygulama genellikle böyle bir istekte bulunmak için özel ayrıcalıklar gerektirir.
Kilit biti için başka bir kullanım, normal sayfa değiştirmeyi içerir. Aşağıdaki
olaylar dizisini göz önünde bulundurun: Düşük öncelikli bir süreç hataları. Yedek
çerçeve seçildiğinde, çağrı sistemi gerekli sayfayı belleğe okur.
Devam etmeye hazır, düşük öncelikli süreç hazır kuyruğuna girer ve CPU'yu bekler .
Düşük öncelikli bir süreç olduğundan, bir süre CPU zamanlayıcısı tarafından
seçilmeyebilir . Düşük öncelikli süreç beklerken, yüksek öncelikli bir süreç arızalanır.
Değiştirme ararken, çağrı sistemi bellekte bulunan ancak referans alınmamış veya
değiştirilmemiş bir sayfa görür: bu, düşük öncelikli işlemin yeni getirdiği sayfadır.
Bu sayfa mükemmel bir değiştirme gibi görünüyor.
Temizdir ve yazılmasına gerek yoktur ve görünüşe göre uzun süredir kullanılmamıştır.

Yüksek öncelikli sürecin düşük öncelikli sürecin yerini alıp alamayacağı bir
politika kararıdır. Sonuçta, yüksek öncelikli sürecin yararına düşük öncelikli süreci
erteliyoruz. Ancak, düşük öncelikli süreç için sayfayı getirmek için harcanan çabayı
boşa harcıyoruz.
Yeni getirilen bir sayfanın en az bir kez kullanılabilene kadar değiştirilmesini
engellemeye karar verirsek, bu mekanizmayı uygulamak için kilit bitini kullanabiliriz.
Değiştirilmek üzere bir sayfa seçildiğinde, kilit biti açılır. Arıza süreci tekrar
gönderilene kadar açık kalır.
Bir kilit biti kullanmak tehlikeli olabilir: kilit biti açılabilir ama asla kapanmayabilir.
Bu durum meydana gelirse (örneğin işletim sistemindeki bir hata nedeniyle), kilitli
çerçeve kullanılamaz hale gelir. Örneğin, Solaris kilitleme "ipuçlarına" izin verir,
ancak serbest çerçeve havuzu çok küçülürse veya bireysel bir işlem bellekte çok
fazla sayfanın kilitlenmesini isterse bu ipuçlarını göz ardı etmekte serbesttir.

10.10 İşletim Sistemi Örnekleri

Bu bölümde Linux, Windows ve Solaris'in sanal belleği nasıl yönettiğini açıklıyoruz.

10.10.1 Linux
Bölüm 10.8.2'de, Linux'un slab tahsisini kullanarak çekirdek belleği nasıl yönettiğini
tartıştık. Şimdi Linux'un sanal belleği nasıl yönettiğini ele alıyoruz. Linux, sayfaları
boş çerçeveler listesinden ayırarak talep çağrısını kullanır. Ayrıca, Bölüm 10.4.5.2'de
açıklanan LRU yaklaşımı saat algoritmasına benzer bir genel sayfa değiştirme ilkesi
kullanır . Linux, belleği yönetmek için iki tür sayfa listesi tutar: etkin liste ve etkin
olmayan liste. Aktif liste , kullanımda olduğu düşünülen sayfaları içerirken, aktif
olmayan liste , yakın zamanda referans verilmemiş ve geri alınmaya uygun sayfaları
içerir.
Machine Translated by Google

10.10 İşletim Sistemi Örnekleri 437

başvurulan

yeni
arka ön
sayfa

aktif_liste

başvurulan

ön arka

inactive_list

Şekil 10.29 Linux aktif listesi ve aktif olmayan liste yapıları.

Her sayfa, sayfaya her başvuru yapıldığında ayarlanan bir erişim bitine sahiptir.
(Sayfa erişimini işaretlemek için kullanılan gerçek bitler mimariye göre değişir.)
önce tahsis edilir, erişilen biti ayarlanır ve dizinin arkasına eklenir.
aktif liste. Benzer şekilde, etkin listedeki bir sayfaya başvurulduğunda,
erişilen biti ayarlanır ve sayfa listenin arkasına taşınır. Periyodik olarak,
aktif listedeki sayfalar için erişilen bitler sıfırlanır. Zamanla, en az
son kullanılan sayfa aktif listenin başında olacaktır . Oradan, olabilir
etkin olmayan listenin arkasına taşıyın. Etkin olmayan listede bir sayfa varsa
referans alındığında, aktif listenin arkasına geri döner . Bu desen
Şekil 10.29'da gösterilmiştir.
İki liste göreceli dengede tutulur ve aktif liste büyüdüğünde
etkin olmayan listeden çok daha büyük, etkin listenin önündeki sayfalar
ıslah için uygun hale geldikleri etkin olmayan listeye gidin. bu
Linux çekirdeğinde, sistemdeki boş bellek miktarını periyodik olarak uyandıran ve
kontrol eden bir sayfa çıkış arka plan süreci süreci kswapd vardır. Eğer boş hafıza
belirli bir eşiğin altına düşerse, kswapd etkin olmayan listedeki sayfaları taramaya
ve bunları ücretsiz liste için geri almaya başlar. Linux sanal bellek yönetimi, Bölüm
20'de daha ayrıntılı olarak tartışılmaktadır.

10.10.2 Pencereler

Windows 10, Intel üzerinde çalışan 32 ve 64 bit sistemleri destekler (IA-32 ve x86-
64) ve ARM mimarileri. 32 bit sistemlerde varsayılan sanal adres alanı
2 GB'dir, ancak 3 GB'a kadar genişletilebilir. 32 bit sistem desteği
4 GB fiziksel bellek. 64 bit sistemlerde Windows 10, 128 TB sanal adres alanına sahiptir
ve 24 TB'a kadar fiziksel belleği destekler. (Sürümleri
Windows Server 128 TB'a kadar fiziksel belleği destekler.) Windows 10, şu ana kadar
açıklanan bellek yönetimi özelliklerinin çoğunu uygular.
paylaşılan kitaplıklar, talep sayfalama, yazma üzerine kopyalama, sayfalama ve bellek
sıkıştırma.
Machine Translated by Google

438 Bölüm 10 Sanal Bellek

Windows 10 , bellek referanslarının yerelliğini tanıyan ve bu nedenle


yalnızca hatalı sayfayı değil, aynı zamanda hatalı sayfadan hemen önceki ve
sonraki birkaç sayfayı da getirerek sayfa hatalarını işleyen bir strateji olan
kümeleme ile talep sayfalamayı kullanarak sanal belleği uygular . Bir kümenin
boyutu, sayfa türüne göre değişir. Bir veri sayfası için, bir küme üç sayfa
içerir (hatalı sayfadan önceki sayfa ve sonraki sayfa); diğer tüm sayfa
hatalarının küme boyutu yedidir.
Windows 10'da sanal bellek yönetiminin önemli bir bileşeni, çalışma
kümesi yönetimidir. Bir proses oluşturulduğunda en az 50 sayfalık bir çalışma
seti ve en fazla 345 sayfalık bir çalışma seti atanır. Çalışma kümesi minimumu ,
işlemin bellekte bulunması garanti edilen minimum sayfa sayısıdır; yeterli
bellek varsa, bir işleme maksimum çalışma kümesi kadar sayfa atanabilir . Bir
süreç, sıkı çalışma sınırlarıyla yapılandırılmadıkça, bu değerler göz ardı
edilebilir. Yeterli bellek varsa, bir işlem çalışma kümesi maksimumunun
ötesine geçebilir.
Benzer şekilde, bir işleme ayrılan bellek miktarı, bellek talebinin yüksek olduğu
dönemlerde minimumun altına düşebilir.
Windows , yerel ve global sayfa değiştirme ilkelerinin bir kombinasyonu
ile Bölüm 10.4.5.2'de açıklandığı gibi LRU yaklaşımı saat algoritmasını kullanır.
Sanal bellek yöneticisi, boş sayfa çerçevelerinin bir listesini tutar. Bu listeyle
ilişkili olarak, yeterli boş belleğin mevcut olup olmadığını gösteren bir eşik
değeri bulunur. Çalışma kümesi maksimumunun altındaki bir işlem için bir
sayfa hatası meydana gelirse, sanal bellek yöneticisi boş sayfalar listesinden
bir sayfa tahsis eder. Maksimum çalışma kümesinde olan bir işlem bir sayfa
hatasına neden olursa ve yeterli bellek varsa, işleme, çalışma kümesi
maksimumunun ötesine geçmesine izin veren boş bir sayfa tahsis edilir.
Bununla birlikte, boş bellek miktarı yetersizse, çekirdek, yerel bir LRU sayfa
değiştirme ilkesi kullanarak değiştirilmek üzere işlemin çalışma kümesinden bir sayfa seçmelidir .
Boş bellek miktarı eşiğin altına düştüğünde, sanal bellek yöneticisi ,
değeri eşiğin üzerindeki bir düzeye geri yüklemek için otomatik çalışma
kümesi kırpma olarak bilinen genel bir değiştirme taktiği kullanır.
Otomatik çalışma seti kırpma, işlemlere ayrılan sayfa sayısını değerlendirerek
çalışır. Bir işleme minimum çalışma kümesinden daha fazla sayfa tahsis
edilmişse, sanal bellek yöneticisi, yeterli bellek bulunana veya işlem minimum
çalışma kümesine ulaşana kadar sayfaları çalışma kümesinden kaldırır. Boşta
olan daha büyük işlemler, daha küçük, aktif işlemlerden önce hedeflenir.
Kırpma prosedürü, minimum çalışma setinin altındaki bir işlemden sayfaları
çıkarmak gerekli olsa bile, yeterli boş bellek olana kadar devam eder. Windows,
hem kullanıcı modunda hem de sistem işlemlerinde çalışma kümesi kırpma
gerçekleştirir.

10.10.3 Solaris
Solaris'te, bir iş parçacığı bir sayfa hatasına neden olduğunda, çekirdek,
bakımını yaptığı boş sayfalar listesinden kusurlu iş parçacığına bir sayfa atar.
Bu nedenle, çekirdeğin yeterli miktarda boş bellek bulundurması zorunludur.
Bu ücretsiz sayfa listesiyle ilişkili olarak , sayfalamaya başlamak için bir eşiği
temsil eden lotsfree parametresi bulunur. lotfree parametresi tipik olarak
fiziksel belleğin boyutunun 1 64'üne ayarlanır . Çekirdek, saniyede dört kez,
boş bellek miktarının lotfree'den az olup olmadığını kontrol eder. sayısı ise
Machine Translated by Google

10.10 İşletim Sistemi Örnekleri 439

ücretsiz sayfalar lotfree'nin altına düşer, sayfa çıkışı olarak bilinen bir süreç başlar .
Sayfa çıkışı işlemi, sayfaları tararken tek el yerine iki el kullanması dışında, Bölüm
10.4.2'de açıklanan ikinci şans algoritmasına benzer.
Sayfa çıkışı işlemi şu şekilde çalışır: Saatin ön ibresi bellekteki tüm sayfaları
tarar ve referans bitini 0'a ayarlar. Daha sonra, saatin arka ibresi bellekteki sayfalar
için referans bitini inceler ve referans biti olan her sayfayı ekler. hala ücretsiz listeye
0'a ayarlandı ve içeriği değiştirilmişse içeriğini ikincil depolamaya yazıyor. Solaris
ayrıca, başka bir işleme yeniden atanmadan önce sayfaya erişilirse, bir sürecin
ücretsiz listeden bir sayfayı geri almasına izin vererek küçük sayfa hatalarını da
yönetir.
Sayfa çıkışı algoritması, sayfaların taranma hızını (tarama hızı olarak bilinir )
kontrol etmek için birkaç parametre kullanır. Tarama hızı, saniyede sayfa olarak
ifade edilir ve yavaş taramadan hızlı taramaya kadar değişir. Boş bellek lotboşun
altına düştüğünde, tarama saniyede yavaş tarama sayfalarında gerçekleşir ve
kullanılabilir boş bellek miktarına bağlı olarak hızlı taramaya ilerler.
Yavaş taramanın varsayılan değeri saniyede 100 sayfadır. Hızlı tarama tipik olarak
(toplam fiziksel sayfalar)/2 sayfa/saniye, maksimum 8.192 sayfa/saniye değerine
ayarlanır. Bu, Şekil 10.30'da gösterilmektedir ( hızlı tarama maksimuma ayarlanmış
olarak).
Saatin akrep ve yelkovanı arasındaki mesafe (sayfa olarak), bir sistem parametresi
olan el yayılımı tarafından belirlenir. Ön elin biraz temizlemesi ile arka elin değerini
araştırması arasındaki süre, tarama hızına ve el yayılımına bağlıdır . Tarama hızı
saniyede 100 sayfa ve el dağılımı 1.024 sayfa ise, bir bitin ön el tarafından
ayarlandığı zaman ile arka el tarafından kontrol edildiği zaman arasında 10 saniye
geçebilir. Ancak, bellek sistemine yapılan talepler nedeniyle, birkaç binlik bir tarama
oranı nadir değildir. Bu, temizleme ve biraz araştırma arasındaki sürenin genellikle
birkaç saniye olduğu anlamına gelir.

8192
hızlı tarama

100
yavaş tarama

minfree özgür çok ücretsiz

boş hafıza miktarı

Şekil 10.30 Solaris sayfa tarayıcı.


Machine Translated by Google

440 Bölüm 10 Sanal Bellek


Yukarıda belirtildiği gibi, sayfa çıkışı işlemi belleği saniyede dört kez kontrol
eder. Ancak, boş bellek, serbest olmayan (sistemde istenen boş bellek miktarı)
değerinin altına düşerse, en azından boş belleği kullanılabilir durumda tutmak
amacıyla, sayfa çıkışı saniyede yüz kez çalışacaktır (Şekil 10.30). Sayfa çıkışı işlemi, boş
bellek miktarını ortalama 30 saniye boyunca serbest durumda tutamazsa , çekirdek
işlemleri değiştirmeye başlar, böylece değiştirilen işlemlere ayrılan tüm sayfaları
serbest bırakır. Genel olarak, çekirdek, uzun süredir boşta olan işlemleri arar. Sistem
minfree'de boş bellek miktarını koruyamıyorsa, her yeni sayfa isteği için sayfa çıkışı
işlemi çağrılır.

Sayfa tarama algoritması, tarayıcı tarafından talep edilmeye uygun olsalar bile,
birkaç işlem tarafından paylaşılan kitaplıklara ait sayfaları atlar. Algoritma ayrıca
işlemlere tahsis edilen sayfalar ile normal veri dosyalarına tahsis edilen sayfalar
arasında ayrım yapar. Bu, öncelikli çağrı olarak bilinir ve Bölüm 14.6.2'de ele alınmıştır.

10.11 Özet
• Sanal bellek, fiziksel belleği son derece geniş tek biçimli bir depolama dizisine
soyutlar. • Sanal belleğin faydaları şunları içerir: (1) bir program fiziksel bellekten

daha büyük olabilir, (2) bir programın tamamen bellekte olması gerekmez, (3) işlemler
belleği paylaşabilir ve (4) işlemler daha verimli bir şekilde oluşturulabilir. • Talep
sayfalama, sayfaların yalnızca program yürütme sırasında talep edildiğinde
yüklendiği bir tekniktir. Asla talep edilmeyen sayfalar bu nedenle asla belleğe

yüklenmez. • Halihazırda bellekte olmayan bir sayfaya erişildiğinde bir sayfa hatası
oluşur. Sayfa, destek deposundan bellekte uygun bir sayfa çerçevesine
getirilmelidir.

• Yazma üzerine kopyalama, bir alt işlemin ebeveyni ile aynı adres alanını paylaşmasına
izin verir. Alt süreç veya üst süreç bir sayfayı yazarsa (değiştirirse), sayfanın bir
kopyası yapılır.

• Kullanılabilir bellek azaldığında, bir sayfa değiştirme algoritması, yeni bir sayfayla
değiştirmek için bellekteki mevcut bir sayfayı seçer. Sayfa değiştirme
algoritmaları FIFO, optimal ve LRU'yu içerir. Saf LRU algoritmalarının uygulanması
pratik değildir ve çoğu sistem bunun yerine LRU yaklaşımı algoritmalarını
kullanır.

• Global sayfa değiştirme algoritmaları, sistemdeki herhangi bir işlemden


değiştirilmek üzere bir sayfa seçerken, yerel sayfa değiştirme algoritmaları,
arıza sürecinden bir sayfa seçer. • Thrashing, bir sistem sayfalamaya çalışmaktan

daha fazla zaman harcadığında meydana gelir. • Bir yer, birlikte aktif olarak kullanılan

bir dizi sayfayı temsil eder. Bir süreç yürütülürken yerellikten yerelliğe doğru
hareket eder. Bir çalışma kümesi, yerelliğe dayalıdır ve bir işlem tarafından şu
anda kullanımda olan sayfalar kümesi olarak tanımlanır.
Alıştırmalar 441
Machine Translated by Google
• Bellek sıkıştırma, birkaç sayfayı tek bir sayfaya sıkıştıran bir bellek yönetimi tekniğidir.
Sıkıştırılmış bellek, sayfalamaya bir alternatiftir ve sayfalamayı desteklemeyen mobil
sistemlerde kullanılır.

• Çekirdek belleği, kullanıcı modu işlemlerinden farklı şekilde tahsis edilir; değişen
boyutlarda bitişik parçalar halinde tahsis edilmiştir. Çekirdek belleği tahsis
etmek için iki yaygın teknik şunlardır: (1) buddy sistemi ve (2) levha tahsisi. • TLB
erişimi, TLB'den erişilebilen bellek miktarını ifade eder ve TLB'deki giriş sayısının
sayfa boyutuyla çarpımına eşittir. TLB erişimini artırmaya yönelik bir teknik ,
sayfaların boyutunu artırmaktır. • Linux, Windows ve Solaris, diğer özelliklerin
yanı sıra isteğe bağlı sayfalama ve yazma üzerine kopyalamayı kullanarak sanal
belleği benzer şekilde yönetir. Her sistem ayrıca , saat algoritması olarak bilinen
bir LRU yaklaşımı varyasyonu kullanır .

Alıştırmalar

10.1 Hangi durumlarda sayfa hataları oluşur? Bir sayfa hatası oluştuğunda işletim
sistemi tarafından gerçekleştirilen eylemleri açıklayın.
10.2 m çerçeveli (başlangıçta tamamı boş) bir işlem için bir sayfa referans dizginiz
olduğunu varsayın . Sayfa referans dizesinin uzunluğu p'dir ve içinde n
farklı sayfa numarası bulunur. Herhangi bir sayfa değiştirme algoritması
için şu soruları yanıtlayın: a. Sayfa hatası sayısının alt sınırı nedir? b. Sayfa
hatası sayısının üst sınırı nedir?

10.3 Aşağıdaki sayfa değiştirme algoritmalarını göz önünde bulundurun. Bu


algoritmaları sayfa hata oranlarına göre "kötü"den "mükemmel"e beş
puanlık bir ölçekte sıralayın. Belady'nin anomalisinden muzdarip olan
algoritmaları, olmayanlardan ayırın. a. LRU'nun değiştirilmesi b. FIFO
değiştirme

c. Optimum değiştirme
d. İkinci şans değiştirme
10.4 Bir işletim sistemi, disk belleğine alınmış bir sanal belleği destekler. Merkezi
işlemcinin çevrim süresi 1 mikrosaniyedir. Mevcut sayfadan farklı bir sayfaya
erişmek için ek 1 mikrosaniye maliyeti vardır. Sayfalar 1.000 kelimeye sahiptir
ve çağrı cihazı dakikada 3.000 devirde dönen ve saniyede 1 milyon kelime
aktaran bir tamburdur. Sistemden aşağıdaki istatistiksel ölçümler elde
edildi:
• Yürütülen tüm talimatların yüzde biri, aşağıdakilerden başka bir sayfaya erişti:
geçerli sayfa.
• Başka bir sayfaya erişen talimatların yüzde 80'i zaten bellekte bulunan bir
sayfaya erişti.
442 Bölüm
Machine Translated by Google 10 Sanal Bellek
• Yeni bir sayfa gerektiğinde değiştirilen sayfa değiştirildi
Zamanın yüzde 50'si.

Sistemin yalnızca bir işlem yürüttüğünü ve tambur aktarımları sırasında


işlemcinin boşta olduğunu varsayarak, bu sistemdeki etkin talimat süresini
hesaplayın.

10.5 12-bit sanal ve fiziksel adresleri ve 256-byte sayfaları olan bir sistem için sayfa
tablosunu düşünün.

Sayfa Sayfa Çerçevesi

0 -

1 2

2 C

3 A

4 -

5 4
6 3

7 -

8 B

9 0

Boş sayfa çerçevelerinin listesi D, E, F'dir (yani, D listenin başındadır, E ikincidir


ve F sondur). Sayfa çerçevesi için kısa çizgi, sayfanın bellekte olmadığını
gösterir.
Aşağıdaki sanal adresleri eşdeğer fiziksel adreslerine dönüştürün
adresler onaltılı olarak. Tüm sayılar onaltılık olarak verilmiştir.

• 9EF
• 111
• 700
• 0FF

10.6 Talep çağrısını desteklemek için gereken donanım işlevlerini tartışın.

10.7 İki boyutlu A dizisini düşünün:


int A[][] = yeni int[100][100];

burada A[0][0], sayfa boyutu 200 olan bir disk belleği sisteminde 200
konumundadır. Matrisi yöneten küçük bir işlem, sayfa 0'da bulunur (0 ila 199
konumları). Böylece, her talimat getirme, sayfa 0'dan olacaktır.
Üç sayfa çerçevesi için, aşağıdaki dizi başlatma döngüleri tarafından kaç
sayfa hatası üretilir? LRU değiştirmeyi kullanın ve
Alıştırmalar 443
Machine Translated by Google

bu sayfa çerçevesi 1 işlemi içerir ve diğer ikisi başlangıçta boştur.

a. for (int j = 0; j < 100; j++)


for (int i = 0; i < 100; i++)
A[i][j] = 0;
b. for (int i = 0; i < 100; i++) for (int j = 0; j <
100; j++)
A[i][j] = 0;

10.8 Aşağıdaki sayfa referans dizesini göz önünde bulundurun:

1, 2, 3, 4, 2, 1, 5, 6, 2, 1, 2, 3, 7, 6, 3, 2, 1, 2, 3, 6.

Aşağıdaki değiştirme algoritmaları için bir, iki, üç, dört, beş, altı ve yedi
çerçeve varsayıldığında kaç sayfa hatası oluşur?
Tüm çerçevelerin başlangıçta boş olduğunu unutmayın, bu nedenle ilk benzersiz
sayfalarınızın her biri bir hataya mal olur.

• LRU değişimi • FIFO

değişimi • Optimum

değişim

10.9 Aşağıdaki sayfa referans dizesini göz önünde bulundurun:

7, 2, 3, 1, 2, 5, 3, 4, 6, 7, 7, 1, 0, 5, 4, 6, 2, 3, 0 , 1.

Üç çerçeveli talep çağrısını varsayarsak, aşağıdaki değiştirme algoritmaları


için kaç sayfa hatası meydana gelir?

• LRU değişimi • FIFO

değişimi • Optimum

değişim

10.10 Bir referans biti gerektiren (ikinci şans değiştirme veya çalışma seti modeli
gibi) bir çağrı algoritması kullanmak istediğinizi, ancak donanımın bir tane
sağlamadığını varsayalım. Donanım tarafından sağlanmasa bile bir referans
bitini nasıl simüle edebileceğinizi çizin veya bunun neden mümkün
olmadığını açıklayın. Mümkünse, maliyetin ne olacağını hesaplayın.

10.11 Optimum olabileceğini düşündüğünüz yeni bir sayfa değiştirme algoritması


geliştirdiniz. Bazı çarpık test durumlarında, Belady'nin anomalisi oluşur.
Yeni algoritma optimal mi? Cevabını açıkla.
10.12 Segmentasyon, sayfalamaya benzer ancak değişken boyutlu “sayfalar” kullanır.
Biri FIFO sayfa değiştirme şemasına ve diğeri LRU sayfa değiştirme
şemasına dayanan iki segment değiştirme algoritması tanımlayın .
Segmentler aynı boyutta olmadığından, değiştirilmek üzere seçilen
segmentin yeterince küçük bırakılamayacak kadar küçük olabileceğini unutmay
Machine Translated by Google

444 Bölüm 10 Sanal Bellek

gerekli segment için ardışık konumlar. Segmentlerin yeniden


yerleştirilemeyeceği sistemler için stratejiler ve mümkün olduğunda
sistemler için stratejiler düşünün.
10.13 Çoklu programlama derecesinin şu anda dörde sabitlendiği isteğe bağlı
sayfalı bir bilgisayar sistemi düşünün. Sistem yakın zamanda CPU ve disk
belleği kullanımını belirlemek için ölçüldü . Aşağıda üç alternatif sonuç
gösterilmiştir. Her durumda, ne oluyor?
CPU kullanımını artırmak için çoklu programlama derecesi arttırılabilir mi?
Çağrı yardımcı oluyor mu?

a. CPU kullanımı yüzde 13; disk kullanımı yüzde 97 b. CPU


kullanımı yüzde 87; disk kullanımı yüzde 3 c. CPU kullanımı
yüzde 13; disk kullanımı yüzde 3

10.14 Taban ve limit kayıtlarını kullanan bir makine için bir işletim sistemimiz var,
ancak makineyi bir sayfa tablosu sağlayacak şekilde değiştirdik.
Sayfa tablosu, taban ve limit kayıtlarını simüle etmek için ayarlanabilir mi?
Nasıl olabilir veya neden olamaz?

Daha fazla okuma


Çalışma seti modeli [Denning (1968)] tarafından geliştirilmiştir. Gelişmiş saat
algoritması [Carr ve Hennessy (1981)] tarafından tartışılmıştır.
[Russinovich et al. (2017)], Windows'un sanal bellek ve bellek sıkıştırmasını nasıl
uyguladığını açıklar. Windows 10'daki sıkıştırılmış bellek, http://www.makeuseof.com/
tag/ram-compression-improves-memory-responsiveness-windows-10'da ayrıntılı
olarak tartışılmaktadır .
[McDougall ve Mauro (2007)] Solaris'te sanal belleği tartışıyorlar. Linux'taki
sanal bellek teknikleri [Love (2010)] ve [Mauerer (2008)]'de açıklanmıştır. FreeBSD ,
[McKusick et al. (2015)].

bibliyografya

[Carr ve Hennessy (1981)] WR Carr ve JL Hennessy, “WSClock—Sanal Bellek Yönetimi için Basit
ve Etkili Algoritma”, İşletim Sistemleri İlkeleri Üzerine ACM Sempozyumu Bildirileri (1981),
sayfa 87–95.

[Denning (1968)] PJ Denning, “TheWorking Set Model for Program Behavior”, Communications
of the ACM, Cilt 11, Sayı 5 (1968), sayfa 323-333.

[Love (2010)] R. Love, Linux Kernel Development, Third Edition, Developer's


Kütüphane (2010).

[Mauerer (2008)] W. Mauerer, Profesyonel Linux Çekirdek Mimarisi, John Wiley


ve Oğulları (2008).

[McDougall ve Mauro (2007)] R. McDougall ve J. Mauro, Solaris Internals, İkinci Baskı, Prentice
Hall (2007).
Machine Translated by Google

bibliyografya 445

[McKusick et al. (2015)] MK McKusick, GV Neville-Neil ve RNM Wat son, FreeBSD UNIX
İşletim Sisteminin Tasarımı ve Uygulanması –İkinci
Baskı, Pearson (2015).

[Russinovich et al. (2017)] M. Russinovich, DA Solomon ve A. Ionescu, Win


dows Internals –Bölüm 1, Yedinci Baskı, Microsoft Press (2017).
EX-35
Machine Translated by Google
Bölüm 10 Alıştırmalar

10.15 Bir programın sanal bellekte bir adrese başvurduğunu varsayın. Aşağıdakilerin her birinin
meydana gelebileceği bir senaryo tanımlayın. (Böyle bir senaryo oluşamıyorsa, nedenini
açıklayın.) • Sayfa hatası olmadan TLB eksik • Sayfa hatasıyla TLB eksik • Sayfa hatası

olmadan TLB isabeti • Sayfa hatasıyla TLB isabeti

10.16 Bir iş parçacığının hazır olduğu ve programlanmayı beklediği, işlemcide çalıştığı veya
engellendiği (örneğin, G/Ç'yi bekliyor) olduğu iş parçacığı durumlarının basitleştirilmiş
bir görünümü hazır, çalışıyor ve engellendi .

hazır

engellendi koşma

Bir iş parçacığının çalışır durumda olduğunu varsayarak, aşağıdaki soruları yanıtlayın


ve yanıtlarınızı açıklayın:

a. Bir sayfa hatasına neden olursa iş parçacığı durumu değiştirir mi? Eğer öyleyse,
hangi duruma değişecek?

b. Sayfa tablosunda çözülen bir TLB hatası oluşturursa iş parçacığı durumu değiştirir
mi? Eğer öyleyse, hangi duruma değişecek?

c. Sayfa tablosunda bir adres referansı çözülürse iş parçacığı durumu değişir mi?
Eğer öyleyse, hangi duruma değişecek?

10.17 Saf talep çağrısını kullanan bir sistem düşünün.

a. Bir süreç yürütmeye ilk başladığında, sayfa hatası oranını nasıl tanımlarsınız?

b. Bir işlem için çalışma seti belleğe yüklendikten sonra, nasıl


sayfa hata oranını karakterize eder misiniz?

c. Bir işlemin yerini değiştirdiğini ve yeni çalışma kümesinin boyutunun kullanılabilir


boş bellekte depolanamayacak kadar büyük olduğunu varsayın.
Sistem tasarımcılarının bu durumla başa çıkmak için seçebilecekleri bazı
seçenekleri belirleyin.

10.18 Aşağıda, 12 bit sanal ve fiziksel adresleri ve 256 baytlık sayfaları olan bir sistem için bir
sayfa tablosu yer almaktadır. Boş sayfa çerçeveleri 9, F, D sırasına göre tahsis edilecektir .
Bir sayfa çerçevesi için tire işareti, sayfanın bellekte olmadığını gösterir.
Egzersizler EX-36
Machine Translated by Google

Sayfa Sayfa Çerçevesi

0 0x4

1 0xB

2 0xA

3 -

4 -

5 0x2

6 -

7 0x0

8 0xC

9 0x1

Aşağıdaki sanal adresleri, onaltılı olarak eşdeğer fiziksel adreslerine


dönüştürün. Tüm sayılar onaltılık olarak verilmiştir. Bir sayfa hatası
durumunda, sayfa tablosunu güncellemek ve mantıksal adresi karşılık gelen
fiziksel adresine çözümlemek için boş çerçevelerden birini kullanmanız
gerekir.

• 0x2A1

• 0x4E6

• 0x94A

• 0x316

10.19 Yazma üzerine kopyalama özelliği nedir ve kullanımı hangi durumlarda


faydalıdır? Bu özelliği uygulamak için hangi donanım desteği gereklidir?

10.20 Belirli bir bilgisayar, kullanıcılarına 232 baytlık bir sanal bellek alanı sağlar.
Bilgisayarın 222 bayt fiziksel belleği vardır. Sanal bellek, sayfalama yoluyla
uygulanır ve sayfa boyutu 4.096 bayttır.
Bir kullanıcı işlemi sanal 11123456 adresini oluşturur. Sistemin ilgili fiziksel
konumu nasıl oluşturduğunu açıklayın. Yazılım ve donanım işlemlerini ayırt
eder.
10.21 İsteğe bağlı bir belleğimiz olduğunu varsayalım. Sayfa tablosu kayıtlarda
tutulur. Boş bir çerçeve varsa veya değiştirilen sayfa değiştirilmezse bir
sayfa hatasına hizmet vermek 8 milisaniye, değiştirilen sayfa değiştirilirse
20 milisaniye sürer. Bellek erişim süresi 100 nanosaniyedir.

Değiştirilecek sayfanın zamanın yüzde 70'inde değiştirildiğini varsayın.


200 nanosaniyeden fazla olmayan bir etkin erişim süresi için kabul edilebilir
maksimum sayfa hatası oranı nedir?

10.22 16 bit sanal ve fiziksel adresleri ve 4.096 bayt sayfaları olan bir sistem için sayfa
tablosunu düşünün.
EX-37
Machine Translated by Google

Sayfa Sayfa Çerçevesi Referans Biti

0 9 0

1 - 0

2 10 0

3 15 0

4 6 0

5 13 0

6 8 0

7 12 0

8 7 0

9 - 0

10 5 0

11 4 0

12 1 0

13 0 0

14 - 0

15 2 0

Sayfa referans alındığında, bir sayfanın referans biti 1'e ayarlanır. Periyodik
olarak, bir iş parçacığı referans bitinin tüm değerlerini sıfırlar. Sayfa çerçevesi
için kısa çizgi, sayfanın bellekte olmadığını gösterir.
Sayfa değiştirme algoritması yerelleştirilmiş LRU'dur ve tüm sayılar ondalık
olarak verilmiştir.

a. Aşağıdaki sanal adresleri (onaltılık olarak) eşdeğer fiziksel adreslere


dönüştürün. Cevapları onaltılık veya ondalık olarak verebilirsiniz. Ayrıca
sayfa tablosundaki uygun giriş için referans bitini ayarlayın.

• 0x621C
• 0xF0A3
• 0xBC1A
• 0x5BAA
• 0x0BA1

b. Yukarıdaki adresleri kılavuz olarak kullanarak, sayfa hatasıyla sonuçlanan bir


mantıksal adres (onaltılık olarak) örneği sağlayın.

c. LRU sayfa değiştirme işlemi hangi sayfa çerçeveleri grubundan olacak ?


Algoritma bir sayfa hatasını çözmede mi seçiyor?

10.23 Bir sayfa hatası oluştuğunda, sayfanın diskten fiziksel belleğe alınmasını beklerken
sayfayı isteyen işlem bloke etmelidir. Beş kullanıcı düzeyinde iş parçacığına
sahip bir işlem olduğunu ve kullanıcı iş parçacıklarının çekirdek iş parçacıklarına
eşlenmesinin bire bir olduğunu varsayalım. Eğer
Egzersizler EX-38
Machine Translated by Google

bir kullanıcı iş parçacığı yığınına erişirken bir sayfa hatasına neden olur, aynı
işleme ait diğer kullanıcı iş parçacıkları da sayfa hatasından etkilenir mi -
yani, hata veren sayfanın belleğe alınmasını da beklemeleri gerekir mi?
Açıklamak.

10.24 Aşağıdaki sayfa referans dizileri için (1) FIFO, (2) LRU ve (3) optimal (OPT)
değiştirme algoritmalarını uygulayın:

• 2, 6, 9, 2, 4, 2, 1, 7, 3, 0, 5, 2, 1, 2, 9, 5, 7, 3, 8, 5

• 0, 6, 3, 0, 2, 6, 3, 5, 2, 4, 1, 3, 0, 6, 1, 4, 2, 3, 5, 7

• 3, 1, 4, 2, 5, 4, 1, 3, 5, 2, 0, 1, 1, 0, 2, 3, 4, 5, 0, 1

• 4, 2, 1, 7, 9, 8, 3, 5, 2, 6, 8, 1, 0, 7, 2, 4, 1, 3, 5, 8

• 0, 1, 2, 3, 4, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 4, 3, 2, 1, 0

Üç çerçeveli talep çağrısını varsayan her algoritma için sayfa hatası sayısını
belirtin.

10.25 Saat algoritmasındaki işaretçinin hareket hızını izlediğinizi varsayın. (İşaretçi,


değiştirilecek aday sayfayı gösterir.) Aşağıdaki davranışı fark ederseniz,
sistem hakkında ne söyleyebilirsiniz:

a. İşaretçi hızlı hareket ediyor.

b. İşaretçi yavaş hareket ediyor.

10.26 En az kullanılan (LFU) sayfa değiştirme algoritmasının, en son kullanılan (LRU)


sayfa değiştirme algoritmasından daha az sayfa hatası ürettiği durumları
tartışın . Bunun tersinin hangi koşullar altında geçerli olduğunu da tartışın.

10.27 En sık kullanılan (MFU) sayfa değiştirme algoritmasının, en son kullanılan (LRU)
sayfa değiştirme algoritmasından daha az sayfa hatası ürettiği durumları
tartışın . Bunun tersinin hangi koşullar altında geçerli olduğunu da tartışın.

10.28 KHIE ("k-hi" olarak telaffuz edilir) işletim sistemi, yerleşik sayfalar için bir FIFO
değiştirme algoritması ve son kullanılan sayfalardan oluşan bir serbest
çerçeve havuzu kullanır. Serbest çerçeve havuzunun LRU değiştirme ilkesi
kullanılarak yönetildiğini varsayın . Aşağıdaki soruları cevaplayın:

a. Bir sayfa hatası oluşursa ve sayfa serbest çerçeve havuzunda yoksa, yeni
istenen sayfa için boş alan nasıl oluşturulur?

b. Bir sayfa hatası oluşursa ve sayfa serbest çerçeve havuzunda mevcutsa,


yerleşik sayfa seti ve serbest çerçeve havuzu, istenen sayfa için yer
açmayı nasıl başarıyor?

c. Yerleşik sayfa sayısı bire ayarlanırsa sistem neye göre dejenere olur?

d. Serbest çerçeve havuzundaki sayfa sayısı sıfırsa sistem neye göre


dejenere olur?
EX-39
Machine Translated by Google

10.29 Aşağıdaki zaman ölçümlü kullanımlara sahip bir talep çağrı sistemi düşünün:

CPU kullanımı %20


çağrı diski %97.7
Diğer G/Ç cihazları %5

Aşağıdakilerin her biri için CPU kullanımını iyileştirip iyileştirmeyeceğini (veya artırma
olasılığının yüksek olduğunu) belirtin. Cevaplarınızı açıklayın.

a. Daha hızlı bir CPU kurun .

b. Daha büyük bir disk belleği yükleyin.

c. Çoklu programlamanın derecesini artırın.

d. Çoklu programlamanın derecesini azaltın.

e. Daha fazla ana bellek takın.

f. Birden çok denetleyiciyle daha hızlı bir sabit disk veya birden çok denetleyici kurun
sabit diskler.

g. Sayfa getirme algoritmalarına ön sayfalama ekleyin. h.

Sayfa boyutunu büyütün.

10.30 Küçük sayfa hatalarının çözülmesinin neden ana sayfa hatalarından daha az zaman aldığını açıklayın
hatalar.

10.31 Mobil cihazlar için işletim sistemlerinde sıkıştırılmış belleğin neden kullanıldığını açıklayın.

10.32 Bir makinenin, tek seviyeli dolaylı adresleme şemasını kullanarak bellek konumlarına
erişebilen talimatlar sağladığını varsayalım. Bir programın tüm sayfaları o anda yerleşik
olmadığında ve programın ilk talimatı dolaylı bir bellek yükleme işlemi olduğunda hangi
sayfa hataları dizisi oluşur? İşletim sistemi işlem başına çerçeve ayırma tekniğini
kullandığında ve bu işleme yalnızca iki sayfa ayrıldığında ne olur?

10.33 Sayfa referanslarını göz önünde bulundurun:


Egzersizler EX-40
Machine Translated by Google

34

32

30

28

26

24

22

20

18
(X)
uygulama vakti

Hangi sayfalar (X) zamanında yeri temsil ediyor ?


10.34 Değiştirme politikanızın (bir disk belleği sisteminde) her sayfayı düzenli
olarak incelemek ve son incelemeden bu yana kullanılmamışsa o sayfayı
atmak olduğunu varsayalım. LRU veya ikinci şans değiştirme yerine bu
politikayı kullanarak ne kazanırsınız ve ne kaybedersiniz ?
10.35 Bir sayfa değiştirme algoritması, sayfa hatalarının sayısını en aza indirmelidir.
Bu küçültmeyi, yoğun olarak kullanılan sayfaları az sayıda sayfa çerçevesi
için rekabet etmek yerine tüm belleğe eşit olarak dağıtarak başarabiliriz.
Her sayfa çerçevesiyle, o çerçeveyle ilişkili sayfa sayısının bir sayacını
ilişkilendirebiliriz. O zamanlar,
Machine Translated by Google

EX-41

bir sayfayı değiştirmek için en küçük sayfa çerçevesini arayabiliriz.


tezgah.

a. Bu temel fikri kullanarak bir sayfa değiştirme algoritması tanımlayın. Bu


sorunları özellikle ele alın:

• Sayaçların başlangıç değeri nedir?


• Sayaçlar ne zaman artırılır?
• Sayaçlar ne zaman azaltılır?

• Değiştirilecek sayfa nasıl seçilir?

b. Dört sayfa çerçeveli aşağıdaki referans dizesi için algoritmanız için kaç
sayfa hatası oluşuyor?

1, 2, 3, 4, 5, 3, 4, 1, 6, 7, 8, 7, 8, 9, 7, 8, 9, 5, 4, 5, 4, 2.

c. Dört sayfa çerçeveli b kısmındaki referans dizesi için en uygun sayfa


değiştirme stratejisi için minimum sayfa hatası sayısı nedir?

10.36 Ortalama erişim ve aktarım süresi 20 milisaniye olan bir çağrı diskine sahip bir
talep çağrı sistemi düşünün. Adresler, bellek erişimi başına 1 mikrosaniye
erişim süresiyle ana bellekteki bir sayfa tablosu aracılığıyla çevrilir. Böylece,
sayfa tablosu aracılığıyla her bir bellek referansı iki erişim alır. Bu süreyi
iyileştirmek için, sayfa tablosu girişi ilişkisel bellekteyse, erişim süresini bir
bellek referansına indiren bir ilişkisel bellek ekledik.

Erişimlerin yüzde 80'inin ilişkisel bellekte olduğunu ve kalanların yüzde


10'unun (veya toplamın yüzde 2'sinin) sayfa hatalarına neden olduğunu
varsayalım. Etkili bellek erişim süresi nedir?

10.37 Dayak yemenin nedeni nedir? Sistem thrashing'i nasıl algılar?


Thrashing algıladığında, sistem bu sorunu ortadan kaldırmak için ne yapabilir?

10.38 Bir işlemin, biri verileri, diğeri kodu temsil eden iki çalışma kümesine sahip olması
mümkün müdür? Açıklamak.

10.39 Çalışma kümesi modelinde çalışma kümesi penceresini tanımlamak için kullanılan
Δ parametresini göz önünde bulundurun. Δ düşük bir değere ayarlandığında,
sayfa hatası sıklığı ve sistemde o anda yürütülmekte olan etkin (askıya
alınmamış) işlemlerin sayısı üzerindeki etkisi nedir? Δ çok yüksek bir değere
ayarlandığında etkisi nedir?

10.40 1.024 KB'lık bir segmentte, bellek, arkadaş sistemi kullanılarak tahsis edilir.
Şekil 10.26'yı kılavuz olarak kullanarak, aşağıdaki bellek isteklerinin nasıl tahsis
edildiğini gösteren bir ağaç çizin:

• 5 KB isteyin •

135 KB isteyin. • 14

KB isteyin . • 3 KB

isteyin .
Egzersizler EX-42
Machine Translated by Google

• 12 KB isteyin .

Ardından, aşağıdaki bellek sürümleri için ağacı değiştirin. Mümkün olduğunda


birleştirme gerçekleştirin:
• 3 KB bırakın .

• 5 KB bırakın .

• 14 KB yayınlayın.

• 12 KB yayınlayın.

10.41 Bir sistem, kullanıcı düzeyinde ve çekirdek düzeyinde iş parçacıkları için destek
sağlar. Bu sistemdeki eşleme bire birdir (her kullanıcı iş parçacığı için karşılık
gelen bir çekirdek iş parçacığı vardır). Çok iş parçacıklı bir süreç (a) tüm süreç
için bir çalışma kümesinden mi yoksa (b) her bir iş parçacığı için bir çalışma
kümesinden mi oluşur? Açıklamak

10.42 Döşeme tahsisi algoritması, her farklı nesne türü için ayrı bir önbellek kullanır. Nesne
türü başına bir önbellek olduğunu varsayarak, bu şemanın neden birden çok
CPU ile iyi ölçeklenmediğini açıklayın. Bu ölçeklenebilirlik sorununu çözmek için
ne yapılabilir?

10.43 Farklı boyutlardaki sayfaları süreçlerine tahsis eden bir sistem düşünün.
Böyle bir sayfalama düzeninin avantajları nelerdir? Bu işlevselliği sağlamak için
sanal bellek sisteminde hangi değişikliklere ihtiyaç duyulur?
Machine Translated by Google

Programlama Sorunları P-51

Programlama Sorunları

10.44 Bölüm 10.4'te sunulan FIFO, LRU ve optimal (OPT) sayfa değiştirme
algoritmalarını uygulayan bir program yazın . Programınızın başlangıçta
sayfa numaralarının 0 ile 9 arasında olduğu rastgele bir sayfa referansı
dizisi oluşturmasını sağlayın. Rastgele sayfa referansını her algoritmaya
uygulayın ve her algoritmanın neden olduğu sayfa hatalarının sayısını
kaydedin. Başlangıçta programa sayfa çerçevesi sayısını iletin.
Bu programı istediğiniz herhangi bir programlama dilinde uygulayabilirsiniz.
( Sanal bellek yöneticisi programlama projesinde yardımcı olması için FIFO
veya LRU uygulamanızı bulabilirsiniz .)

Programlama Projeleri

Bir Sanal Bellek Yöneticisi Tasarlamak Bu proje,


216 = 65.536 bayt büyüklüğünde bir sanal adres alanı için mantıksal adresleri
fiziksel adreslere çeviren bir program yazmaktan oluşur . Programınız, mantıksal
adresleri içeren bir dosyadan okuyacak ve bir TLB ve bir sayfa tablosu kullanarak,
her mantıksal adresi karşılık gelen fiziksel adresine çevirecek ve çevrilen fiziksel
adreste saklanan baytın değerini çıkaracaktır.
Öğrenme hedefiniz, mantıksal adresleri fiziksel adreslere çevirmeyle ilgili adımları
anlamak için simülasyonu kullanmaktır. Bu, talep çağrısını kullanarak sayfa
hatalarını çözmeyi, bir TLB'yi yönetmeyi ve bir sayfa değiştirme algoritmasını
uygulamayı içerecektir.

Özel

Programınız, mantıksal adresleri temsil eden birkaç 32 bit tam sayı içeren bir
dosyayı okuyacaktır. Ancak, yalnızca 16 bitlik adreslerle ilgilenmeniz gerekir, bu
nedenle her mantıksal adresin en sağdaki 16 bitini maskelemelisiniz.
Bu 16 bit (1) 8 bitlik bir sayfa numarasına ve (2) 8 bitlik bir sayfa kaymasına bölünür.
Bu nedenle, adresler aşağıdaki gibi yapılandırılmıştır:

sayfa
telafi etmek
numarası
31 1516 78 0

Diğer özellikler aşağıdakileri içerir:

• Sayfa tablosunda 28 giriş • 28


baytlık sayfa boyutu
• TLB'de 16 giriş

• 28 baytlık çerçeve boyutu


• 256 kare

• 65.536 baytlık fiziksel bellek (256 çerçeve × 256 bayt çerçeve boyutu)
Machine Translated by Google

P-52 Bölüm 10 Sanal Bellek


Ek olarak, programınızın yalnızca mantıksal adresleri okumak ve bunları karşılık
gelen fiziksel adreslerine çevirmekle ilgilenmesi gerekir. Mantıksal adres alanına
yazmayı desteklemeniz gerekmez.
Adres Tercümesi

Programınız, Bölüm 9.3'te belirtildiği gibi bir TLB ve sayfa tablosu kullanarak
mantıksal adresleri fiziksel adreslere çevirecektir . İlk olarak mantıksal adresten
sayfa numarası çıkarılır ve TLB'ye başvurulur. TLB isabeti durumunda çerçeve
numarası TLB'den alınır . TLB ıskalanması durumunda sayfa tablosuna başvurulmalıdır.
İkinci durumda, ya sayfa tablosundan çerçeve numarası alınır ya da bir sayfa hatası
oluşur. Adres çeviri sürecinin görsel bir temsili:

sayfa
telafi etmek
numarası
sayfa çerçeve
numarası numarası
0

. 0 çerçeve 0
. TLB isabeti 1 çerçeve 1
. 2 çerçeve 2
.
15 çerçeve .
sayı
telafi etmek
.
TLB .
.

0 sayfa 0 255 çerçeve 255


1 sayfa 1
fiziksel
2 sayfa 2
hafıza

.
.
TLB özledim
.
.

255 sayfa 255

sayfa
tablosu

Sayfa Hatalarını İşleme

Programınız, Bölüm 10.2'de açıklandığı gibi talep çağrısını uygulayacaktır. Destek


deposu, 65.536 bayt boyutunda bir ikili dosya olan BACKING STORE.bin dosyasıyla
temsil edilir. Bir sayfa hatası oluştuğunda, BACKING STORE dosyasından 256 baytlık
bir sayfa okuyacak ve bunu fiziksel bellekte uygun bir sayfa çerçevesine
depolayacaksınız. Örneğin, sayfa numarası 15 olan bir mantıksal adres bir sayfa
hatasıyla sonuçlanırsa, programınız BACKING STORE'dan sayfa 15'i okur ( sayfaların
0'dan başladığını ve 256 bayt boyutunda olduğunu unutmayın) ve bunu bir sayfa
çerçevesinde saklar. fiziksel hafıza. Bu çerçeve bir kez depolandığında (ve sayfa
tablosu ve TLB güncellendiğinde), sonraki 15. sayfaya erişimler ya TLB ya da sayfa
tablosu tarafından çözülecektir .
Machine Translated by Google

Programlama Projeleri P-53

BACKING STORE.bin dosyasını rastgele erişimli bir dosya olarak ele almanız
gerekecek, böylece dosyanın belirli konumlarını okumak için rastgele arayabilirsiniz. G/Ç
gerçekleştirmek için fopen(), fread(), fseek() ve fclose() dahil olmak üzere standart C
kitaplığı işlevlerini kullanmanızı öneririz .
Fiziksel belleğin boyutu, sanal adres alanının boyutuyla aynıdır—65,536 bayt—bu
nedenle bir sayfa hatası sırasında sayfa değiştirme konusunda endişelenmenize gerek
yoktur. Daha sonra, daha az miktarda fiziksel bellek kullanarak bu projede yapılan bir
değişikliği açıklayacağız; bu noktada, bir sayfa değiştirme stratejisi gerekecektir.

Test Dosyası

0 ile 65535 (sanal adres alanının boyutu) arasında değişen mantıksal adresleri temsil
eden tamsayı değerlerini içeren address.txt dosyasını sağlıyoruz. Programınız bu
dosyayı açacak, her bir mantıksal adresi okuyacak ve onu karşılık gelen fiziksel adresine
çevirecek ve fiziksel adreste imzalı baytın değerini çıkaracaktır.

Nasıl Başlanır?

İlk olarak, sayfa numarası ve ofset tabanlı olarak ayıklayan basit bir program yazın.
üzerinde:

sayfa
telafi etmek
numarası
31 1516 78 0

aşağıdaki tam sayılardan:

1, 256, 32768, 32769, 128, 65534, 33153

Belki de bunu yapmanın en kolay yolu, bit maskeleme ve bit kaydırma için operatörleri
kullanmaktır. Sayfa numarasını ve bir tamsayıdan ofseti doğru bir şekilde belirledikten
sonra, başlamaya hazırsınız demektir.
Başlangıçta TLB'yi atlamanızı ve yalnızca bir sayfa tablosu kullanmanızı öneririz .
Sayfa tablonuz düzgün çalıştığında TLB'yi entegre edebilirsiniz . Adres çevirisinin TLB
olmadan da çalışabileceğini unutmayın ; TLB sadece daha hızlı hale getirir. TLB'yi
uygulamaya hazır olduğunuzda, yalnızca on altı girişi olduğunu hatırlayın, bu nedenle
tam bir TLB'yi güncellediğinizde bir değiştirme stratejisi kullanmanız gerekecektir .
TLB'nizi güncellemek için bir FIFO veya bir LRU politikası kullanabilirsiniz .

Programınızı Nasıl Çalıştırırsınız

Programınız aşağıdaki gibi çalışmalıdır:

./a.out adresleri.txt
Programınız 0'dan 65535'e kadar 1000 mantıksal adres içeren address.txt dosyasını
okuyacaktır. Programınız, her mantıksal adresi fiziksel bir adrese çevirecek ve doğru
fiziksel adreste saklanan imzalı baytın içeriğini belirleyecektir . (C dilinde char veri
türünün bir bayt depolama alanı kapladığını hatırlayın, bu nedenle char değerlerini
kullanmanızı öneririz .)
P-54 Bölüm
Machine Translated by Google 10 Sanal Bellek
Programınız aşağıdaki değerlerin çıktısını almaktır:

1. Çevrilen mantıksal adres (okunmakta olan tamsayı değeri


address.txt).
2. Karşılık gelen fiziksel adres (programınızın mantıksal adresi neye çevirdiği).

3. Çevrilmiş fizikte fiziksel bellekte saklanan imzalı bayt değeri


adres.

Ayrıca, address.txt dosyası için doğru çıktı değerlerini içeren doğru.txt


dosyasını da sağlıyoruz . Programınızın mantıksal adresleri fiziksel adreslere doğru
çevirdiğini belirlemek için bu dosyayı kullanmalısınız.
İstatistik

Tamamlandıktan sonra, programınız aşağıdaki istatistikleri rapor edecektir:

1. Sayfa hata oranı—Bununla sonuçlanan adres referanslarının yüzdesi


sayfa hataları.

2. TLB isabet oranı—Şu anda çözülen adres referanslarının yüzdesi


TLB .

address.txt dosyasındaki mantıksal adresler rastgele oluşturulduğundan ve herhangi


bir bellek erişim konumunu yansıtmadığından, yüksek bir TLB isabeti beklemeyin.
oran.

Sayfa Değiştirme

Şimdiye kadar, bu proje fiziksel belleğin sanal adres alanı ile aynı boyutta olduğunu
varsaymıştır. Pratikte, fiziksel bellek tipik olarak bir sanal adres alanından çok daha
küçüktür. Projenin bu aşaması artık 256 yerine 128 sayfa çerçeveli daha küçük bir
fiziksel adres alanı kullanıldığını varsayar. Bu değişiklik, programınızı, boş sayfa
çerçevelerini takip edecek şekilde değiştirmeyi ve ayrıca FIFO veya Boş bellek
olmadığında sayfa hatalarını çözmek için LRU (Bölüm 10.4).
Machine Translated by Google
Machine Translated by Google

Beşinci Bölüm

Depolamak
Yönetmek
Bilgisayar sistemleri, dosyaları ve verileri kalıcı olarak depolamak için yığın depolama
sağlamalıdır. Modern bilgisayarlar, hem sabit diskleri hem de kalıcı bellek aygıtlarını kullanarak
yığın depolamayı ikincil depolama olarak uygular.
İkincil depolama aygıtları birçok açıdan farklılık gösterir. Bazıları bir seferde bir karakter,
bazıları ise bir karakter bloğu aktarır. Bazılarına yalnızca sırayla, bazılarına ise rastgele
erişilebilir. Bazıları verileri senkronize olarak, bazıları ise asenkron olarak aktarır. Bazıları
adanmış, bazıları ortak. Salt okunur veya okuma-yazma olabilirler. Hızları büyük ölçüde farklılık
gösterse de, birçok yönden bilgisayarın en yavaş ana bileşenidir.

Tüm bu cihaz çeşitliliği nedeniyle, uygulamaların cihazların tüm yönlerini kontrol


edebilmesi için işletim sisteminin geniş bir işlevsellik yelpazesi sağlaması gerekir. Bir işletim
sisteminin G/Ç alt sisteminin temel hedeflerinden biri, sistemin geri kalanı için mümkün olan
en basit arabirimi sağlamaktır. Cihazlar bir performans darboğazı olduğundan, diğer bir
anahtar, maksimum eşzamanlılık için G/Ç'yi optimize etmektir.
Machine Translated by Google
Machine Translated by Google

11 BÖLÜM
Yığın Bellek
Yapı

Bu bölümde, bir bilgisayarın kalıcı depolama sistemi olan yığın depolamanın nasıl
yapılandırıldığını tartışacağız. Modern bilgisayarlardaki ana yığın depolama
sistemi, genellikle sabit disk sürücüleri (HDD) ve kalıcı bellek (NVM) aygıtları
tarafından sağlanan ikincil depolamadır. Bazı sistemler ayrıca genellikle manyetik
bant, optik diskler ve hatta bulut depolamadan oluşan daha yavaş, daha büyük,
üçüncül depolamaya sahiptir.
Modern bilgisayar sistemlerinde en yaygın ve önemli depolama aygıtları
HDD'ler ve NVM aygıtları olduğundan, bu bölümün büyük kısmı bu iki depolama
türünü tartışmaya ayrılmıştır. Önce fiziksel yapılarını tanımlıyoruz. Ardından,
performansı en üst düzeye çıkarmak için G/Ç'lerin sırasını programlayan zamanlama
algoritmalarını ele alıyoruz . Ardından, aygıt biçimlendirmesini ve önyükleme
bloklarının, hasarlı blokların ve takas alanının yönetimini tartışacağız. Son olarak,
RAID sistemlerinin yapısını inceliyoruz .
Birçok yığın depolama türü vardır ve tartışma tüm türleri içerdiğinde, genel
geçici olmayan depolama (NVS) terimini kullanırız veya depolama "sürücüleri"
hakkında konuşuruz. HDD'ler ve NVM cihazları gibi belirli cihazlar uygun şekilde
belirtilir.

BÖLÜM HEDEFLERİ

• Çeşitli ikincil depolama cihazlarının fiziksel yapılarını tanımlayın ve


bir cihazın yapısının kullanımları üzerindeki etkisi.

• Yığın depolama cihazlarının performans özelliklerini açıklayın. • G/Ç zamanlama

algoritmalarını değerlendirin . • Aşağıdakiler dahil olmak üzere yığın depolama için

sağlanan işletim sistemi hizmetlerini tartışın:


YAĞMA.

11.1 Yığın Depolama Yapısına Genel Bakış

Modern bilgisayarlar için ikincil depolamanın büyük kısmı, sabit disk sürücüleri
(HDD'ler) ve kalıcı bellek (NVM) aygıtları tarafından sağlanır. Bu bölümde,

449
Machine Translated by Google

450 Bölüm 11 Yığın Depolama Yapısı

t izle mil

kol montajı
sektör s

okuma-yazma
silindir c
kafası

servis tabağı

kol

rotasyon

Şekil 11.1 HDD hareketli kafalı disk mekanizması.

bu cihazların temel mekanizmalarını açıklıyoruz ve işletim sistemlerinin fiziksel


özelliklerini adres eşleme yoluyla mantıksal depolamaya nasıl çevirdiğini
açıklıyoruz.

11.1.1 Sabit Disk Sürücüleri

Kavramsal olarak, HDD'ler nispeten basittir (Şekil 11.1). Her disk tabağı , CD gibi
düz dairesel bir şekle sahiptir . Ortak plaka çapları 1,8 ila 3,5 inç arasında
değişir. Bir tabağın iki yüzeyi manyetik bir malzeme ile kaplanmıştır.
Bilgileri manyetik olarak plakalara kaydederek depolarız ve plakalardaki manyetik
deseni algılayarak bilgileri okuruz.
Her tabağın her yüzeyinin hemen üzerinde bir okuma-yazma kafası “uçar”.
Kafalar, tüm kafaları bir birim olarak hareket ettiren bir disk koluna bağlanmıştır .
Bir tabağın yüzeyi mantıksal olarak sektörlere ayrılan dairesel parçalara
bölünmüştür . Belirli bir kol pozisyonundaki palet seti bir silindiri oluşturur. Bir
disk sürücüsünde binlerce eş merkezli silindir olabilir ve her iz yüzlerce sektör
içerebilir. Her sektörün sabit bir boyutu vardır ve en küçük aktarım birimidir.
Sektör boyutu, 2010 yılına kadar genellikle 512 bayttı.
Bu noktada birçok üretici 4KB sektörlerine geçiş yapmaya başlıyor. Ortak disk
sürücülerinin depolama kapasitesi gigabayt ve terabayt cinsinden ölçülür.
Kapağı çıkarılmış bir disk sürücüsü Şekil 11.2'de gösterilmiştir.
Bir disk sürücü motoru onu yüksek hızda döndürür. Çoğu sürücü, dakikada
dönüş sayısı (RPM) cinsinden belirtilen saniyede 60 ila 250 kez döner . Ortak
sürücüler 5.400, 7.200, 10.000 ve 15.000 RPM'de döner. Bazı sürücüler
kullanılmadığında kapanır ve bir G/Ç isteği alındığında açılır . Dönme hızı,
aktarım hızlarıyla ilgilidir. Aktarım hızı , sürücü ile bilgisayar arasındaki veri
akışının hızıdır. Diğer bir performans yönü, konumlandırma süresi veya rastgele
erişim süresi, iki bölümden oluşur: disk kolunu istenen silindire hareket ettirmek
için gerekli süre, arama süresi olarak adlandırılır ve bunun için gerekli süre.
Machine Translated by Google

451
11.1 Yığın Depolama Yapısına Genel Bakış

Şekil 11.2 Kapağı çıkarılmış 3,5 inç HDD.

disk kafasına dönmesi istenen sektör, dönme gecikmesi olarak adlandırılır. Tipik
diskler saniyede onlarca ila yüzlerce megabayt veri aktarabilir ve arama süreleri ve
birkaç milisaniyelik dönme gecikmeleri vardır. Sürücü denetleyicisinde DRAM
arabelleklerine sahip olarak performansı artırırlar .
Disk kafası, hava veya helyum gibi başka bir gazdan oluşan son derece ince bir
yastık (mikron olarak ölçülür) üzerinde uçar ve kafanın disk yüzeyiyle temas etme
tehlikesi vardır. Disk plakaları ince bir koruyucu tabaka ile kaplansa da, kafa bazen
manyetik yüzeye zarar verir. Bu kazaya kafa çarpması denir . Bir kafa çarpması
normalde tamir edilemez; diskin tamamı değiştirilmelidir ve diskteki veriler başka bir
depolama birimine yedeklenmedikçe veya RAID korumalı değilse kaybolur. (RAID ,
Bölüm 11.8'de tartışılmaktadır.)

HDD'ler kapalı birimlerdir ve HDD'leri tutan bazı kasalar , sistemi veya depolama
kasasını kapatmadan bunların çıkarılmasına izin verir. Bu, bir sistemin belirli bir
zamanda bağlanabileceğinden daha fazla depolamaya ihtiyacı olduğunda veya
bozuk bir sürücüyü çalışan bir sürücüyle değiştirmek gerektiğinde yararlıdır. CD'ler,
DVD'ler ve Blu-ray diskler dahil olmak üzere diğer depolama ortamı türleri de çıkarılabilir .

DİSK AKTARIM ORANLARI

Bilgi işlemin birçok yönüyle olduğu gibi, diskler için yayınlanan performans numaraları,
gerçek dünyadaki performans sayılarıyla aynı değildir. Örneğin , belirtilen transfer oranları
her zaman efektif transfer oranlarından daha yüksektir . Aktarım hızı, disk kafası tarafından
manyetik ortamdan bitlerin okunabileceği hız olabilir, ancak bu, blokların işletim sistemine
teslim edilme oranından farklıdır.
Machine Translated by Google

452 Bölüm 11 Yığın Depolama Yapısı

11.1.2 Kalıcı Bellek Aygıtları

Kalıcı bellek (NVM) cihazlarının önemi artıyor. Basitçe tarif edildiğinde, NVM cihazları
mekanik olmaktan çok elektriklidir. En yaygın olarak, böyle bir cihaz, verileri
depolamak için kullanılan bir denetleyici ve flash NAND kalıp yarı iletken
yongalarından oluşur. İçeriğini kaybetmemesi için pil destekli DRAM gibi başka
NVM teknolojileri ve 3D XPoint gibi diğer yarı iletken teknolojileri vardır, ancak
bunlar çok daha az yaygındır ve bu nedenle bu kitapta tartışılmamaktadır.

11.1.2.1 Kalıcı Bellek Aygıtlarına Genel Bakış Flash bellek

tabanlı NVM , disk sürücüsü benzeri bir kapta sıklıkla kullanılır ve bu durumda buna
katı hal diski (SSD) denir (Şekil 11.3). Diğer durumlarda, bir USB sürücüsü (parmak
sürücü veya flash sürücü olarak da bilinir) veya bir DRAM çubuğu şeklini alır. Ayrıca
akıllı telefonlar gibi cihazlarda ana depolama olarak anakartlara yüzeye monte edilir.
Tüm formlarda, aynı şekilde hareket eder ve tedavi edilebilir. NVM cihazlarıyla ilgili
tartışmamız bu teknolojiye odaklanıyor.
NVM cihazları, hareketli parçaları olmadığı için HDD'lerden daha güvenilir olabilir ve
arama süresi veya dönme gecikmesi olmadığı için daha hızlı olabilir.
Ayrıca daha az güç tüketirler. Olumsuz tarafı, geleneksel sabit disklerden megabayt
başına daha pahalıdırlar ve daha büyük sabit disklerden daha az kapasiteye
sahiptirler. Ancak zamanla, NVM cihazlarının kapasitesi HDD kapasitesinden daha
hızlı arttı ve fiyatları daha hızlı düştü, bu nedenle kullanımları çarpıcı biçimde artıyor.
Aslında, SSD'ler ve benzeri cihazlar artık bazı dizüstü bilgisayarlarda onları daha
küçük, daha hızlı ve daha enerji verimli hale getirmek için kullanılmaktadır.

NVM aygıtları sabit disk sürücülerinden çok daha hızlı olabildiğinden, standart
veri yolu arabirimleri iş hacminde büyük bir sınırlamaya neden olabilir . Bazı NVM
cihazları, doğrudan sistem veri yoluna ( örneğin PCIe ) bağlanmak üzere
tasarlanmıştır. Bu teknoloji, bilgisayar tasarımının diğer geleneksel yönlerini de değiştiriyor.

Şekil 11.3 3,5 inç SSD devre kartı.


Machine Translated by Google

11.1 Yığın Depolama Yapısına Genel Bakış 453

Bazı sistemler bunu disk sürücülerinin doğrudan yerine geçmek için kullanırken, diğerleri
performansı optimize etmek için verileri manyetik diskler, NVM ve ana bellek arasında taşıyan
yeni bir önbellek katmanı olarak kullanır.
NAND yarı iletkenleri, kendi depolama ve güvenilirlik zorluklarını ortaya koyan bazı
özelliklere sahiptir. Örneğin, bir "sayfa" artışıyla (bir sektöre benzer) okunabilir ve yazılabilirler,
ancak verilerin üzerine yazılamaz - bunun yerine, önce NAND hücrelerinin silinmesi gerekir.
Birkaç sayfa boyutunda bir "blok" artışında meydana gelen silme, okumadan (en hızlı işlem) veya
yazmadan (okumaktan daha yavaş, ancak silmekten çok daha hızlı) çok daha fazla zaman alır.
Bu duruma yardımcı olan şey, NVM flash cihazlarının her kalıpta birçok veri yolu bulunan birçok
kalıptan oluşmasıdır, bu nedenle işlemler paralel olarak gerçekleşebilir (her biri bir veri yolu
kullanır). NAND yarı iletkenleri ayrıca her silme döngüsünde bozulur ve yaklaşık 100.000 program
silme döngüsünden sonra (belirli sayı ortama bağlı olarak değişir), hücreler artık verileri
tutmaz. Yazma aşınması ve hareketli parça olmaması nedeniyle NAND NVM'nin kullanım ömrü
yıl olarak değil, Günlük Sürücü Yazma Sayısı (DWPD) ile ölçülür.

Bu ölçü, sürücü arızalanmadan önce sürücü kapasitesinin günde kaç kez yazılabileceğidir.
Örneğin, 5 DWPD derecesine sahip 1 TB NAND sürücüsüne , garanti süresi boyunca hatasız
olarak günde 5 TB yazılması beklenir .

Bu sınırlamalar, birkaç iyileştirme algoritmasına yol açmıştır. Neyse ki, bunlar genellikle
NVM aygıt denetleyicisinde uygulanır ve işletim sistemiyle ilgili değildir. İşletim sistemi
mantıksal blokları okur ve yazar ve cihaz bunun nasıl yapıldığını yönetir. (Mantıksal bloklar
Bölüm 11.1.5'te daha ayrıntılı olarak tartışılmaktadır.) Bununla birlikte, NVM cihazlarının
çalışma algoritmalarına dayalı performans varyasyonları vardır, bu nedenle kontrolörün ne
yaptığına dair kısa bir tartışma garanti edilir.

11.1.2.2 NAND Flash Denetleyici Algoritmaları

NAND yarı iletkenlerinin üzerine yazıldıktan sonra yazılamadığından, genellikle geçersiz


veriler içeren sayfalar vardır. Bir kez yazılan ve daha sonra tekrar yazılan bir dosya sistemi
bloğunu düşünün. Bu arada herhangi bir silme işlemi olmadıysa, ilk yazılan sayfada artık
geçersiz olan eski veriler ve ikinci sayfada bloğun güncel, iyi versiyonu bulunur. Geçerli ve
geçersiz sayfaları içeren bir NAND bloğu Şekil 11.4'te gösterilmiştir. Hangi mantıksal
blokların geçerli veriler içerdiğini izlemek için denetleyici bir flas çeviri katmanı (FTL) tutar.
Bu tablo, hangi fiziksel sayfaların şu anda geçerli mantıksal blokları içerdiğini eşler. Ayrıca

Şekil 11.4 Geçerli ve geçersiz sayfaları olan bir NAND bloğu.


Machine Translated by Google

454 Bölüm 11 Yığın Depolama Yapısı

fiziksel blok durumunu izler - yani hangi bloklar yalnızca geçersiz sayfalar içerir ve
bu nedenle silinebilir.
Şimdi bekleyen bir yazma isteği olan tam bir SSD düşünün. SSD dolu
olduğundan , tüm sayfalar yazılmıştır, ancak geçerli veri içermeyen bir blok olabilir.
Bu durumda, yazma işlemi silme işleminin gerçekleşmesini bekleyebilir ve ardından
yazma işlemi gerçekleşebilir. Ama ya ücretsiz blok yoksa? Tek tek sayfalar geçersiz
veriler içeriyorsa, yine de biraz boşluk olabilir. Bu durumda, çöp toplama meydana
gelebilir - iyi veriler diğer konumlara kopyalanabilir, silinebilecek blokları serbest
bırakabilir ve daha sonra yazmaları alabilir. Ancak, çöp toplama iyi verileri nerede
saklar? Bu sorunu çözmek ve yazma performansını iyileştirmek için NVM cihazı aşırı
provizyon kullanır. Cihaz, her zaman yazılabilecek bir alan olarak birkaç sayfa
(genellikle toplamın yüzde 20'si) olarak ayırır. Çöp toplama veya verilerin eski
sürümlerini geçersiz kılan yazma işlemleri tarafından tamamen geçersiz olan bloklar,
cihaz doluysa veya boş havuza geri döndürülürse silinir ve aşırı sağlama alanına
yerleştirilir.

Aşırı tedarik alanı, aşınma dengelemeye de yardımcı olabilir. Bazı bloklar tekrar
tekrar silinirse, diğerleri silinmezse, sık silinen bloklar diğerlerinden daha hızlı
yıpranır ve tüm cihazın ömrü, tüm blokların aynı anda yıpranmasına göre daha kısa
olur. Denetleyici, verileri daha az silinen bloklara yerleştirmek için çeşitli algoritmalar
kullanarak bundan kaçınmaya çalışır, böylece sonraki silmeler, daha fazla silinen
bloklar yerine bu bloklarda gerçekleşir ve tüm cihaz boyunca aşınmayı dengeler.

Veri koruma açısından, HDD'ler gibi, NVM cihazları, hataları tespit etmek ve mümkünse
düzeltmek için yazma sırasında verilerle birlikte hesaplanan ve saklanan ve verilerle birlikte
okunan hata düzeltme kodları sağlar.
(Hata düzeltme kodları Bölüm 11.5.1'de anlatılmıştır.) Bir sayfada sıklıkla düzeltilebilir
hatalar varsa, sayfa bozuk olarak işaretlenebilir ve sonraki yazmalarda kullanılmayabilir.
Genel olarak, HDD gibi tek bir NVM cihazı, okuma veya yazma isteklerini bozduğu
veya yanıtlayamadığı feci bir arızaya sahip olabilir. Bu durumlarda verilerin
kurtarılabilmesini sağlamak için RAID koruması kullanılır.

11.1.3 Geçici Bellek

Yığın depolama yapısıyla ilgili bir bölümde geçici belleği tartışmak tuhaf görünebilir,
ancak DRAM sıklıkla bir yığın depolama aygıtı olarak kullanıldığı için haklıdır.
Spesifik olarak, RAM sürücüleri ( RAM diskleri de dahil olmak üzere birçok adla bilinir )
ikincil depolama gibi davranır ancak sistemin DRAM'inin bir bölümünü oluşturan ve
onu bir depolama alanıymış gibi sistemin geri kalanına sunan aygıt sürücüleri
tarafından oluşturulur. cihaz. Bu "sürücüler" ham blok aygıtları olarak kullanılabilir,
ancak daha yaygın olarak, standart dosya işlemleri için üzerlerinde dosya sistemleri
oluşturulur.
Bilgisayarlarda zaten ara belleğe alma ve önbelleğe alma vardır, bu nedenle
geçici veri depolama için DRAM'in başka bir kullanımının amacı nedir? Sonuçta,
DRAM geçicidir ve bir RAM sürücüsündeki veriler bir sistem çökmesine, kapanmasına
veya kapanmasına dayanmaz. Önbellekler ve arabellekler, programcı veya işletim
sistemi tarafından tahsis edilirken, RAM sürücüleri, kullanıcının (aynı zamanda programcının)
Machine Translated by Google

455
11.1 Yığın Depolama Yapısına Genel Bakış

MANYETİK BANTLAR

Manyetik bant , erken bir ikincil depolama ortamı olarak kullanıldı. Kalıcı olmasına ve büyük
miktarda veri tutabilmesine rağmen, erişim süresi ana bellek ve sürücülere kıyasla daha
yavaştır. Ayrıca, manyetik teybe rastgele erişim, HDD'lere rastgele erişimden yaklaşık bin kat
daha yavaştır ve SSD'lere rastgele erişimden yaklaşık yüz bin kat daha yavaştır, bu nedenle
bantlar ikincil depolama için pek kullanışlı değildir. Bantlar esas olarak yedekleme, seyrek
olarak kullanılan bilgilerin saklanması ve bir sistemden diğerine bilgi aktarımı için bir araç
olarak kullanılır.

Bir bant bir makarada tutulur ve bir okuma-yazma kafasının üzerinden sarılır veya geri
sarılır. Bir teyp üzerinde doğru noktaya hareket etmek dakikalar alabilir, ancak bir kez
yerleştirildiğinde, teyp sürücüleri HDD'lerle karşılaştırılabilir hızlarda veri okuyabilir ve yazabilir .
Teyp kapasiteleri, belirli bir teyp sürücüsü türüne bağlı olarak büyük ölçüde değişir ve
mevcut kapasiteler birkaç terabaytı aşar. Bazı teypler, etkin depolamayı iki katından daha
fazla artırabilen yerleşik sıkıştırmaya sahiptir. Bantlar ve sürücüleri genellikle 4, 8 ve 19
milimetre ve 1/4 ve 1/2 inç dahil olmak üzere genişliğe göre sınıflandırılır. Bazıları teknolojiye
göre isimlendirilir, örneğin LTO-6 (Şekil 11.5) ve SDLT.

Şekil 11.5 Teyp kartuşu takılı bir LTO-6 Teyp sürücüsü.

standart dosya işlemlerini kullanarak geçici koruma için bellekteki veriler. Aslında, RAM
sürücüsü işlevi, bu tür sürücülerin tüm büyük işletim sistemlerinde bulunması için
yeterince kullanışlıdır. Linux'ta /dev/ram vardır, macOS'ta diskutil komutu bunları
oluşturur, Windows bunları üçüncü taraf araçlar aracılığıyla alır ve Solaris ve Linux
önyükleme sırasında bir RAM sürücüsü olan “tmpfs” türünde /tmp oluşturur.
RAM sürücüleri, yüksek hızlı geçici depolama alanı olarak kullanışlıdır. NVM cihazları
hızlı olmasına rağmen , DRAM çok daha hızlıdır ve RAM sürücülerine yapılan G/Ç
işlemleri , dosyaları ve içeriklerini oluşturmanın, okumanın, yazmanın ve silmenin en hızlı yoludur.
Birçok program, geçici dosyaları depolamak için RAM sürücüleri kullanır (veya bundan
faydalanabilir) . Örneğin, programlar bir RAM sürücüsünden dosya yazıp okuyarak
verileri kolayca paylaşabilir. Başka bir örnek için, Linux önyükleme sırasında , işletim
sisteminin depolama aygıtlarını anlayan bölümleri yüklenmeden önce sistemin diğer
bölümlerinin bir kök dosya sistemine ve içeriğine erişmesine izin veren geçici bir kök
dosya sistemi (initrd) oluşturur.
Machine Translated by Google

456 Bölüm 11 Yığın Depolama Yapısı

11.1.4 İkincil Depolama Bağlantı Yöntemleri

İkincil bir depolama aygıtı, bir bilgisayara sistem veri yolu veya bir G/Ç veri yolu ile bağlanır .
Gelişmiş teknoloji eki (ATA), seri ATA (SATA), eSATA, seri bağlı SCSI (SAS), evrensel seri veri yolu
(USB) ve fiber kanalı (FC) dahil olmak üzere çeşitli veri yolları mevcuttur . En yaygın bağlantı
yöntemi SATA'dır. NVM cihazları HDD'lerden çok daha hızlı olduğu için endüstri, NVM ekspres
(NVMe) adı verilen NVM cihazları için özel, hızlı bir arayüz oluşturdu .

NVMe , aygıtı doğrudan sistem PCI veri yoluna bağlayarak, diğer bağlantı yöntemlerine
kıyasla verimi artırır ve gecikmeyi azaltır.
Bir veri yolu üzerindeki veri aktarımları, denetleyiciler (veya ana bilgisayar veriyolu
adaptörleri (HBA) adı verilen özel elektronik işlemciler tarafından gerçekleştirilir ). Ana
bilgisayar denetleyicisi , veri yolunun bilgisayar ucundaki denetleyicidir. Her depolama
aygıtına bir aygıt denetleyicisi yerleştirilmiştir. Bir yığın depolama G/Ç işlemi gerçekleştirmek
için bilgisayar , Bölüm 12.2.1'de açıklandığı gibi , tipik olarak bellek eşlemeli G/Ç bağlantı
noktalarını kullanarak ana bilgisayar denetleyicisine bir komut yerleştirir. Ana bilgisayar
denetleyicisi daha sonra komutları mesajlar yoluyla aygıt denetleyicisine gönderir ve
denetleyici komutu gerçekleştirmek için sürücü donanımını çalıştırır. Aygıt denetleyicilerinde
genellikle yerleşik bir önbellek bulunur. Sürücüdeki veri aktarımı, önbellek ve depolama
ortamı arasında gerçekleşir ve ana bilgisayara yüksek elektronik hızlarda veri aktarımı,
DMA yoluyla önbellek ana bilgisayarı DRAM'ı arasında gerçekleşir.

11.1.5 Adres Eşleme

Depolama aygıtları , mantıksal bloğun en küçük aktarım birimi olduğu büyük tek boyutlu
mantıksal blok dizileri olarak adreslenir. Her mantıksal blok, bir fiziksel sektör veya yarı
iletken sayfayla eşlenir. Tek boyutlu mantıksal blok dizisi, aygıtın sektörlerine veya
sayfalarına eşlenir. Sektör 0, örneğin , bir HDD'deki en dış silindirdeki ilk parçanın ilk
sektörü olabilir . Haritalama, sırayla bu iz boyunca, sonra o silindir üzerindeki diğer izler
boyunca ve daha sonra silindirlerin geri kalanı boyunca, en dıştan en içe doğru ilerler.
NVM için eşleme, çip, blok ve sayfanın bir demetinden (sonlu sıralı liste) bir dizi mantıksal
bloka kadardır. Mantıksal blok adresi (LBA) , algoritmalar için sektör, silindir, başlık demeti
veya çip, blok, sayfa demetinden daha kolaydır.

Bu eşlemeyi bir HDD'de kullanarak, en azından teoride, mantıksal bir blok numarasını
bir silindir numarasından, o silindir içindeki bir parça numarasından ve bu yoldaki bir
sektör numarasından oluşan eski tarz bir disk adresine dönüştürebiliriz. Pratikte bu çeviriyi
yapmak üç nedenden dolayı zordur.
İlk olarak, çoğu sürücüde bazı kusurlu sektörler bulunur, ancak eşleme, sürücünün
başka yerlerindeki yedek sektörleri değiştirerek bunu gizler. Mantıksal blok adresi sıralı
kalır, ancak fiziksel sektör konumu değişir. İkincisi, iz başına sektör sayısı bazı sürücülerde
sabit değildir. Üçüncüsü, disk üreticileri LBA'yı fiziksel adres eşlemesini dahili olarak
yönetir, bu nedenle mevcut sürücülerde LBA ve fiziksel sektörler arasında çok az ilişki
vardır . Bu fiziksel adres değişkenlerine rağmen, HDD'lerle ilgilenen algoritmalar,
mantıksal adreslerin nispeten fiziksel adreslerle ilişkili olduğunu varsayma eğilimindedir.
Yani, artan mantıksal adresler, artan fiziksel adres anlamına gelme eğilimindedir.

İkinci nedene daha yakından bakalım. Sabit doğrusal hız (CLV) kullanan ortamlarda,
iz başına bit yoğunluğu tekdüzedir. Bir iz diskin merkezinden ne kadar uzaksa, uzunluğu
o kadar büyük olur, dolayısıyla o kadar çok sektör olabilir.
Machine Translated by Google

11.2 HDD Zamanlama 457

tutmak. Dış bölgelerden iç bölgelere doğru hareket ettikçe iz başına sektör sayısı
azalır. En dıştaki bölgedeki izler, en içteki bölgedeki izlerden tipik olarak yüzde 40
daha fazla sektör tutar. Sürücü, kafanın altında hareket eden aynı veri hızını korumak
için kafa dıştan iç raylara hareket ettikçe dönüş hızını arttırır. Bu yöntem CD-ROM
ve DVD-ROM sürücülerinde kullanılır. Alternatif olarak, disk dönüş hızı sabit kalabilir;
bu durumda, veri hızını sabit (ve verilerin sürücüde nerede olursa olsun performansı
nispeten aynı) tutmak için bitlerin yoğunluğu iç izlerden dış izlere doğru azalır. Bu
yöntem sabit disklerde kullanılır ve sabit açısal hız (CAV) olarak bilinir.

Disk teknolojisi geliştikçe iz başına sektör sayısı artmaktadır ve bir diskin dış
bölgesi genellikle iz başına birkaç yüz sektöre sahiptir. Benzer şekilde, disk başına
silindir sayısı da artmaktadır; büyük disklerde on binlerce silindir bulunur.

Bir işletim sistemleri metninde ele alınması makul olandan daha fazla depolama
aygıtı türü olduğunu unutmayın. Örneğin, ana akım HDD'lerden daha yüksek
yoğunluğa ancak daha kötü performansa sahip "shingled manyetik kayıt" sabit
diskleri vardır (bkz. http://www.tomsitpro.com/articles/shingled-magnetic-recoding-
smr-101-basics,2- 933.html). Ayrıca NVM ve HDD teknolojisini içeren kombinasyon
cihazları veya NVM ve HDD cihazlarını HDD'den daha hızlı ancak NVM'den daha
düşük maliyetli bir depolama biriminde birleştirebilen birim yöneticileri (bkz. Bölüm
11.5) vardır . Bu aygıtlar, daha yaygın aygıtlardan farklı özelliklere sahiptir ve
performansı en üst düzeye çıkarmak için farklı önbelleğe alma ve zamanlama
algoritmalarına ihtiyaç duyabilir.

11.2 HDD Zamanlama


İşletim sisteminin sorumluluklarından biri de donanımı verimli kullanmaktır. HDD'ler için
bu sorumluluğun karşılanması, erişim süresinin en aza indirilmesini ve veri aktarım bant
genişliğinin en üst düzeye çıkarılmasını gerektirir.
Plaka kullanan HDD'ler ve diğer mekanik depolama aygıtları için erişim süresinin
Bölüm 11.1'de belirtildiği gibi iki ana bileşeni vardır. Arama süresi, cihaz kolunun
kafaları istenen sektörü içeren silindire hareket ettirme süresidir ve dönme
gecikmesi, plakanın istenen sektörü kafaya döndürmesi için ek süredir. Cihaz bant
genişliği , aktarılan toplam bayt sayısının, ilk hizmet talebi ile son aktarımın
tamamlanması arasındaki toplam süreye bölümüdür. Depolama G/Ç isteklerinin
hizmet verildiği sırayı yöneterek hem erişim süresini hem de bant genişliğini
iyileştirebiliriz .

Bir işlem sürücüye veya sürücüden G/Ç'ye ihtiyaç duyduğunda , bir sistem çağrısı yapar
işletim sistemine. İstek, birkaç bilgi parçasını belirtir:

• Bu işlemin giriş mi çıkış mı olduğu • Üzerinde


çalışılacak dosyayı gösteren açık dosya tanıtıcısı • Aktarım
için bellek adresi nedir
• Aktarılacak veri miktarı
Machine Translated by Google

458 Bölüm 11 Yığın Depolama Yapısı

İstenen sürücü ve kontrolör mevcutsa, talep anında servise alınabilir. Sürücü veya
denetleyici meşgulse, yeni hizmet talepleri, o sürücü için bekleyen istekler kuyruğuna
yerleştirilir. Birçok işlemi olan bir çok programlı ming sistemi için, cihaz kuyruğunda çoğu
zaman bekleyen birkaç istek olabilir.

Baş aramalardan kaçınarak performansını optimize edebilen bir aygıta yönelik bir istek
kuyruğunun varlığı, aygıt sürücülerine sıra sıralaması yoluyla performansı artırma şansı
verir.
Geçmişte, HDD arabirimleri, ana bilgisayarın hangi parçayı ve hangi başlığı
kullanacağını belirlemesini gerektiriyordu ve disk zamanlama algoritmaları için çok çaba harcanıyordu.
Yüzyılın başından daha yeni sürücüler, yalnızca bu kontrolleri ana bilgisayara ifşa etmekle
kalmaz, aynı zamanda LBA'yı sürücü kontrolü altındaki fiziksel adreslerle eşler. Disk
zamanlamanın mevcut hedefleri arasında adalet, zamanlılık ve sürücüler sıralı G/Ç ile en iyi
performansı gösterdiğinden, sırayla görünen okumaları veya yazmaları gruplama gibi
optimizasyonlar yer alır . Bu nedenle, bazı zamanlama çabası hala yararlıdır. Birkaç disk
zamanlama algoritmasından herhangi biri kullanılabilir ve bunları daha sonra tartışacağız.
Modern sürücülerde kafa konumu ve fiziksel blok/silindir konumlarının mutlak bilgisinin
genellikle mümkün olmadığını unutmayın. Ancak kabaca bir tahmin olarak, algoritmalar
artan LBA'ların artan fiziksel adresler anlamına geldiğini ve birbirine yakın LBA'ların fiziksel
blok yakınlığına eşit olduğunu varsayabilir .

11.2.1 FCFS Planlaması


Disk programlamanın en basit biçimi, elbette, ilk gelen ilk hizmet alır (FCFS) algoritmasıdır
(veya FIFO). Bu algoritma özünde adildir, ancak genellikle en hızlı hizmeti sağlamaz.
Örneğin, silindirlerdeki bloklara G/Ç isteklerini içeren bir disk kuyruğunu düşünün.

98, 183, 37, 122, 14, 124, 65, 67,

bu sırayla. Disk kafası başlangıçta silindir 53'teyse, toplam 640 silindir kafa hareketi için önce
53'ten 98'e, ardından 183, 37, 122, 14, 124, 65'e ve son olarak 67'ye hareket edecektir. Bu
çizelge Şekil 11.6'da gösterilmiştir.
122'den 14'e ve ardından 124'e vahşi salınım, bu programdaki sorunu göstermektedir.
37 ve 14 numaralı silindirlere yönelik taleplere birlikte, 122 ve 124'e yönelik taleplerden önce
veya sonra hizmet verilebilirse, toplam kafa hareketi önemli ölçüde azaltılabilir ve böylece
performans geliştirilebilir.

11.2.2 TARAMA Planlaması


SCAN algoritmasında, disk kolu diskin bir ucundan başlar ve diğer ucuna doğru hareket
eder, her silindire ulaştığında, diskin diğer ucuna ulaşana kadar taleplere hizmet eder.
Diğer uçta ise kafa hareketinin yönü tersine çevrilir ve servise devam edilir. Kafa sürekli
olarak diski ileri geri tarar. SCAN algoritmasına bazen asansör algoritması denir, çünkü disk
kolu tıpkı bir binadaki asansör gibi davranır, önce tüm taleplere hizmet verir ve sonra diğer
yoldan servis taleplerine geri döner.

Örneklemek için örneğimize dönelim. 98, 183, 37, 122, 14, 124, 65 ve 67 silindirlerindeki
istekleri programlamak için SCAN uygulamadan önce şunu bilmemiz gerekir:
Machine Translated by Google

11.2 HDD Zamanlama 459

kuyruk = 98, 183, 37, 122, 14, 124, 65, 67


kafa 53'te başlar
0 14 37 536567 98 122124 183 199

Şekil 11.6 FCFS disk zamanlaması.

kafanın mevcut konumuna ek olarak kafa hareketinin yönü.


Disk kolunun 0'a doğru hareket ettiğini ve ilk kafa konumunun tekrar 53
olduğunu varsayarsak, kafa daha sonra 37'ye ve ardından 14'e hizmet edecektir.
Silindir 0'da, kol tersine dönecek ve diskin diğer ucuna doğru hareket ederek,
diske bakım yapacaktır. 65, 67, 98, 122, 124 ve 183'te istekler (Şekil 11.7). Başın
hemen önündeki kuyruğa bir istek gelirse, neredeyse anında hizmet verilir;
kafanın hemen arkasından gelen bir istek, kol diskin sonuna gelene, yönü
tersine çevirene ve geri gelene kadar beklemek zorunda kalacaktır.
Silindir taleplerinin düzgün bir şekilde dağıldığını varsayarak, kafa bir uca
ulaştığında ve yönü tersine çevirdiğinde taleplerin yoğunluğunu göz önünde
bulundurun. Bu noktada, bu silindirlerin bakımı yakın zamanda yapıldığından,
nispeten az sayıda istek hemen kafanın önüne geliyor. En yoğun istek
yoğunluğu diskin diğer ucundadır. Bu istekler de en uzun süre bekledi, öyleyse
neden önce oraya gitmiyorsunuz? Bir sonraki algoritmanın fikri budur.

kuyruk = 98, 183, 37, 122, 14, 124, 65, 67


kafa 53'te başlar
0 14 37 536567 98 122124 183199

Şekil 11.7 SCAN disk zamanlaması.


Machine Translated by Google

460 Bölüm 11 Yığın Depolama Yapısı

11.2.3 C-SCAN Planlaması

Dairesel SCAN (C-SCAN) zamanlaması , daha düzgün bir bekleme süresi sağlamak için
tasarlanmış bir SCAN çeşididir . SCAN gibi , C-SCAN da kafayı diskin bir ucundan diğer
ucuna hareket ettirerek yol boyunca taleplere hizmet eder. Ancak kafa diğer uca
ulaştığında, dönüş yolculuğunda herhangi bir istekte bulunmadan hemen diskin başına
döner.
Örneklemek için örneğimize dönelim. 98, 183, 37, 122, 14, 124, 65 ve 67
silindirlerindeki istekleri programlamak için C-SCAN uygulamadan önce , isteklerin
programlandığı kafa hareketinin yönünü bilmemiz gerekir.
İsteklerin, disk kolu 0'dan 199'a hareket ederken programlandığı ve ilk kafa pozisyonunun
tekrar 53 olduğu varsayıldığında, istek Şekil 11.8'de gösterildiği gibi sunulacaktır. C-
SCAN çizelgeleme algoritması , esasen silindirleri, son silindirden ilk silindire kadar saran
dairesel bir liste olarak ele alır.

11.2.4 Disk Zamanlama Algoritmasının Seçimi

Nadiren kullanıldıkları için bu kapsama dahil olmayan birçok disk zamanlama algoritması vardır.
Ancak işletim sistemi tasarımcıları hangisinin uygulanacağına nasıl karar verir ve dağıtımcılar
en iyi kullanmayı nasıl seçer? Herhangi bir özel istek listesi için, optimal bir geri alma sırası
tanımlayabiliriz, ancak optimal bir program bulmak için gereken hesaplama, SCAN'a göre
tasarrufları haklı çıkarmayabilir .
Bununla birlikte, herhangi bir zamanlama algoritmasında performans, büyük ölçüde
isteklerin sayısına ve türlerine bağlıdır. Örneğin, kuyruğun genellikle yalnızca bir
bekleyen isteği olduğunu varsayalım. Ardından, tüm zamanlama algoritmaları aynı
şekilde davranır, çünkü disk kafasını nereye taşıyacakları konusunda yalnızca bir
seçeneğe sahiptirler: hepsi FCFS zamanlaması gibi davranır.
SCAN ve C-SCAN , diske ağır yük yerleştiren sistemler için daha iyi performans
gösterir, çünkü aç kalma sorununa neden olma olasılıkları daha düşüktür. Yine de,
Linux'u son tarih zamanlayıcısını oluşturmaya iten açlık olabilir . Bu zamanlayıcı, ayrı
okuma ve yazma kuyrukları tutar ve işlemlerin okuma sırasında yazmadan daha büyük
olasılıkla bloke olması nedeniyle okuma önceliği verir. sıralar

kuyruk = 98, 183, 37, 122, 14, 124, 65, 67


kafa 53'te başlar
0 14 37 53 65 67 98 122124 183199

Şekil 11.8 C-SCAN disk zamanlaması.


Machine Translated by Google

11.3 NVM Planlaması 461

LBA sırasına göre sıralanır , esasen C-SCAN uygulanır. Tüm G/Ç istekleri, bu LBA
siparişinde toplu olarak gönderilir. Son teslim tarihi dört sıra tutar: biri LBA'ya ve
diğeri FCFS'ye göre sıralanmış iki okuma ve iki yazma . Her gruptan sonra, FCFS
kuyruklarında yapılandırılmış bir yaştan daha eski istekler olup olmadığını kontrol
eder (varsayılan olarak 500 ms). Bu durumda , bir sonraki G/Ç grubu için bu isteği
içeren LBA kuyruğu (okuma veya yazma) seçilir.
Son G/Ç zamanlayıcısı, Linux RedHat 7 dağıtımında varsayılandır, ancak RHEL 7
ayrıca iki tane daha içerir. NOOP , NVM cihazları gibi hızlı depolama kullanan CPU'ya
bağlı sistemler için tercih edilir ve Tamamen Adil Kuyruk zamanlayıcısı (CFQ) SATA
sürücüleri için varsayılandır . CFQ üç sıra tutar (bunları LBA düzeninde sıralanmış
halde tutmak için eklemeli sıralama ile ): gerçek zamanlı, en iyi çaba (varsayılan) ve
boşta. Her birinin diğerlerine göre özel önceliği vardır, bu sırayla, açlıktan ölme
olasılığı vardır. Bir işlemin yakında daha fazla G/Ç isteği yayınlayıp yayınlamayacağını
tahmin ederek geçmiş verileri kullanır. Bunu belirlerse, sıradaki diğer istekleri yok
sayarak yeni G/Ç'yi beklerken boşta kalır. Bu, işlem başına depolama G/Ç isteklerinin
referans konumunu varsayarak arama süresini en aza indirmek içindir . Bu
programlayıcıların ayrıntıları https://access.redhat.com/site/documentation/en-US/
Red Hat Enterprise Linux/7/html/Performance Tuning Guide/index.html adresinde bulunabilir .

11.3 NVM Planlaması


Az önce tartışılan disk zamanlama algoritmaları, HDD'ler gibi mekanik tabla tabanlı
depolama için geçerlidir . Öncelikle disk kafası hareketi miktarını en aza indirmeye
odaklanırlar. NVM aygıtları hareketli disk kafaları içermez ve genellikle basit bir FCFS
ilkesi kullanır. Örneğin, Linux NOOP planlayıcısı bir FCFS ilkesi kullanır, ancak bunu
bitişik istekleri birleştirmek için değiştirir. NVM cihazlarının gözlemlenen davranışı,
servis okumaları için gereken sürenin tek tip olduğunu, ancak flash belleğin
özelliklerinden dolayı yazma servis süresinin tek tip olmadığını gösterir. Bazı SSD
zamanlayıcıları bu özellikten yararlandı ve yalnızca bitişik yazma isteklerini birleştirdi
ve tüm okuma isteklerine FCFS sırasına göre hizmet verdi.
Gördüğümüz gibi, I/O sıralı veya rastgele gerçekleşebilir. Okunacak veya
yazılacak veriler okuma/yazma kafasının yakınında olduğundan, HDD ve bant gibi
mekanik cihazlar için sıralı erişim en uygunudur . Saniyedeki giriş/çıkış işlemlerinde
(IOPS) ölçülen rastgele erişimli G/Ç, HDD disk kafası hareketine neden olur . Doğal
olarak, rastgele erişimli G/Ç , NVM'de çok daha hızlıdır . Bir HDD yüzlerce IOPS
üretebilirken, bir SSD yüz binlerce IOPS üretebilir.

NVM cihazları, HDD kafa aramalarının en aza indirildiği ve ortama veri okuma
ve yazmanın vurgulandığı ham sıralı geçiş için çok daha az avantaj sunar. Bu
durumlarda, okumalar için, iki tür cihazın performansı, NVM cihazları için eşdeğerden
bir büyüklük sırasına kadar değişebilir . NVM'ye yazmak okumaktan daha yavaştır, bu
da avantajı azaltır. Ayrıca, HDD'ler için yazma performansı cihazın ömrü boyunca
tutarlıyken, NVM cihazları için yazma performansı, cihazın ne kadar dolu olduğuna
(çöp toplama ve aşırı provizyon ihtiyacını hatırlayın) ve ne kadar "yıprandığına" bağlı
olarak değişir. Birçok silme döngüsü nedeniyle ömrünün sonuna yaklaşan bir NVM
cihazı, genellikle yeni bir cihazdan çok daha kötü performansa sahiptir.
Machine Translated by Google

462 Bölüm 11 Yığın Depolama Yapısı

NVM cihazlarının zaman içinde ömrünü ve performansını iyileştirmenin bir yolu,


dosyalar silindiğinde dosya sisteminin cihaza bilgi vermesini sağlamaktır, böylece
cihaz bu dosyaların depolandığı blokları silebilir. Bu yaklaşım Bölüm 14.5.6'da daha
ayrıntılı olarak tartışılmaktadır.
Çöp toplamanın performans üzerindeki etkisine daha yakından bakalım.
Rastgele okuma ve yazma yükü altında bir NVM cihazı düşünün . Tüm blokların
yazıldığını, ancak boş alan olduğunu varsayın. Geçersiz verilerin kapladığı alanı geri
kazanmak için çöp toplama işlemi gerçekleştirilmelidir. Bu, bir yazma işleminin bir
veya daha fazla sayfanın okunmasına, bu sayfalardaki iyi verilerin aşırı sağlama
alanına yazılmasına, tümüyle geçersiz veri bloğunun silinmesine ve bu bloğun aşırı
sağlama alanına yerleştirilmesine neden olabileceği anlamına gelir. Özetle, bir yazma
isteği sonunda bir sayfanın yazılmasına (veriler), bir veya daha fazla sayfanın
okunmasına (çöp toplama yoluyla) ve bir veya daha fazla sayfanın yazılmasına (çöpten
toplanan bloklardan iyi verilerin) neden olur. G/Ç isteklerinin uygulamalar tarafından
değil, çöp toplama ve alan yönetimi yapan NVM cihazı tarafından oluşturulmasına
yazma amplificatio denir ve cihazın yazma performansını büyük ölçüde etkileyebilir.
En kötü durumda, her yazma isteğiyle birlikte birkaç ekstra G/Ç tetiklenir.

11.4 Hata Tespiti ve Düzeltme

Hata algılama ve düzeltme, bellek, ağ oluşturma ve depolama dahil olmak üzere


birçok bilgi işlem alanı için temeldir. Hata algılama , bir sorunun oluşup oluşmadığını
belirler - örneğin, DRAM'deki bir bit, 0'dan 1'e kendiliğinden değişti, iletim sırasında
bir ağ paketinin içeriği değişti veya yazıldığı ve okunduğu zaman arasında
değişen bir veri bloğu .
Sistem, sorunu algılayarak, hata yayılmadan önce bir işlemi durdurabilir, hatayı
kullanıcıya veya yöneticiye bildirebilir veya bozulmaya başlayan veya zaten arızalı olan
bir cihaz konusunda uyarabilir.
Bellek sistemleri, eşlik bitlerini kullanarak uzun süredir belirli hataları tespit
etmiştir. Bu senaryoda, bir bellek sistemindeki her bayt, 1'e ayarlanmış bayttaki bit
sayısının çift (eşlik = 0) veya tek (eşlik = 1) olup olmadığını kaydeden, kendisiyle ilişkili
bir eşlik bitine sahiptir. Bayttaki bitlerden biri zarar görürse (ya 1 0 olur veya 0 1 olur),
baytın paritesi değişir ve bu nedenle depolanan parite ile eşleşmez. Benzer şekilde,
depolanan eşlik biti zarar görmüşse, hesaplanan eşlikle eşleşmez. Böylece, tüm tek
bitlik hatalar bellek sistemi tarafından algılanır. Ancak çift bitlik bir hata tespit
edilemeyebilir. Paritenin, bitlerin bir XOR'u ("özel VEYA" için) gerçekleştirilerek kolayca
hesaplanabileceğini unutmayın . Ayrıca, her bir bellek baytı için, pariteyi depolamak
için artık fazladan bir belleğe ihtiyacımız olduğunu unutmayın.

Eşlik, sabit uzunluktaki sözcüklerdeki değerleri hesaplamak, depolamak ve


karşılaştırmak için modüler aritmetik kullanan bir sağlama toplamı biçimidir . Ağ
oluşturmada yaygın olan başka bir hata algılama yöntemi, çoklu bit hatalarını tespit
etmek için bir karma işlevi kullanan döngüsel artıklık denetimidir (CRC'ler) . .

Hata düzeltme kodu ( ECC) yalnızca sorunu algılamakla kalmaz, aynı zamanda
düzeltir. Düzeltme, algoritmalar ve ekstra depolama miktarları kullanılarak yapılır.
Kodlar, ne kadar ekstra depolama alanına ihtiyaç duyduklarına ve kaç tane hatayı
düzeltebileceklerine bağlı olarak değişir. Örneğin, disk sürücüleri sektör başına ECC kullanır ve
Machine Translated by Google

11.5 Depolama Aygıtı Yönetimi 463

sayfa başına flash sürücüler ECC. Normal G/Ç sırasında denetleyici bir sektör/sayfa
veri yazdığında , ECC , yazılan verilerdeki tüm baytlardan hesaplanan bir değerle
yazılır. Sektör/sayfa okunduğunda, ECC yeniden hesaplanır ve saklanan değerle
karşılaştırılır. Depolanan ve hesaplanan sayılar farklıysa, bu uyumsuzluk verilerin
bozulduğunu ve depolama ortamının bozuk olabileceğini gösterir (Bölüm 11.5.3).
ECC hata düzeltiyor çünkü sadece birkaç bit veri bozulmuşsa, denetleyicinin hangi
bitlerin değiştiğini belirlemesini ve doğru değerlerinin ne olması gerektiğini
hesaplamasını sağlamak için yeterli bilgi içeriyor . Daha sonra kurtarılabilir bir
yazılım hatası bildirir. Çok fazla değişiklik meydana gelirse ve ECC hatayı düzeltemezse,
düzeltilemez bir sabit hata sinyali verilir. Denetleyici, bir sektör veya sayfa
okunduğunda veya yazıldığında ECC işlemini otomatik olarak yapar .

Hata algılama ve düzeltme, sıklıkla tüketici ürünleri ile kurumsal ürünler


arasındaki farklardır. ECC , örneğin DRAM hata düzeltmesi ve veri yolu koruması için
bazı sistemlerde kullanılır .

11.5 Depolama Aygıtı Yönetimi

İşletim sistemi, depolama aygıtı yönetiminin diğer bazı yönlerinden de sorumludur.


Burada, sürücü başlatma, sürücüden önyükleme ve bozuk blok kurtarmayı tartışıyoruz.

11.5.1 Sürücü Biçimlendirme, Bölümler ve Birimler

Yeni bir depolama aygıtı boş bir levhadır: sadece bir manyetik kayıt malzemesi tabağı
veya bir dizi başlatılmamış yarı iletken depolama hücresidir. Bir depolama aygıtının
verileri depolamadan önce, denetleyicinin okuyabileceği ve yazabileceği sektörlere
bölünmesi gerekir. NVM sayfaları başlatılmalı ve FTL oluşturulmalıdır. Bu işleme
düşük seviyeli biçimlendirme veya fiziksel biçimlendirme denir . Düşük seviyeli
biçimlendirme, cihazı her depolama konumu için özel bir veri yapısıyla doldurur. Bir
sektör veya sayfanın veri yapısı tipik olarak bir başlık, bir veri alanı ve bir fragmandan
oluşur. Başlık ve fragman, sektör/sayfa numarası ve hata algılama veya düzeltme
kodu gibi denetleyici tarafından kullanılan bilgileri içerir.
Çoğu sürücü, üretim sürecinin bir parçası olarak fabrikada düşük düzeyde
biçimlendirilir. Bu biçimlendirme, üreticinin cihazı test etmesine ve mantıksal blok
numaralarından ortamdaki hatasız sektörlere veya sayfalara eşleştirmeyi başlatmasına
olanak tanır. Genellikle 512 bayt ve 4KB gibi birkaç sektör boyutu arasından seçim
yapmak mümkündür. Daha büyük bir sektör boyutuna sahip bir diski biçimlendirmek,
her ize daha az sektör sığabileceği anlamına gelir, ancak aynı zamanda her ize daha
az başlık ve fragman yazılması ve kullanıcı verileri için daha fazla alan olması anlamına gelir.
Bazı işletim sistemleri yalnızca belirli bir sektör boyutunu işleyebilir.
Dosyaları tutmak için bir sürücü kullanmadan önce, işletim sisteminin yine de
kendi veri yapılarını cihaza kaydeder. Bunu üç adımda yapar.
İlk adım, cihazı bir veya daha fazla blok veya sayfa grubuna ayırmaktır. İşletim
sistemi, her bölüme ayrı bir aygıtmış gibi davranabilir. Örneğin, bir bölüm, işletim
sisteminin yürütülebilir kodunun bir kopyasını içeren bir dosya sistemini, bir başkası
takas alanını ve bir diğeri, kullanıcı dosyalarını içeren bir dosya sistemini tutabilir.
Bazı işletim sistemleri ve dosya sistemleri, bir aygıtın tamamı oluşturulduğunda
bölümlemeyi otomatik olarak gerçekleştirir.
Machine Translated by Google

464 Bölüm 11 Yığın Depolama Yapısı

dosya sistemi tarafından yönetilmelidir. Bölüm bilgileri, depolama aygıtında sabit bir konuma
sabit bir biçimde yazılır. Linux'ta fdisk komutu, depolama aygıtlarındaki bölümleri yönetmek için
kullanılır. Aygıt, işletim sistemi tarafından tanındığında, bölüm bilgilerini okur ve işletim sistemi,
bölümler için aygıt girişleri oluşturur ( Linux'ta /dev'de ). Buradan, /etc/fstab gibi bir yapılandırma
dosyası, işletim sistemine bir dosya sistemi içeren her bölümü belirli bir konuma bağlamasını ve
salt okunur gibi bağlama seçeneklerini kullanmasını söyler. Bir dosya sistemini monte etmek,
dosya sistemini sistem ve kullanıcıları tarafından kullanılabilir hale getirmektir.

İkinci adım, hacim oluşturma ve yönetimidir. Bazen, bir dosya sistemi doğrudan bir
bölümün içine yerleştirildiğinde olduğu gibi, bu adım örtüktür.
Bu hacim daha sonra monte edilmeye ve kullanılmaya hazırdır. Diğer zamanlarda, birim
oluşturma ve yönetimi açıktır - örneğin birden fazla bölüm veya cihaz bir RAID seti olarak (bkz.
Bölüm 11.8) cihazlara yayılmış bir veya daha fazla dosya sistemiyle birlikte kullanılacaksa. Linux
birim yöneticisi lvm2 , Linux ve diğer işletim sistemleri için ticari üçüncü taraf araçlar gibi bu
özellikleri sağlayabilir. ZFS , hem birim yönetimi hem de tek bir komut ve özellik kümesine
entegre edilmiş bir dosya sistemi sağlar. ("Birim"in, CD görüntüsü gibi bir dosya sistemi içeren
bir dosya bile dahil olmak üzere, herhangi bir monte edilebilir dosya sistemi anlamına
gelebileceğini unutmayın .)

Üçüncü adım, mantıksal biçimlendirme veya bir dosya sisteminin oluşturulmasıdır. Bu


adımda, işletim sistemi ilk dosya sistemi veri yapılarını cihazda depolar. Bu veri yapıları, boş ve
tahsis edilmiş alan haritalarını ve bir ilk boş dizini içerebilir.

Bölüm bilgileri, bir bölümün önyüklenebilir bir dosya sistemi (işletim sistemini içeren) içerip
içermediğini de gösterir. Önyükleme için etiketlenen bölüm, dosya sisteminin kökünü oluşturmak
için kullanılır. Monte edildikten sonra, diğer tüm cihazlar ve bunların bölümleri için cihaz
bağlantıları oluşturulabilir. Genel olarak, bir bilgisayarın "dosya sistemi" tüm bağlı birimlerden
oluşur. Windows'ta bunlar ayrı ayrı bir harf (C:, D:, E:) ile adlandırılır. Linux gibi diğer sistemlerde,
önyükleme sırasında önyükleme dosya sistemi monte edilir ve diğer dosya sistemleri bu ağaç
yapısı içinde monte edilebilir (Bölüm 13.3'te tartışıldığı gibi). Windows'ta, dosya sistemi arayüzü,
belirli bir cihazın ne zaman kullanıldığını netleştirirken, Linux'ta tek bir dosya erişimi, istenen
dosya sisteminde (bir birim içinde) istenen dosyaya erişilmeden önce birçok cihazı geçebilir. Şekil
11.9, üç birimi (C:, E: ve F:) gösteren Windows 7 Disk Yönetimi aracını gösterir. E: ve F: öğelerinin
her birinin "Disk 1" aygıtının bir bölümünde olduğunu ve bu aygıtta daha fazla bölüm için
ayrılmamış alan olduğunu (muhtemelen dosya sistemlerini içeren) unutmayın.

Verimliliği artırmak için çoğu dosya sistemi blokları, sıklıkla kümeler olarak adlandırılan
daha büyük parçalar halinde gruplandırır. Cihaz G/Ç'si bloklar aracılığıyla yapılır, ancak dosya
sistemi G/ Ç'si kümeler aracılığıyla yapılır ve G/Ç'nin daha fazla sıralı erişime ve daha az rastgele
erişim özelliğine sahip olmasını etkin bir şekilde sağlar. Dosya sistemleri , örneğin bir dosya
üzerinde çalışırken HDD kafa aramalarını azaltarak, dosya içeriklerini meta verilerinin yakınında
da gruplandırmaya çalışır .
Bazı işletim sistemleri, özel programlara, herhangi bir dosya sistemi veri yapısı olmaksızın,
büyük bir ardışık mantıksal blok dizisi olarak bir bölümü kullanma yeteneği verir. Bu diziye bazen
ham disk denir ve bu diziye G/Ç , ham G/Ç olarak adlandırılır. Örneğin, takas alanı için kullanılabilir
(bkz. Bölüm 11.6.2) ve bazı veritabanı sistemleri , kontrol etmelerini sağladığı için ham G/Ç'yi
tercih eder.
Machine Translated by Google

11.5 Depolama Aygıtı Yönetimi 465

Şekil 11.9 Aygıtları, bölümleri, birimleri ve dosya sistemlerini gösteren Windows 7 Disk
Yönetimi aracı.

her bir veritabanı kaydının depolandığı tam konum. Ham G/Ç , arabellek önbelleği,
dosya kilitleme, önceden getirme, alan ayırma, dosya adları ve dizinler gibi tüm
dosya sistemi hizmetlerini atlar. Bazı uygulamaları ham bir bölüm üzerinde kendi
özel amaçlı depolama hizmetlerini uygulamalarına izin vererek daha verimli hale
getirebiliriz, ancak çoğu uygulama verileri yönetmek yerine sağlanan bir dosya
sistemini kullanır. Linux'un genellikle ham G/Ç'yi desteklemediğini, ancak open()
sistem çağrısına DIRECT bayrağını kullanarak benzer erişim sağlayabildiğini
unutmayın.

11.5.2 Önyükleme Bloğu

Bir bilgisayarın çalışmaya başlaması için (örneğin, açıldığında veya yeniden


başlatıldığında) çalışacak bir başlangıç programına sahip olması gerekir. Bu ilk
önyükleme yükleyicisi basit olma eğilimindedir. Çoğu bilgisayar için, önyükleme,
sistem ana kartındaki NVM flash bellek sabit yazılımında depolanır ve bilinen bir
bellek konumuna eşlenir. Gerektiğinde ürün üreticileri tarafından güncellenebilir,
ancak sisteme bulaşan virüsler tarafından da yazılabilir. CPU kayıtlarından cihaz
denetleyicilerine ve ana belleğin içeriğine kadar sistemin tüm yönlerini başlatır .

Bu küçük önyükleme yükleyici programı, ikincil depolamadan tam bir önyükleme


programı getirecek kadar akıllıdır. Tam önyükleme programı, aygıtta sabit bir yerde
"önyükleme bloklarında" saklanır. Varsayılan Linux önyükleme yükleyicisi grub2'dir
(https://www.gnu.org/software/grub/manual/ grub.html/). Önyükleme bölümü olan
bir aygıta önyükleme diski veya sistem diski denir.

Önyükleme NVM'sindeki kod , depolama denetleyicisine önyükleme bloklarını


belleğe okumasını söyler (bu noktada hiçbir aygıt sürücüsü yüklenmez) ve ardından
bu kodu yürütmeye başlar. Tam önyükleme programı, önyükleme yükleyicisinden
daha karmaşıktır: tüm işletim sistemini cihazdaki sabit olmayan bir yerden
yükleyebilir ve işletim sistemini çalıştırabilir.
Örnek olarak Windows'taki önyükleme işlemini ele alalım. İlk olarak,
Windows'un bir sürücünün bölümlere ayrılmasına izin verdiğini ve önyükleme
bölümü olarak tanımlanan bir bölümün işletim sistemi ve aygıt sürücülerini
içerdiğini unutmayın. Windows sistemi, önyükleme kodunu sabit diskteki ilk
mantıksal bloğa veya ana önyükleme olarak adlandırdığı NVM aygıtının ilk sayfasına yerleştirir.
Machine Translated by Google

466 Bölüm 11 Yığın Depolama Yapısı

MBR önyükleme kodu

bölüm 1 bölme
tablosu

bölüm 2

önyükleme bölümü
bölüm 3

bölüm 4

Şekil 11.10 Windows'ta bir depolama aygıtından önyükleme.

kayıt veya MBR. Önyükleme, sistemin belleniminde bulunan kodu çalıştırarak başlar. Bu
kod, sistemi MBR'den önyükleme kodunu okumaya yönlendirir ve depolama denetleyicisi
ve depolama aygıtı hakkında ondan bir sektör yüklemek için yeterince bilgi sahibi olur.
Önyükleme kodunu içermeye ek olarak, MBR , Şekil 11.10'da gösterildiği gibi, sürücü için
bölümleri listeleyen bir tablo ve sistemin hangi bölümden önyükleneceğini gösteren bir
bayrak içerir. Sistem önyükleme bölümünü tanımladıktan sonra, o bölümden ( önyükleme
sektörü olarak adlandırılır) ilk sektörü/sayfayı okur ve bu onu çekirdeğe yönlendirir.
Ardından, çeşitli alt sistemlerin ve sistem hizmetlerinin yüklenmesini içeren önyükleme
işleminin geri kalanıyla devam eder.

11.5.3 Kötü Bloklar

Disklerin hareketli parçaları ve küçük toleransları olduğundan (disk kafasının disk yüzeyinin
hemen üzerinde uçtuğunu hatırlayın), bozulmaya eğilimlidirler. Bazen başarısızlık
tamamlanır; bu durumda diskin değiştirilmesi ve içeriğinin yedekleme ortamından yeni
diske geri yüklenmesi gerekir. Daha sık olarak, bir veya daha fazla sektör kusurlu hale gelir.
Hatta çoğu disk fabrikadan bozuk bloklarla gelir. Kullanılan diske ve denetleyiciye bağlı
olarak, bu bloklar çeşitli şekillerde işlenir.

IDE denetleyicileri olan bazı diskler gibi eski disklerde bozuk bloklar manuel olarak
işlenir. Bir strateji, disk biçimlendirilirken bozuk blokları bulmak için diski taramaktır.
Bulunan tüm bozuk bloklar, dosya sisteminin bunları ayırmaması için kullanılamaz olarak
işaretlenir. Normal çalışma sırasında bloklar bozulursa , bozuk blokları aramak ve onları
kilitlemek için özel bir program (Linux badblocks komutu gibi) manuel olarak çalıştırılmalıdır.
Bozuk bloklarda bulunan veriler genellikle kaybolur.

Daha karmaşık diskler, bozuk blok kurtarma konusunda daha akıllıdır. Denetleyici,
diskteki bozuk blokların bir listesini tutar. Liste, fabrikada düşük düzeyli biçimlendirme
sırasında başlatılır ve diskin ömrü boyunca güncellenir.
Düşük seviyeli biçimlendirme, işletim sistemi tarafından görülmeyen yedek sektörleri de
bir kenara bırakır. Denetleyiciye, her bozuk sektörü mantıksal olarak yedek sektörlerden
biriyle değiştirmesi söylenebilir. Bu şema, sektör yedekleme veya yönlendirme olarak bilinir .
Tipik bir kötü sektör işlemi aşağıdaki gibi olabilir:

• İşletim sistemi mantıksal blok 87'yi okumaya çalışır.


Machine Translated by Google

11.6 Takas Alanı Yönetimi 467


• Kontrolör ECC'yi hesaplar ve sektörün bozuk olduğunu tespit eder. Rapor ediyor
bu bulgu işletim sistemine bir G/Ç hatası olarak gönderilir.

• Aygıt denetleyicisi bozuk sektörü bir yedekle değiştirir. • Bundan

sonra, sistem mantıksal blok 87'yi her talep ettiğinde, talep kontrolör tarafından
değiştirme sektörünün adresine çevrilir.

Denetleyici tarafından böyle bir yeniden yönlendirmenin, işletim sisteminin disk


zamanlama algoritması tarafından yapılan herhangi bir optimizasyonu geçersiz
kılabileceğini unutmayın! Bu nedenle, çoğu disk, her silindirde birkaç yedek sektör ve
ayrıca bir yedek silindir sağlayacak şekilde biçimlendirilir. Bozuk bir blok yeniden
eşlendiğinde, denetleyici, mümkünse aynı silindirden bir yedek sektör kullanır.
Sektör ayırmaya bir alternatif olarak, bazı denetleyicilere bozuk bir bloğu sektör
kayması ile değiştirmeleri talimatı verilebilir . İşte bir örnek: Mantıksal blok 17'nin arızalı
hale geldiğini ve mevcut ilk yedeğin sektör 202'yi takip ettiğini varsayalım.
Sektör kayması daha sonra 17'den 202'ye kadar olan tüm sektörleri yeniden eşleyerek
hepsini bir noktada aşağıya taşır. Yani sektör 202 yedeğe kopyalanır, ardından sektör
201'i 202'ye, ardından 200'ü 201'e ve bu şekilde devam eder, sektör 18 sektör 19'a
kopyalanır. Sektörleri bu şekilde kaydırmak sektör 18'in alanını boşaltır, böylece sektör
17 bununla eşlenebilir.
Kurtarılabilir yazılım hataları, blok verilerinin bir kopyasının yapıldığı ve bloğun
ayrıldığı veya kaydırıldığı bir cihaz etkinliğini tetikleyebilir. Ancak kurtarılamayan bir
sabit hata, verilerin kaybolmasına neden olur. Bu bloğu hangi dosya kullanıyorsa onarmak
gerekir (örneğin, bir yedekleme bandından geri yükleyerek) ve bu manuel müdahale
gerektirir.
NVM aygıtlarında ayrıca, üretim sırasında işlevsiz olan veya zamanla bozulan bitler,
baytlar ve hatta sayfalar bulunur. Bu hatalı alanların yönetimi, kaçınılması gereken arama
süresi performans kaybı olmadığından HDD'lere göre daha basittir. Ya birden fazla sayfa
bir kenara ayrılabilir ve değiştirme konumları olarak kullanılabilir ya da aşırı sağlama
alanından alan kullanılabilir (fazla sağlama alanının kullanılabilir kapasitesini azaltarak).
Her iki durumda da, denetleyici bozuk sayfaların bir tablosunu tutar ve bu sayfaları hiçbir
zaman yazılabilir olarak ayarlamaz, böylece asla erişilmez.

11.6 Takas Alanı Yönetimi


Değiştirme ilk olarak, tüm süreçleri ikincil depolama ve ana bellek arasında taşımayı
tartıştığımız Bölüm 9.5'te sunuldu. Bu ayardaki takas, fiziksel bellek miktarı kritik derecede
düşük bir noktaya ulaştığında ve işlemler bellekten takas alanına, kullanılabilir belleği
boşaltmak için taşındığında gerçekleşir.
Pratikte, çok az sayıda modern işletim sistemi takası bu şekilde uygular. Bunun yerine,
sistemler artık takası sanal bellek teknikleri (Bölüm 10) ve takas sayfaları ile birleştiriyor,
tüm süreçleri değil. Aslında, bazı sistemler artık bu iki kavramın birleşmesini yansıtan
"swapping" ve "paging" terimlerini birbirinin yerine kullanıyor.

Takas alanı yönetimi , işletim sisteminin bir başka düşük seviyeli görevidir. Sanal
bellek, ana belleğin bir uzantısı olarak ikincil depolama alanını kullanır. Sürücü erişimi,
bellek erişiminden çok daha yavaş olduğundan, takas kullanarak
468 Bölüm 11 Yığın Depolama Yapısı
Machine Translated by Google

alan, sistem performansını önemli ölçüde azaltır. Takas alanının tasarımı ve


uygulanmasının ana hedefi, sanal bellek sistemi için en iyi çıktıyı sağlamaktır. Bu
bölümde, takas alanının nasıl kullanıldığını, takas alanının depolama aygıtlarında
nerede bulunduğunu ve takas alanının nasıl yönetildiğini tartışacağız.

11.6.1 Değiştirme Alanı Kullanımı

Değiştirme alanı, kullanılan bellek yönetimi algoritmalarına bağlı olarak farklı


işletim sistemleri tarafından çeşitli şekillerde kullanılır. Örneğin, takası uygulayan
sistemler, kod ve veri bölümleri de dahil olmak üzere tüm süreç görüntüsünü
tutmak için takas alanını kullanabilir. Çağrı sistemleri, basitçe ana bellekten dışarı
itilen sayfaları saklayabilir. Bu nedenle, bir sistemde ihtiyaç duyulan takas alanı
miktarı, fiziksel bellek miktarına, desteklediği sanal bellek miktarına ve sanal
belleğin kullanılma şekline bağlı olarak birkaç megabayt disk alanından gigabayta
kadar değişebilir.
Gereken takas alanı miktarını olduğundan fazla tahmin etmenin daha güvenli
olabileceğini unutmayın, çünkü bir sistemde takas alanı biterse, işlemleri iptal
etmek zorunda kalabilir veya tamamen çökebilir. Fazla tahmin, dosyalar için
kullanılabilecek ikincil depolama alanını boşa harcar, ancak başka bir zararı yoktur.
Bazı sistemler, takas alanı için ayrılacak miktarı önerir. Örneğin Solaris, sanal
belleğin sayfalanabilir fiziksel belleği aştığı miktara eşit takas alanı ayarlamayı
önerir. Geçmişte Linux, fiziksel bellek miktarını iki katına çıkarmak için takas alanı
ayarlamayı önerdi. Bugün, sayfalama algoritmaları değişti ve çoğu Linux sistemi
önemli ölçüde daha az takas alanı kullanıyor.

Linux dahil olmak üzere bazı işletim sistemleri, hem dosyalar hem de özel takas
bölümleri dahil olmak üzere birden çok takas alanının kullanımına izin verir. Bu
takas alanları genellikle ayrı depolama aygıtlarına yerleştirilir, böylece sayfalama ve
takas yoluyla G/Ç sistemine yüklenen yük, sistemin G/Ç bant genişliğine yayılabilir .

11.6.2 Takas Alanı Konumu Takas alanı iki

yerden birinde bulunabilir: normal dosya sisteminden oyulabilir veya ayrı bir
bölümde olabilir. Takas alanı dosya sistemi içindeki büyük bir dosyaysa, onu
oluşturmak, adlandırmak ve alanını tahsis etmek için normal dosya sistemi rutinleri
kullanılabilir.
Alternatif olarak, takas alanı ayrı bir ham bölümde oluşturulabilir. Bu alana
hiçbir dosya sistemi veya dizin yapısı yerleştirilmemiştir. Bunun yerine, ham
bölümden blokları tahsis etmek ve serbest bırakmak için ayrı bir takas alanı
depolama yöneticisi kullanılır. Bu yönetici, depolama verimliliği yerine hız için
optimize edilmiş algoritmalar kullanır, çünkü takas alanına, kullanıldığında dosya
sistemlerinden çok daha sık erişilir (takas alanının takas ve sayfalama için
kullanıldığını hatırlayın). Dahili parçalanma artabilir, ancak bu takas kabul edilebilir
çünkü takas alanındaki verilerin ömrü genellikle dosya sistemindeki dosyalardan
çok daha kısadır. Takas alanı önyükleme sırasında yeniden başlatıldığından,
herhangi bir parçalanma kısa ömürlüdür. Ham bölüm yaklaşımı, disk bölümleme
sırasında sabit miktarda takas alanı oluşturur. Daha fazla takas alanı eklemek,
aygıtın yeniden bölümlenmesini gerektirir (bu,
Machine Translated by Google

11.7 Depolama Eklentisi 469

diğer dosya sistemi bölümleri veya onları yok etme ve yedekten geri yükleme) veya başka
bir yere başka bir takas alanı ekleme.
Bazı işletim sistemleri esnektir ve hem ham bölümlerde hem de dosya sistemi
alanında yer değiştirebilir. Linux bir örnektir: ilke ve uygulama ayrıdır ve makinenin
yöneticisinin hangi tür takasın kullanılacağına karar vermesine olanak tanır. Takas, dosya
sisteminde tahsis ve yönetim kolaylığı ile ham bölümlerde takas performansı arasındadır.

11.6.3 Takas Alanı Yönetimi: Bir Örnek


Çeşitli UNIX sistemlerinde takas ping ve sayfalamanın gelişimini takip ederek takas
alanının nasıl kullanıldığını gösterebiliriz . Geleneksel UNIX çekirdeği, bitişik disk
bölgeleri ve bellek arasındaki tüm işlemleri kopyalayan bir takas uygulamasıyla başladı.
UNIX , daha sonra, sayfalama donanımı kullanılabilir hale geldikçe, değiştirme ve
sayfalamanın bir kombinasyonuna dönüştü.
Solaris 1'de (SunOS), tasarımcılar verimliliği artırmak ve teknolojik gelişmeleri
yansıtmak için standart UNIX yöntemlerini değiştirdiler. Bir işlem yürütüldüğünde, kod
içeren metin-segment sayfaları dosya sisteminden getirilir, ana belleğe erişilir ve sayfa
çıkışı için seçilirse atılır.
Dosya sisteminden bir sayfayı yeniden okumak, onu takas alanına yazmak ve ardından
oradan yeniden okumaktan daha verimlidir. Takas alanı yalnızca , bir işlemin yığın, yığın
ve başlatılmamış verileri için ayrılan belleği içeren anonim belleğin (herhangi bir dosya
tarafından desteklenmeyen bellek) sayfaları için bir yedekleme deposu olarak kullanılır.

Solaris'in sonraki sürümlerinde daha fazla değişiklik yapıldı. En büyük değişiklik,


Solaris'in artık takas alanını sanal bellek sayfası ilk oluşturulduğunda değil, yalnızca bir
sayfa fiziksel bellekten çıkmaya zorlandığında ayırmasıdır.
Bu şema, eski sistemlerden daha fazla fiziksel belleğe sahip olan ve daha az sayfa açma
eğiliminde olan modern bilgisayarlarda daha iyi performans sağlar.
Linux, Solaris'e benzer, çünkü takas alanı artık yalnızca anonim fare belleği için
kullanılıyor. Linux, bir veya daha fazla takas alanının kurulmasına izin verir. Bir takas alanı,
normal bir dosya sistemindeki bir takas dosyasında veya özel bir takas bölümünde
olabilir. Her takas alanı, değiştirilen sayfaları tutmak için kullanılan bir dizi 4 KB'lık sayfa
yuvasından oluşur. Her takas alanıyla ilişkili bir takas haritasıdır—her biri takas alanındaki
bir sayfa yuvasına karşılık gelen bir dizi tamsayı sayacı.
Bir sayacın değeri 0 ise, karşılık gelen sayfa yuvası mevcuttur. 0'dan büyük değerler,
sayfa yuvasının değiştirilen bir sayfa tarafından işgal edildiğini gösterir. Sayacın değeri,
değiştirilen sayfaya yapılan eşlemelerin sayısını gösterir.
Örneğin, 3 değeri, değiştirilen sayfanın üç farklı işlemle eşlendiğini gösterir (bu,
değiştirilen sayfa, üç işlem tarafından paylaşılan bir bellek bölgesini depoluyorsa
oluşabilir). Linux sistemlerinde takas için veri yapıları Şekil 11.11'de gösterilmektedir.

11.7 Depolama Eklentisi

Bilgisayarlar ikincil depolamaya üç şekilde erişir: ana bilgisayara bağlı depolama, ağa
bağlı depolama ve bulut depolama yoluyla.
Machine Translated by Google

470 Bölüm 11 Yığın Depolama Yapısı

takas alanı
sayfa
yuvası

takas bölümü
veya takas dosyası

takas haritası 10301

Şekil 11.11 Linux sistemlerinde takas için veri yapıları.

11.7.1 Ana Bilgisayara Bağlı Depolama Ana

Bilgisayara bağlı depolama , yerel G/Ç bağlantı noktaları aracılığıyla erişilen depolamadır . Bu
bağlantı noktaları, daha önce belirtildiği gibi en yaygın olanı SATA olan çeşitli teknolojiler kullanır.
Tipik bir sistemde bir veya birkaç SATA bağlantı noktası bulunur.
Bir sistemin daha fazla depolama alanına erişmesine izin vermek için, tek bir depolama
aygıtı, kasadaki bir cihaz veya kasadaki birden çok sürücü USB FireWire veya Thunderbolt
bağlantı noktaları ve kabloları aracılığıyla bağlanabilir.
Üst düzey iş istasyonları ve sunucular genellikle daha fazla depolamaya ihtiyaç duyar veya
depolamayı paylaşmaya ihtiyaç duyar, bu nedenle fiber kanal (FC) gibi daha karmaşık G/Ç
mimarileri, fiber optik veya dört üzerinden çalışabilen yüksek hızlı bir seri mimari kullanın.
iletken bakır kablo. Geniş adres alanı ve iletişimin anahtarlamalı yapısı nedeniyle, birden çok
ana bilgisayar ve depolama aygıtı yapıya eklenebilir ve bu da G/Ç iletişiminde büyük esneklik
sağlar .
Ana bilgisayara bağlı depolama olarak kullanım için çok çeşitli depolama cihazları
uygundur. Bunların arasında HDD'ler; NVM cihazları; CD, DVD, Blu-ray ve teyp sürücüleri; ve
depolama alanı ağları (SAN'lar) (Bölüm 11.7.4'te ele alınmıştır). Ana bilgisayara bağlı bir
depolama aygıtına veri aktarımlarını başlatan G/Ç komutları, özel olarak tanımlanmış depolama
birimlerine (veri yolu kimliği veya hedef mantıksal birim gibi) yönelik mantıksal veri bloklarının
okuma ve yazma işlemleridir.

11.7.2 Ağa Bağlı Depolama Ağa bağlı depolama

(NAS) (Şekil 11.12), bir ağ üzerinden depolamaya erişim sağlar. Bir NAS cihazı, özel amaçlı bir
depolama sistemi veya depolamasını ağdaki diğer ana bilgisayarlara sağlayan genel bir
bilgisayar sistemi olabilir. İstemciler, UNIX ve Linux sistemleri için NFS veya Windows
makineleri için CIFS gibi bir uzaktan prosedür çağrı arabirimi aracılığıyla ağa bağlı
depolamaya erişir . Uzaktan yordam çağrıları (RPC'ler) , bir IP ağı üzerinden TCP veya UDP
aracılığıyla taşınır - genellikle tüm veri trafiğini istemcilere taşıyan aynı yerel alan ağı (LAN) .
Ağa bağlı depolama birimi, genellikle RPC arabirimini uygulayan yazılıma sahip bir depolama
dizisi olarak uygulanır .

CIFS ve NFS , çeşitli kilitleme özellikleri sağlayarak, bu protokollerle bir NAS'a erişen ana
bilgisayarlar arasında dosya paylaşımına izin verir . Örneğin, birden fazla NAS istemcisinde
oturum açmış bir kullanıcı , aynı anda tüm bu istemcilerden kendi ana dizinine erişebilir.
Machine Translated by Google

11.7 Depolama Eklentisi 471

müşteri

NAS

LAN/WAN müşteri

NAS
müşteri

Şekil 11.12 Ağa bağlı depolama.

Ağa bağlı depolama, bir LAN üzerindeki tüm bilgisayarların, yerel ana bilgisayara
bağlı depolama ile aynı adlandırma ve erişim kolaylığıyla bir depolama havuzunu
paylaşması için uygun bir yol sağlar. Ancak, bazı doğrudan bağlı depolama
seçeneklerinden daha az verimli ve daha düşük performansa sahip olma eğilimindedir.
iSCSI , ağa bağlı en yeni depolama protokolüdür. Özünde, SCSI protokolünü taşımak
için IP ağ protokolünü kullanır . Bu nedenle, SCSI kabloları yerine ağlar, ana bilgisayarlar
ve depolamaları arasındaki ara bağlantı olarak kullanılabilir.
Sonuç olarak, ana bilgisayarlar, depolama ana bilgisayardan uzakta olsa bile, depolamalarına
doğrudan bağlıymış gibi davranabilir. NFS ve CIFS bir dosya sistemi sunarken ve
dosyaların bölümlerini ağ üzerinden gönderirken, iSCSI ağ üzerinden mantıksal bloklar
gönderir ve blokları doğrudan kullanmasını veya onlarla bir dosya sistemi oluşturmasını
istemciye bırakır.

11.7.3 Bulut Depolama


Bölüm 1.10.5, bulut bilişimi tartıştı. Bulut sağlayıcılarından bir teklif, bulut depolamadır.
Ağa bağlı depolamaya benzer şekilde, bulut depolama, bir ağ üzerinden depolamaya
erişim sağlar. NAS'ın aksine , depolamaya İnternet veya başka bir WAN üzerinden bir
ücret karşılığında (hatta ücretsiz olarak) depolama sağlayan uzak bir veri merkezine
erişilir .
NAS ve bulut depolama arasındaki diğer bir fark , depolamaya nasıl erişildiği ve
kullanıcılara nasıl sunulduğudur. CIFS veya NFS protokolleri kullanılıyorsa NAS'a yalnızca
başka bir dosya sistemi olarak veya iSCSI protokolü kullanılıyorsa ham blok aygıtı olarak
erişilir. Çoğu işletim sisteminde bu protokoller entegre edilmiştir ve NAS depolamayı
diğer depolama ile aynı şekilde sunar. Buna karşılık, bulut depolama API tabanlıdır ve
programlar depolamaya erişmek için API'leri kullanır. Amazon S3 , lider bir bulut depolama
teklifidir. Dropbox, sağladığı bulut depolama alanına bağlanmak için uygulamalar
sağlayan bir şirket örneğidir. Diğer örnekler arasında Microsoft OneDrive ve Apple
iCloud bulunur.
API'lerin mevcut protokoller yerine kullanılmasının bir nedeni , bir WAN'ın gecikme ve
başarısızlık senaryolarıdır. NAS protokolleri, WAN'lardan daha düşük gecikme süresine
sahip olan ve depolama kullanıcısı ile depolama cihazı arasındaki bağlantıyı kaybetme
olasılığı çok daha düşük olan LAN'larda kullanılmak üzere tasarlanmıştır . Bir LAN
bağlantısı başarısız olursa, NFS veya CIFS kullanan bir sistem, düzelene kadar askıda
kalabilir. Bulut depolama ile, bu tür arızalar daha olasıdır, bu nedenle bir uygulama,
bağlantı yeniden sağlanana kadar erişimi duraklatır.
Machine Translated by Google

472 Bölüm 11 Yığın Depolama Yapısı

müşteri
sunucu

müşteri
depolama LAN/WAN
dizisi sunucu
müşteri

depolama SAN
dizisi veri işleme merkezi

teyp web içerik


kitaplığı sağlayıcısı

Şekil 11.13 Depolama alanı ağı.

11.7.4 Depolama Alanı Ağları ve Depolama Dizileri


Ağa bağlı depolama sistemlerinin bir dezavantajı, depolama G/Ç işlemlerinin veri
ağındaki bant genişliğini tüketmesi ve böylece ağ iletişiminin gecikmesini artırmasıdır.
Bu sorun, büyük istemci-sunucu kurulumlarında özellikle akut olabilir - sunucular ve
istemciler arasındaki iletişim, bant genişliği için sunucular ve depolama cihazları
arasındaki iletişimle rekabet eder.

Depolama alanı ağı (SAN) , Şekil 11.13'te gösterildiği gibi sunucuları ve depolama
birimlerini birbirine bağlayan (ağ protokolleri yerine depolama protokollerini kullanan)
özel bir ağdır. Bir SAN'ın gücü , esnekliğinde yatar. Aynı SAN'a birden çok ana bilgisayar
ve birden çok depolama dizisi eklenebilir ve depolama, ana bilgisayarlara dinamik olarak
ayrılabilir. Depolama dizileri, RAID korumalı veya korumasız sürücüler olabilir (Sadece Bir
Grup Disk (JBOD)). Bir SAN anahtarı, ana bilgisayarlar ve depolama arasında erişime izin
verir veya erişimi engeller. Örnek olarak, bir ana bilgisayarın disk alanı azalıyorsa, SAN ,
o ana bilgisayara daha fazla depolama tahsis edecek şekilde yapılandırılabilir. SAN'lar ,
sunucu kümelerinin aynı depolamayı paylaşmasını ve depolama dizilerinin birden çok
doğrudan ana bilgisayar bağlantısı içermesini mümkün kılar.
SAN'lar genellikle depolama dizilerinden daha fazla bağlantı noktasına sahiptir ve maliyeti daha
yüksektir. SAN bağlantısı kısa mesafelerdedir ve tipik olarak yönlendirmesi yoktur, bu nedenle bir
NAS , bir SAN'dan çok daha fazla bağlı ana bilgisayara sahip olabilir .
Depolama dizisi, SAN bağlantı noktalarını, ağ bağlantı noktalarını veya her ikisini
birden içeren amaca yönelik oluşturulmuş bir aygıttır (bkz. Şekil 11.14) . Ayrıca, verileri
depolamak için sürücüler ve depolamayı yönetmek ve ağlar üzerinden depolamaya
erişime izin vermek için bir denetleyici (veya yedekli denetleyiciler kümesi) içerir.
Denetleyiciler, ağ protokollerini, kullanıcı arabirimlerini, RAID korumasını, anlık
görüntüleri, çoğaltmayı, sıkıştırmayı, veri tekilleştirmeyi ve şifrelemeyi içerebilen dizinin
özelliklerini uygulayan CPU'lar, bellek ve yazılımdan oluşur. Bu işlevlerden bazıları Bölüm
14'te tartışılmaktadır.
Bazı depolama dizileri SSD'leri içerir. Bir dizi yalnızca SSD'leri içerebilir , bu da
maksimum performans ancak daha küçük kapasite ile sonuçlanır veya dizi yazılımının
(veya yöneticinin) belirli bir kullanım için en iyi ortamı seçmesi veya SSD'leri önbellek
olarak kullanması ile birlikte SSD'ler ve HDD'lerin bir karışımını içerebilir. ve toplu
depolama olarak HDD'ler .
11.8 RAID Yapısı 473
Machine Translated by Google

Şekil 11.14 Bir depolama dizisi.

FC , en yaygın SAN ara bağlantısıdır, ancak iSCSI'nin basitliği


kullanımını artırmaktadır. Diğer bir SAN ara bağlantısı, donanım ve yazılım desteği
sağlayan özel amaçlı bir veri yolu mimarisi olan InfiniBan'dır (IB).
sunucular ve depolama birimleri için yüksek hızlı ara bağlantı ağları.

11.8 RAID Yapısı

Depolama aygıtları küçülmeye ve ucuzlamaya devam etti, bu nedenle artık birçok sürücüyü
bir bilgisayar sistemine bağlamak ekonomik olarak mümkün. sahip olmak
Bir sistemdeki çok sayıda sürücü, iyileştirme için fırsatlar sunar.
Sürücüler paralel olarak çalıştırılırsa, verilerin okunabileceği veya yazılabileceği hız. Ayrıca,
bu kurulum güvenilirliği artırma potansiyeli sunar
veri depolama, çünkü fazlalık bilgiler birden çok yerde saklanabilir
sürücüler. Bu nedenle, bir sürücünün arızalanması veri kaybına yol açmaz. Çeşitli
Toplu olarak bağımsız disklerin yedekli dizileri (RAID'ler) olarak adlandırılan disk düzenleme
teknikleri, performansı ele almak için yaygın olarak kullanılır ve
güvenilirlik sorunları.
Geçmişte, küçük, ucuz disklerden oluşan RAID'ler , büyük ve pahalı disklere uygun
maliyetli bir alternatif olarak görülüyordu. Bugün, RAID'ler amaçları için kullanılmaktadır.
ekonomik nedenlerden ziyade daha yüksek güvenilirlik ve daha yüksek veri aktarım hızı. Bu
nedenle, bir zamanlar "ucuz" anlamına gelen RAID'deki I , şimdi
"bağımsız."

11.8.1 Yedeklilik Yoluyla Güvenilirliğin İyileştirilmesi

Önce RAID RAID'lerinin güvenilirliğini ele alalım . Bazı disklerin şansı


N disk kümesinin başarısız olması, belirli bir diskin başarısız olma şansından çok daha fazladır.
tek disk başarısız olur. Arızalar arasındaki ortalama sürenin (MTBF) olduğunu varsayalım .
tek bir disk 100.000 saattir. Ardından, 100 dizisindeki bazı disklerin MTBF'si
474 Bölüm 11 Yığın Depolama Yapısı
Machine Translated by Google

YAPILANDIRMA RAID

RAID depolama çeşitli şekillerde yapılandırılabilir. Örneğin, bir sistem doğrudan


veri yollarına bağlı sürücülere sahip olabilir. Bu durumda, işletim sistemi veya
sistem yazılımı RAID işlevselliğini uygulayabilir . Alternatif olarak, akıllı bir ana
bilgisayar denetleyicisi birden çok bağlı aygıtı kontrol edebilir ve donanımdaki bu
aygıtlara RAID uygulayabilir . Son olarak, bir depolama dizisi kullanılabilir. Bir
depolama dizisi, az önce tartışıldığı gibi, kendi denetleyicisi, önbelleği ve
sürücüleri olan bağımsız bir birimdir. Bir veya daha fazla standart denetleyici
(örneğin, FC) aracılığıyla ana bilgisayara bağlanır. Bu ortak kurulum, RAID işlevi
olmayan bir işletim sisteminin veya yazılımın RAID korumalı depolamaya sahip olmasını sağ

diskler 100.000/100 = 1.000 saat veya 41.66 gün olacak, ki bu hiç de uzun değil!
Verilerin yalnızca bir kopyasını saklarsak, her disk arızası önemli miktarda veri
kaybına neden olur ve bu kadar yüksek bir veri kaybı oranı kabul edilemez.
Güvenilirlik sorununun çözümü artıklık getirmektir; normalde ihtiyaç
duyulmayan ancak disk arızası durumunda kayıp bilgileri yeniden oluşturmak için
kullanılabilecek ek bilgileri depolarız. Böylece bir disk arızalansa bile veriler
kaybolmaz. RAID , NVM cihazlarına da uygulanabilir , ancak NVM cihazlarının
hareketli parçaları yoktur ve bu nedenle HDD'lere göre arızalanma olasılığı daha düşük
Artıklık sağlamanın en basit (ama en pahalı) yaklaşımı, her sürücüyü
çoğaltmaktır. Bu tekniğe yansıtma denir . Yansıtma ile mantıksal disk iki fiziksel
sürücüden oluşur ve her yazma işlemi her iki sürücüde de gerçekleştirilir. Sonuç,
yansıtılmış birim olarak adlandırılır. Birimdeki sürücülerden biri arızalanırsa, veriler
diğerinden okunabilir. Veriler, yalnızca ilk arızalı sürücü değiştirilmeden önce
ikinci sürücü arızalanırsa kaybolur.
Yansıtılmış bir birimin MTBF'si (burada hata, veri kaybıdır) iki faktöre bağlıdır.
Biri, bireysel sürücülerin MTBF'sidir. Diğeri, ortalama onarım süresidir; bu, arızalı
bir sürücüyü değiştirmek ve üzerindeki verileri geri yüklemek için (ortalama
olarak) geçen süredir. İki sürücünün arızalarının bağımsız olduğunu varsayalım;
yani birinin başarısızlığı diğerinin başarısızlığına bağlı değildir. Ardından, tek
bir sürücünün MTBF'si 100.000 saat ve ortalama onarım süresi 10 saat ise,
yansıtılmış bir sürücü sisteminin ortalama veri kaybı süresi 100.0002 (2 10) =
500 106 saat veya 57.000 yıl!
Sürücü arızalarının bağımsız olacağını gerçekten varsayamayacağımızı
bilmelisiniz. Elektrik kesintileri ve deprem, yangın ve sel gibi doğal afetler, aynı
anda her iki sürücüde de hasara neden olabilir. Ayrıca, bir grup sürücüdeki üretim
hataları, ilişkili arızalara neden olabilir. Sürücüler yaşlandıkça, arıza olasılığı artar
ve birincisi onarılırken ikinci bir sürücünün arızalanma şansı artar. Bununla birlikte,
tüm bu hususlara rağmen, aynalı tahrik sistemleri, tek tahrikli sistemlere göre
çok daha yüksek güvenilirlik sunar.

Elektrik kesintileri, doğal afetlerden çok daha sık meydana geldikleri için özel
bir endişe kaynağıdır. Sürücülerin ikizlenmesinde bile, her iki sürücüde de aynı
bloğa yazma işlemi devam ediyorsa ve her iki blok tamamen yazılmadan önce
güç kesilirse, iki blok tutarsız bir durumda olabilir. Bu soruna bir çözüm, önce bir
kopya, sonra bir kopya yazmaktır. Diğeri, RAID dizisine katı hal kalıcı bir önbellek
eklemektir . Bu geri yazma önbelleği
Machine Translated by Google

11.8 RAID Yapısı 475

elektrik kesintileri sırasında veri kaybından korunur, bu nedenle, önbelleğin ECC veya ikizleme
gibi bir tür hata koruması ve düzeltmesi olduğu varsayılarak, yazma işleminin bu noktada
tamamlanmış olduğu kabul edilebilir .

11.8.2 Paralellik Yoluyla Performansta İyileştirme Şimdi, birden çok sürücüye paralel

erişimin performansı nasıl geliştirdiğini ele alalım. Yansıtma ile, okuma isteklerinin işlenme hızı iki
katına çıkar, çünkü okuma istekleri her iki sürücüye de gönderilebilir (neredeyse her zaman olduğu
gibi, her ikisi de bir çiftte işlevsel olduğu sürece). Her okumanın aktarım hızı, tek sürücülü sistemdekiyle
aynıdır, ancak birim zaman başına okuma sayısı iki katına çıkmıştır.

Birden fazla sürücüyle, verileri sürücüler arasında şeritleyerek (veya bunun yerine)
aktarım hızını da iyileştirebiliriz. En basit biçiminde, veri şeritleme , her bir baytın bitlerini
birden çok sürücüye bölmekten oluşur; bu tür şeritleme, bit düzeyinde şeritleme olarak
adlandırılır. Örneğin, sekiz sürücüden oluşan bir dizimiz varsa, i sürücüsüne her baytın i bitini
yazarız . Sekiz sürücü dizisi, normal boyutun sekiz katı ve daha da önemlisi erişim hızının sekiz
katı olan sektörlere sahip tek bir sürücü olarak ele alınabilir. Her sürücü, her erişime katılır
(okuma veya yazma); yani saniyede işlenebilen erişim sayısı, tek bir sürücüdekiyle yaklaşık
olarak aynıdır, ancak her erişim, aynı anda tek bir sürücüdekinden sekiz kat daha fazla veri
okuyabilir.

Bit düzeyinde şeritleme, 8'in katı olan veya 8'i bölen bir dizi sürücüyü içerecek şekilde
genelleştirilebilir. Örneğin, dört sürücüden oluşan bir dizi kullanırsak, her baytın i ve 4+i
bitleri i sürücüsüne gider . Ayrıca, şeritlemenin bit seviyesinde gerçekleşmesi gerekmez.
Örneğin blok düzeyinde şeritlemede, bir dosyanın blokları birden çok sürücü arasında
şeritlenir; n sürücüde , bir dosyanın i bloğu (i mod n)+1 sürücüsüne gider .
Bir sektörün baytları veya bir bloğun sektörleri gibi diğer şeritleme seviyeleri de mümkündür.
Blok düzeyinde şeritleme, yaygın olarak kullanılabilen tek şeritlemedir.
Bir depolama sistemindeki paralellik, şeritleme yoluyla elde edildiği gibi, iki ana hedefe
sahiptir:

1. Birden çok küçük erişimin (yani sayfa erişimlerinin) verimini artırın


yük dengeleme ile.

2. Büyük erişimlerin yanıt süresini azaltın.

11.8.3 RAID Düzeyleri

Yansıtma yüksek güvenilirlik sağlar, ancak pahalıdır. Şeritleme, yüksek veri aktarım hızları
sağlar, ancak güvenilirliği artırmaz. “Parite” bitleriyle (kısaca anlatacağımız) birleştirilmiş
disk şeritlemeyi kullanarak daha düşük maliyetle artıklık sağlamak için çok sayıda şema
önerilmiştir. Bu şemaların farklı maliyet-performans dengeleri vardır ve RAID seviyeleri adı
verilen seviyelere göre sınıflandırılır. Burada yalnızca en yaygın seviyeleri açıklıyoruz; Şekil
11.15 bunları resimli olarak gösterir (şekilde P , hata düzeltme bitlerini ve C verilerin ikinci bir
kopyasını gösterir). Şekilde gösterilen tüm durumlarda, dört sürücü değerinde veri depolanır
ve fazladan sürücüler, arıza kurtarma için gereksiz bilgileri depolamak için kullanılır.
Machine Translated by Google

476 Bölüm 11 Yığın Depolama Yapısı

Şekil 11.15 RAID seviyeleri.

• RAID düzeyi 0. RAID düzeyi 0, Şekil 11.15(a)'da gösterildiği gibi, blok düzeyinde şeritlemeli
ancak herhangi bir fazlalık (yansıtma veya eşlik bitleri gibi) olmayan sürücü dizilerini ifade
eder.

• RAID düzeyi 1. RAID düzeyi 1, sürücü ikizleme anlamına gelir. Şekil 11.15(b) şunları gösterir:
yansıyan bir organizasyon.

• RAID düzeyi 4. RAID düzeyi 4, bellek stili hata düzeltme olarak da bilinir.
kod (ECC) organizasyonu. ECC , RAID 5 ve 6'da da kullanılır .
ECC fikri, sürücüler arasında blokların şeritlenmesi yoluyla doğrudan depolama
dizilerinde kullanılabilir. Örneğin, bir yazma dizisinin birinci veri bloğu sürücü 1'de, ikinci
blok sürücü 2'de saklanabilir ve N'inci blok N sürücüsünde depolanana kadar bu böyle
devam edebilir ; bu blokların hata düzeltme hesaplama sonucu, N + 1 sürücüsünde
depolanır. Bu şema, P etiketli sürücünün hata düzeltme bloğunu sakladığı Şekil
11.15(c)'de gösterilmektedir . Sürücülerden biri arızalanırsa, hata düzeltme kodunun
yeniden hesaplanması bunu algılar ve

You might also like