Süreçler Arası İletişim(IPC) ref[1]
Bir bilgisayar içinde veya bir ağdaki bilgisayarlar arasında, süreçler arasındaki otomatik veri transferidir. ref[3] Süreçler arası iletişim, daha çok, süreçler arasındaki iletişimi kolaylaştırmakla ilgili teknik ve mekanizmalarla ilgilenir. ref[2]
Karşılıklı Dışlama (MUTEX) ve Çözüm Yöntemleri
Süreç yönetimindeki temel sorun, yarış durumu (race condition) olarak belirtilen, 2 veya daha fazla sürecin paylaşılan belleğe okurken veya yazarken sonucun süreçlerin doğru sıra ve zamanda çalışmasına bağlı olduğu durumdur.
Önerilen temel çözüm ise karşılıklı dışlama(mutual exculusion:mutex) yöntemidir. Bu, kritik bölgede (paylaşılan bellek bölgesi) bulunan bir süreç varsa herhangi diğer bir sürecin kritik bölgesine girmesine izin verilmemesi, bunun önlenmesi durumudur. Karşılıklı dışlamanın gerçeklenmesi için kullanılabilen yönetemlerden üçü şunlardır: a) Semafor Kullanımı b) Monitör Kullanımı c) Mesaj İletimi
I) Semaforlar
Özel bir tamsayıdır. Sıfır veya pozitif değerler alabilir. Belli bir program üzerinde uyandırılmayı bekleyen süreç bilgisinin tutulmasında kullanılır. Bir sürecin uyku durumunda olması demek, işletim sisteminin o sürece servis yapabilmesi icin bekletilmesi demektir. Çekirdek, süreçler üzerinde uyku (sleep) ve uyandırma işlemleri yaparak (wakeup) pekçok sürecin tek bir işlemciden hizmet alabilmesini sağlar.ref[5] Sürecin uyku durumuna gelmesi aynı zamanda giriş/çıkış (I/O) işlemleri için de bekleme durumuna gelmesi demektir.ref[6]
Süreçler üzerinde tanımlı iki işlem vardır:
UP İşlemi
Semafor değerini 1 arttıran işlemdir.
DOWN İşlemi
Önce semafor değerinin 0 olup olmadığı kontrol edilir. Sıfır değilse 1 azaltılır. Sıfırsa süreç beklemeye alınarak, bir başka süreç tarafından uyandırılmak üzere uyku durumuna geçer.
Semaforlar üzerindeki UP ve DOWN işlemleri kesilemez işlemlerdir. Bir semafor üzerinde bu işlemler yapılırken, başka bir sürecin aynı semafor üzerinde işlemi yarıda keserek UP veya DOWN işlemi yapması mükün değildir. Böylece, süreçler arası iletişimdeki Sleep and Wakeup metodundakine benzer bir durumun önüne geçilmiş olur. Bu metodun uygulanmasında karşılaşılabilecek temel sorun, süreçlerden birinin tam uyku anına geçerken ama geçmeden hemen önce işlemcinin bu süreçle ilgilenmeyi bırakıp diğer sürece dönmesi, diğer süreçten gelen WAKEUP sistem çağrısının süreç gerçekten de uyku durumuna geçmediği için kaybolması, sonraki işlemci zamaninda tam uyuma aninda kalan sürecin buradan işlemine devam edip uyku durumuna geçmesi ve aslında uyanmasi gerekip sayaci arttirmayan bu sürecin diğer sürecin de uyku durumuna geçmesine sebep olmasıdır. Böylece her iki süreç de uyku durumuna geçmiştir.
Başka bir deyişle, UP ve DOWN işlemlerinin kesilemez olması yarış durumunu önlemek için gereklidir.
II) Monitörler
Özel veri yapılarıdır. İçlerinde, prosedürler, veri yapıları ve değişkenler vardır. Süreçler monitörlerin içinde tanımlı olan procedürlere erişebilir; fakat doğrudan içlerindeki veri yapılarını kullanamazlar. Karşılıklı dışlamayı sağlayan en önemli özellikleri, aynı anda sadece bir sürecin bir monitör üzerinde etkin olmasıdır. Bunu sağlamak için de kullanılan en genel metod da ikilik (binary) semafor kullanmaktır. İkilik semaforlar, başlangıç değeri 1 olarak atanan ve iki veya daha fazla süreçten sadece birinin kritik bölgesine girmesinin kontrolünde kullanılan semaforlardır.
Süreçlerin monitörlerin durum değişkenleri (condition variables) üzerinde gerçekleştirebildiği iki işlem vardır: (Durum değişkenleri, monitörlerin senkronizasyonunda kullanılan değişkenlerdir.) ref[4]
WAIT İşlemi
Bir monitör işlemi devam edemeyeceğini anlarsa durum değişkenlerinin biri üzerinde WAIT işlemi yapar. Çağıran sürecin bloklanması anlamına gelen bu işlem, aynı zamanda monitore girişi engellenen sıradaki süreçlerden birinin de girişine olanak da sağlar.
SIGNAL İşlemi
Beklemede olan süreci uyandirmak icin kullanilan işlemdir. Ayni anda iki aktif sürecin monitör içinde olmasını önlemek için konulan kural, SIGNAL işleminden sonra sürecin monitörü terk etmesi gerekliliğidir. Sonuç olarak bir SIGNAL ifadesi bir monitör süreçteki en son adım olarak gözükür. Bir diğer sonuç da WAIT işleminin daima SIGNAL işleminden önce geleceğidir.
UP ve DOWN işlemlerinde olduğu gibi monitör süreçlerin durum değişkenleri üzerinde yaptığı WAIT ve SIGNAL işlemleri de kesilemez işlemlerdir. Böylece herhangi bir süreç WAIT gerçekleştirmek üzereyken işlemin kesilip başka bir sürecin müdahalesi engellenmiş olur. Monitör yapılarındaki otomatik karşılıklı dışlama mekanizması ile paralel programlama semaforlara göre daha az hatalı gerçeklenir.
III) Mesaj İletimi
Süreçler ve monitörlerdeki temel sorun, karşılıklı dışlama sorununda bu çözüm yöntemlerinin aynı belleğe erişen süreçler için tanımlanmasıdır. Bu bellek bölgesinin dağıtık olduğu, başka bir deyişle, herbiri kendi işlemci ve belleği olan bilgisayarlardan oluşan bir ağda karşılıklı dışlama sorununun çözümü mesaj iletimi ile sağlanır. Mesaj iletiminde iki sistem çağrısı kullanılır:
SEND
Belirtilen adrese mesaj gönderir.
RECEIVE
Belirtilen kaynaktan bir mesaj alır.
Süreçler arasındaki mesaj iletimini kolaylaştırmak için mailbox (ileti kutusu) adı verilen bir veri yapısı kullanılır. Bu veri yapısını belli sayıda veri tutmak (buffer) için oluşturulmuş bir alan olarak düşünebiliriz. İleti kutuları kullanimi ile SEND ve RECEIVE'deki adres parametleri yerini, süreç adresleri yerine ileti kutularına bırakır. Buradaki prensip süreçlerin birbirlerinden gelen mesajlara ve ileti kutularının dolu olup olmamasına göre çalışmasıdır.
Primitivlerin Eşliği
Süreçler arası iletişiminin temel sorunu olan yarış durumuna, karşılıklı dışlama, semafor, monitör veya mesaj iletimi kullanılarak bir çözüm bulmaya çalışıldı. Kullanılan bu metodlar anlamsal olarak birbirine benzemektedir. Herhangi birini kullanarak diğerlerini aynı şekilde ifade etmek mümkündür. Şimdi bunların nasıl yapılabildiğini inceleyelim.
I) Monitör ve Mesaj İletiminin Semafor Kullanılarak İfadesi
İşletim sisteminin ön tanımlı olarak semafor yapısına sahip olduğunu ve bunun kullanımına izin verdiğini düşünelim. Semaforları kullanarak, süreçlerin üzerinde işlem yapabileceği mönitör kurallarına uygun bir veri yapısını aşağıdaki şekilde tanımlayabiliriz:
#include "prototypes.h" typedef int semaphore; semaphore mutex = 1; /* monitöre giriş kontrolünde kullanılacak */ void enter_monitor(void) /* monitöre girişte kullanılacak kod */ { down(mutex); /* monitör içinde aynı anda yalnız bir sürece izin verilsin */ } void leave_normally(void) /* süreç monitörü herhangi bir işlem yapmadan terk edebilir */ { up(mutex); /* monitöre giriş izni */ } void leave_with_signal(c) /* c üzerinde SIGNAL işlemi gerçeklendi ve süreç monitörü terk etti */ semaphore c; /* üzerinde işlem yapılacak durum değişkenine karşılık bir semafor */ { up(c); /* c üzerinde bekleyen bir süreci uyandir*/ } void wait(c) /* WAIT işlemi */ semaphore c; /* üzerinde işlem yapılacak durum değişkeni */ { up(mutex); /* başka süreçlerin mönitöre girişine izin ver */ down(c); /* beklemede olan bir süreç uyandırıldı, sayacı azalt */ }
Kod incelendiğinde herbir semafor için mutex isimli bir semafor kullanıldığı görülmektedir. Bu semafor, başlangıç değeri 1 olarak atanan ve monitör yapısı üzerinde karşılıklı dışlamayı gerçekleyecek olan semafordur. Kodun ilerleyen satırlarında wait ve leave_with_signal prosedürlerinde ikinci bir semaforun tanimlandığı görülmektedir. Bu da monitör yapısındaki durum değişkenine karşılık gelmektedir. Her bir durum değişkeni için bir semafor tanımlanabilir. Süreçlerin monitör yapısı üzerindeki WAIT ve SIGNAL işlemleri bu semaforlar üzerinde gerçeklenecektir.
Monitör yapısını hatırlarsak, bir süreç monitöre girmekte, monitörün durum değişkenlerinin biri üzerinde WAIT veya SIGNAL işlemi yapmakta, SIGNAL işleminden sonra da monitörü terk etmekteydi.
Sürecin monitör veri yapısını kullanmaya başlaması enter_monitör prosedürü ile gerçeklenmektedir. Bu prosedürde sadece mutex semaforu üzerinde DOWN işlemi yapılmaktadır. Başlangıç değeri 1 olan mutex, işlem sonunda 0 değerine sahip olur. Böylece, başka bir süreç, monitör veri yapısını kullanmak için enter_monitör prosedürünü çağırdığında, mutex üzerinde DOWN işlemi gerçeklenmek istenecek, değerin 0 olduğu görülünce süreç beklemeye alınacaktır.
Süreç monitöre girdikten ve onu kullanmaya başladıktan sonra herhangi bir işlem yapmadan onu terkedebilir. leave_normally prosedürü ile mutex üzerinde UP işlemi yapılarak, değeri 1 yapılır ve monitör yapısı diğer süreçler tarafından kullanıma açılmış olur.
Süreçlerin monitör veri yapısı üzerinde gerçekleştirebildiği WAIT ve SIGNAL işlemleri de ayrı birer prosedür olarak yazılmıştır. WAIT işleminde süreç beklemeye alınacağından, monitörü kullanmak isteyebilecek diğer süreçlere kullanım izin verilmesi için mutex degeri UP işlemiyle 1 yapılmaktadır, böylece enter_monitor prosedürünü kullanıp monitörü kullanmak isteyen süreç bunu başarabilir. Sürecin beklemeye alınması ise monitörün durum değişkenini temsil eden bir semafor (ki burada c) üzerinde yapılacak DOWN işlemiyle gerçeklenmektedir. Bu, sayisal olarak c eğerini 1 azaltan ve anlamsal olarak da bize c üzerinde bir sürecin beklemeye gectiğini belirten bir işlemdir.
SIGNAL, monitördeki son işlem olarak tanımlanması gereken bir işlemdi. SIGNAL'den sonra monitör süreç monitörü terk etmeli, bu terk edişten önce de uyku durumundaki süreçlerden birini uyandırmalıydı. leave_with_signal ile bu sağlanmıştır.
Mizansen:
A, B, C gibi üç sürecimiz olsun. A monitöre girsin ve bekleme durumuna geçsin. Öyleyse A önce enter_monitor ile mutex değerinin 0 olmasına sonra da wait cağrısında aynı semafor üzerinde UP işlemi yapacağından 1 olmasına sebep olacaktır. Ayrıca durum değişkeni olarak her semafor için oluşturulmuş semaforlardan biri olan c üzerinde beklemeye geçtiğini gösteren DOWN işlemi de yapacaktır.
B, bu andan sonra monitöre girip A'yı uyandırsın. Mönitöre girdiği anda mutex değeri 0 olur. Tam bu anda C monitöre girmek istese değeri sıfır olan mutex üzerinde DOWN işlemi yapamayacağından ya da sayısal bir işlem yapamayacağından bekleme kuyruğuna alınacaktır. B'nin A'yı uyandırması leave_with_signal ile gerçeklenmektedir ve sadece c değeri üzerindeki UP işleminden ibarettir. mutex üzerinde bir değişiklik yapılmaması da, A uyandıktan sonra monitör içinde aktif olacağından, başka bir sürece giriş izni verilmemesi için gereklidir.
Şimdi de mesaj iletiminin semaforlarla nasıl olduğuna bakalım.
Tek yapılması gereken mesaj iletiminde kullanılan iki sistem çağrısının semaforlarla ifade edilmesidir. Yazıldığından kadar az gereksinime sahip olmayan bu tanımlamada her bir süreç için ayrı bir semafor değeri kullanılır. Başlangıç değeri 0 olan bu semaforlar, SEND ve RECEIVE işlemleri bitene kadar diğer işlemlerin bekletilmesini sağlar. Süreçler arası iletişimde kullanılacak ileti kutusuları (mailbox) ise paylaşılan bir bellek alanında tutulacak ve aslında içlerinde mesaj girdilerini(slot) barındıracak olan birer dizi yapısı olacaktır. Mesaj girdileri aslında bağlı liste yapısıdır, böylece mesajların alındıkları sırada dağıtılması sağlanır.
İleti kutularında ayrıca şu bilgiler de kayıtlıdır:
Kuyruklarda sadece süreç numaraları vardır. Gerekli olan kuyruk üzerinde UP işlemi yapılarak süreç uyandırılabilir.
Tüm ileti kutularının bulunduğu paylaşılan bellek alanına erişim tek bir semafor ile sağlanır. Bu semafor ikilik bir semafordur.
Mesaj iletiminin semaforlarla gösterimi için kullanılan paylaşılan bellek
Bir süreç herhangi bir SEND veya RECEIVE işlemi gerçekleştirmeden önce, mutex semaforu üzerinde DOWN işlemi yapacak, SEND için en az bir boş slot, RECEIVE icin de doluluk kontrolü yapacaktır. İşlemi gerçekleştirme anında da mesajı bağlı liste kuyruğuna yazacak veya oradan çekecek, bunu yapınca da boş slot ve dolu slot değerlerini de güncelleyecektir.
RECEIVE işlemi boş bir ileti kutusunda gerçekleştirildiğinde, mesajı kabul etmeye çalışan süreç kendini alıcı kuyruğuna koyacaktır. Daha sonra da işleme başladan önce DOWN yaparak sıfırladığı mutex semaforunu UP işlemiyle 1 yapacak, kendisini beklemeye aldığı için başka bir sürecin kendisini uyandırmasına olanak sağlayacaktır. Aynı zamanda beklemede olduğunu belirtmek için de üzerinde işlem yaptığı ayrık olarak tanımlanan semafor üzerinde de DOWN işlemi yapacaktır.
SEND işlemi yapıldığında, eğer hedef ileti kutusunda yer varsa, mesaj gerekli yere yerleştirilir. Gönderici süreç, hedef sürecin ileti kutusundaki alıcı kuyruğunda beklemede süreç var mı diye bakar. Eğer varsa, sıradakini, kuyruktan çeker, onun semaforu üzerinde UP işlemi yaparak uyandırır. Bu anda paylaşılan bellekte aktif iki süreç olmasını önlemek için de paylaşılan belleği terk etmesi gerekmektedir. Monitör yapısındaki uygulamaya benzer olarak WAKEUP işlemi de kritik bölgeyi terk ederken bir süreçte göreceğimiz son adım olacaktır.
II) Semafor ve Mesaj İletiminin Monitör Kullanılarak İfadesi
Monitörlerin daha yüksek bir yapıya sahip olmasından, benzer fakat daha basit bir metod kullanılacaktır. Semaforlar için bir sayaç, her bir semafor için bir bağlı liste ve her bir süreç için de bir durum değişkenine ihtiyaç vardır. DOWN işleminde karşılıklı dışlamayı kontrol edecek olan sayaç değeri kontrol edilecek, sıfırdan büyükse değerini bir azaltacak ve mönitör terk edilecektir. Sıfırsa, bağlı listeye yeni bir süreç numarası girişi olacak ve durum değişkeni üzerinde de WAIT işlemi gerçeklenecektir.
UP işleminde ise, üzerinde işlem yapılacak semafor değeri UP işlemiyle 1 arttırılacaktır. Bu işlemi gerçekleştiren süreç, bağlı listede herhangi bir süreç numarası (id) var mı diye kontrol edecek, varsa bu kaydı listeden çekecek ve semfor üzerinde SIGNAL işlemi yapacaktır.
Mesaj iletiminin monitörlerle gösterimi semaforlara benzemektedir. Her bir süreç için kullanılan semaforlar yerine durum değişkenleri kullanılır. İleti kutusu yapısı da semaforlarla monitor gerceklenmesinde bahsedilen yapiyla aynidir.
III) Semafor ve Monitörlerin Mesaj İletimi Kullanılarak İfadesi
Eğer bir mesaj sistemi varsa, semafor ve monitörlerin ifadesi ufak bir hileyle mümkündür. Burada kullanılacak olan yardımcı oyuncumuz ise eşleme süreci(synchronization process)dir.ref[7]
Eşleme süreci bir sayaç ve beklemedeki her bir semafor için beklemedeki süreçleri içeren bir bağlı listeyi barındırır. UP ve DOWN işlemleri için uygun kütüphaneler çağrılır ve eşleme sürecine istenilen işlemin mesajı ve kullanılacak olan semaforun bilgisi mesajlanır. Daha sonra kütüphane süreci, eşleme sürecinden bir yanıt almak için RECEIVE sistem çağrısını kullanır.
Mesaj geldiğinde, eşleme süreci sayacın değerine bakarak, istenen işlemin gerçekleştirilip gerçekleştirilemeyeceğine karar verir. UP işlemleri her zaman gerçeklenebilirken, DOWN işlemi semafor değeri sıfırsa bloklanır. Eğer DOWN işlemi gerçekleştirilebilecekse, eşleme süresi boş bir mesaj geri göndererek mesajı gönderen sürecin bloke olmasını önler.Eğer işlem DOWN işlemi ve semafor değeri sıfırsa, eşleme süreci istekte bulunan süreci kuyruğa yazar ve bir yanıt göndermez. Sonuçta DOWN işlemi yapmaya çalışan süreç bloklanır, dana sonra bir UP işlemi olduğunda eşleme süreci kuyruktan bloklanmış bir süreci çeker ve bir yanıt gönderir. Tüm bu işlemlerde yarış durumundan kaçılmış olur çünkü eşleme süreci bir kerede sadece tek bir istekle ilgilenmektedir.
Monitörler de benzer yöntemle ifade edilebilir. Monitörlerin semaforlar ile, semaforların da mesaj iletimi ile nasıl gösterileceğinden bahsettik. Bu ikisi kullanılarak monitörlerin mesaj iletimi ile gösterimi sağlanabilir. Bunu gerçekleştirme yollarından biri, derleyici tarafından bilinen, yukarıda da bahsi geçen up ve down işlemlerini yapan bir kütüphane süreci kullanmaktır. Bu işlemler mutex gibi bir ikilik semafor ve her bir süreç için tanımlanmış semforlar üzerinde gerçekleşecek, daha sonra da yapılan işlemler eşleme sürecine mesaj ile gönderilecektir.
REFERANSLAR
Oğuz Y., Çanakkale 18 Mart Üniversitesi Bilgisayar Mühendisliği, 2. sınıf, 29.03.2005
iletisim: 030401006 at students dot comu dot edu dot tr (okul için)
comp dot ogz at gmail dot com (genel)