Bütünsel Bağlam Denetimi
Önceki XXIII. Oylum - Yerel Olmayan Çıkışlar Sonraki
Bütünsel Bağlam Denetimi
İçindekiler
1. SVID Bağlam Denetimi Örneği
Unix standardında var olan, yürütme yolunu denetleyen bir diğer işlev grubu. Bu işlevler bu bölümde buraya kadar anlatılanlardan daha güçlü olup en baştan beri System V API içinde bulunmaktadırlar ve buradan Unix API'sine aktarılmışlardır. Markalı Unix gerçekleştirimleri dışında bu arabirimlere fazla rastlanmaz. GNU C'nin bulunduğu bütün platformlar ve mimarilerde de yer almazlar. Var olup olmadıklarını configure kullanarak anlayabilirsiniz.
longjmp işlevinin durumunu içeren değişkenler için kullanılan jmp_buf ve sigjmp_buf türlerine benzer şekilde, burada anlatılacak olan arabirimler için de uygun türler tanımlanmıştır. Bu türteki nesneler daha fazla bilgi içerdiklerinden dolayı daha büyüktürler. Bu tür ileride göreceğimiz birkaç yerde daha kullanılmıştır. Bu bölümde anlatılan veri türleri ve işlevlerin tümü ucontext.h başlık dosyasında tanımlanmış ve bildirilmiştir.
ucontext_t
veri türü
ucontext_t yapısı en azından aşağıdaki üyeleri içermelidir:
ucontext_t *uc_link
Sonraki bağlam yapısına göstericidir. Eğer mevcut yapıda tanımlanan bağlamdan çıkılmışsa kullanılır.
sigset_t uc_sigmask
Bu bağlam kullanıldığında engellenen sinyalleri içerir.
stack_t uc_stack
Bu bağlam için kullanılan yığıt. Değeri bir yığıt göstericisi olmak zorunda değildir ve normalde de değildir. Bkz. Sinyal Yığıtı.
mcontext_t uc_mcontext
Bu üye sürecin mevcut durumunu içerir. mcontext_t türü de bu başlıkta tanımlanır fakat bu tanımın geçirimsiz olduğu düşünülmelidir. Bu tür bilinerek geliştirilmiş uygulamaların taşınırlığı daha düşüktür.
Bu türden nesneler kullanıcı tarafından oluşturulmalıdır. İlklendirme ve değişiklik işlemleri için aşağıdaki işlevlerden biri kullanılır:
int getcontext
(ucontext_t *bağlam)
işlev
getcontext işlevi, kendisini çağıran evre bağlamında bağlam ile gösterilen nesneyi ilklendirir. Buradaki bağlam, yazmaçlar, sinyal maskesi ve mevcut yığıta ait içerikleri barındırır. İçeriklerin icrası getcontext çağrısı döndüğü anda başlar.
İşlev eğer başarılıysa 0 değerini döndürür. Değilse -1 döndürür ve errno'ya uygun değeri atar.
getcontext işlevi setjmp'a benzer ancak işlevin ilk kez mi döndüğü yoksa ilklendirilmiş bağlam kullanılıp yürütmeye o noktadan mı geri dönüldüğü konusunda bilgi vermez. Eğer bu ayrımın yapılması gerekliyse, bunu kullanıcı kendisi ortaya çıkarmalıdır. Ancak bunu dikkatlice yapmak gerekir çünkü bağlam içerisinde yazmaç değişkenlerini içeren yazmaçlar bulunabilir. Bu durumda değişkenleri volatile olarak tanımlamak iyi olur.
bağlam nesnesine bir kez ilk değer atandıktan sonra ya olduğu gibi ya da değiştirilerek kullanılır. Değiştirme normal olarak eş-yordamları veya benzeri yapıları gerçekleştirmek için yapılır. makecontext bunu yapmak kullanılır.
void makecontext
(ucontext_t *bağlam,
 void      (*işlev) (void),
 int         argc,
 …)
işlev
İşleve aktarılan bağlam parametresi getcontext tarafından ilklendirilmiş olmalıdır. Sonuçta elde edilen bağlama geri dönüldüğünde yapılan ilk işlem, argc tane tamsayı argüman ile işlev işlevinin çağrılmasıdır. makecontext çağrısında tamsayı argümanlar argc parametresinden sonra verilmelidir.
Bu işlev çağrılmadan önce bağlam yapısına ait uc_stack ve uc_link üyeleri ilklendirilmelidir. uc_link üyesi bu bağlam için kullanılan yığıtı tanımlar. Aynı anda kullanılan bağlamların her biri yığıt için ayrı bellek bölgeleri kullanmalıdır.
bağlam'ın gösterdiği nesnenin uc_link üyesi, işlev işlevinin geri dönüş noktasında yürütülecek bağlamı göstermeli veya bir boş gösterici olmalıdır. Kullanımı hakkında daha fazla bilgi için setcontext'e bakınız.
Yığıt için bellek ayırırken dikkatli olunmalıdır. Günümüzde işlemcilerin çoğunluğu bir bellek bölgesinin çalıştırılabilir kod içerip içeremeyeceği konusunda ayrım yapar. Veri bölütleri ve özdevimli ayırma yapılan bellekte bu tür bir yaftalama yoktur. Sonuçta yazılımlar başarısız olur. Bu tür çalıştırılabilir koda bir örnek, iç içe işlev çağrıları için GNU C derleyicisinin ürettiği çağrı dizilimleridir. Yığıtlar için güvenli bir şekilde bellek ayırmak için örneğin özgün evre yığıtı üzerindeki bellek kullanılabilir veya çalıştırılmaya uygun şekilde yaftalanmış bir bellek bölgesi ayırılabilir (bkz. Bellek Eşlemli G/Ç).
Uyumluluk Bilgisi
Mevcut Unix standardı yığıt için bellek ayırma konusunda hemen hemen hiç belirleyici değildir. Bütün gerçekleştirimler uc_stack üyesinin kullanımında anlaşmıştır ama stack_t değerinin üyelerinin içerebileceği değerler konusunu açık bırakmıştır. GNU C kütüphanesi ve diğer Unix gerçekleştirimlerinin çoğunluğunda uc_stack üyesinin ss_sp değeri, yığıt için ayrılmış bellek bölgesinin tabanını göstermelir ve ss_size değeri de bu bölgenin büyüklüğünü içermelidir. Bazı gerçekleştirimlerde ise ss_sp değeri yığıt göstericisinin değerini içerir (yığıtın gelişme yönüne göre bu değer farklıdır). Bu farklılık makecontext işlevinin kullanımını zorlaştırır ve derleme sırasında platformn bilgisinin elde edilip kullanılmasını zorunlu kılar.
int setcontext
(const ucontext_t *bağlam)
işlev
setcontext işlevi, bağlam tarafından tanımlanmış bağlamı yeniden geçerli kılar. Bağlamda değişiklik yapılmaz ve istendiği kadar sık yeniden kullanılabilir.
Eğer bağlam setcontext ile oluşturulmuşsa yürütme sonunda yazmaçlar, setcontext sanki şimdi geri dönüş yapmış gibi aynı değerleri içerir.
Eğer makecontext'in çağrılmasıyla bağlamda değişiklik yapılmışsa makecontext'in çağrıldığı işlevle yürütmeye devam edilir ve bu işleve aynı çağrı sırasında verilen paramatreler aktarılır. Bu işlev geri dönüş yaptığında makecontext çağrılırken verilen bağlam yapısının uc_link üyesi tarafından gösterilen bağlamla yürütmeye devam edilir. Eğer uc_link bir boş gösterici ise, bu durumda uygulama sonlanır.
Bağlam yığıt hakkında bilgi içerdiğinden aynı bağlamı aynı anda iki evre kullanmamalıdır. Aksi takdirde, sonuç çoğu durumda felaket olurdu.
setcontext işlevi bir hata oluşmadıkça dönmeyecekir, hata oluşmuşsa -1 değeri ile döner.
setcontext işlevi mevcut bağlamı basitçe bağlam parametresi ile tanımlayarak değiştirir. Mevcut bağlamın korunmasını gerektiren durumlar da olmasına rağmen bu çoğunlukla kullanışlıdır.
int swapcontext
(ucontext_t *restrict       diğer-bağlam,
 const ucontext_t *restrict bağlam)
işlev
swapcontext işlevi setcontext işlevine benzer, fakat geçerli bağlam olan bağlam bağlamını bir getcontext çağrısından dönmüş olan diğer-bağlam ile değiştirir. swapcontext çağrısında sonra yürütme bu bağlamla devam eder.
Eğer swapcontext başarılıysa işlev dönmez. diğer-bağlam bağlamı evvelki bir makecontext çağrısı ile değişiklik yapılmaksızın kullanışmışsa dönüş değeri 0'dır. Eğer işlev başarısız olmuşsa -1 döner ve errno değişkenine hata durumu atanır.
Önceki Üst Ana Başlık Sonraki
Yerel Olmayan Çıkışlarda Sinyaller Başlangıç SVID Bağlam Denetimi Örneği
Bir Linux Kitaplığı Sayfası