Sinyal İşleme ve Evresel Olmayan İşlevler
Önceki Sinyal Yakalayıcıların Tanımlanması Sonraki
Sinyal İşleme ve Evresel Olmayan İşlevler
Sinyal yakalama işlevleri genelde çok zor değildir. En iyi çözüm, hiçbir şey yapmayan ama yazılımın sürekli sınadığı bir harici değişkene değer atayan ve bu değişkenle ilgili işlemleri yazılıma bırakan bir kod yazmaktır. En iyisi budur çünkü, eylemci işlev rasgele, umulmadık bir zamanda, basit bir işlevin ortasında ve hatta çok sayıda makine kodu komut gerektiren C işleçlerinin başlangıcı ile sonu arasında çağrılabilir. Üzerinde çalışılan veri yapıları eylemci işlevler çağrıldığında kararsız durumda bile olabilirler. Bir int türünden değişkenin diğerine kopyalanması çoğu makinede iki makine komutundan oluşur.
Bu, bir sinyal yakalayıcı ile ne yapmaya hazırlandığınıza bağlı olarak çok dikkatli olmak zorunda olduğunuz anlamına gelir.
  • Eğer eylemci işlevin yazılımınızdan herhangi bir genel değişkene erişmesi gerekiyorsa bu değişkenleri volatile olarak bildirin. Bu, derleyiciye bu değişkenin herhangi bir anda değişebileceğini ve bu tür değişikliklere göre değerlendirilmiş eniyilemelerin yapılmamasını söyler.
  • Eylemci içinden bir işlev çağırıyorsanız, onun sinyallerle ilgili olarak evresel olduğundan, değilse, başka bir ilgili işlev tarafından sinyalin engellenmediğinden emin olmalısınız.
Bir işlev yığıtı değil de belleği kullanıyorsa evresel olmayabilir.
  • Bir işlev bir durağan veya bir genel ya da sadece kendinin erişebildiği bir özdevimli ayrılmış nesne kullanıyorsa, evresel olmayabilir ve işlevin herhangi iki çağrısı bir diğeri ile etkileşebilir.
    Örneğin sinyal yakalayıcının gethostbyname işlevini kullandığını varsayalım. Bu işlev değerini bir durağan nesne içinde döndürür. Eğer gethostbyname çağrısı sırasında ya da çağrının ardından (yazılım hala bu değeri kullanıyorken) bir sinyal gelirse, yazılımın istediği değerin taşmasına sebep olabilir.
    Diğer yandan, yazılım gethostbyname işlevini ya da aynı nesnedeki bilgiyi döndüren herhangi bir başka işlev kullanmıyorsa ya da her kullanımda daima sinyaller engelleniyorsa güvendesiniz demektir.
    Değeri bir sabit nesne içinde döndüren ve bu şekilde aynı nesnenin daima yeniden kullanılabilir olmasını sağlayan çok sayıda kütüphane işlevi vardır ve bunların tamamı aynı soruna yol açabilir. Bu kılavuzdaki işlev açıklamalarında bu davranış daima açıklanmıştır.
  • Eğer bir işlev, sizin tanımladığınız bir nesneyi kullanıyor ve değiştiriyorsa, büyük ihtimalle işlev evresel değildir; bu işlevlerin aynı nesneyi kullanması halinde birbirlerini etkileyebilirler.
    Akımlarla G/Ç işlemleri yaptığınızda bu durum ortaya çıkabilir. Bir sinyal yakalayıcını fprintf işlevi ile bir ileti bastığını varsayalım. Tam da aynı akımı kullanan bir fprintf çağrısının ortasında yazılımın bir sinyal aldığını varsayalım. Hem sinyal eylemcinin hem de yazılımın verisi bozulurdu, çünkü her iki çağrı kendi akımı üzerinde aynı veri yapısıyla çalışıyor olacaklardı.
    Bununla birlikte, eylemcinin kullandığı akımın sinyal geldiğinde yazılım tarafından kullanılması mümkün olmayabilir ki, bu durumda güvendesiniz demektir. Yazılım başka bir akımı kullanıyorsa sorun yoktur.
  • Çoğu sistemde, hangi bellek bloklarının serbest bırakılacağını kaydettikleri bir durağan veri yapısı kullandıklarından malloc ve free evresel değildir. Sonuç olarak, bellek ayıran ve serbest bırakan kütüphane işlevleri evresel olmayacaktır. Bu, bir sonucu saklayacağı alanı ayıran işlevleri de kapsar.
    Bir yakalama işlevi içinde bellek ayırma ihtiyacından kaçınmanın en iyi yolu, işlev için kullanılacak alanı önceden ayırmaktır.
    Bir yakalama işlevi içinde belleği serbest bırakma ihtiyacından kaçınmanın en iyi yolu ise, serbest bırakılacak nesneleri kaydetmek ya da imlemek ve yazılımda zaman zaman bu türde serbest bırakılmayı bekleyen nesneler olup olmadığına bakmaktır. Fakat bu dikkatli yapılmalıdır çünkü bir nesnenin bir zincire yerleştirilmesi atomik değildir ve başka bir sinyal yakalayıcı ile işlem kesmeye uğratılırsa nesnelerden birinin kaybedilmesi gibi şeyler olabilir.
  • errno değişkenini değiştiren işlevler evresel değildir, fakat bunu düzeltebilirsiniz: eylemcide errno değişkeninin orjinal değerini kaydedip normal olarak dönmeden önce eski yerine koyabilirsiniz. Bu, sistemin bir sinyalle tetiklediği eylemcinin çalışmaya başlamasıyla alınması engellenen hataların eylemcinin işi bittiğinde elde edilebilmesini sağlar.
    Bu teknik genellikle uygulanabilirdir; belli bir nesneyi bellekte değiştiren bir işlevi bir sinyal yakalayıcı içinden çağırmak isterseniz, bunu nesneyi kaydederek ve sonra eski değeri yerine koyarak rahatça yapabilirsiniz.
  • Sadece, bir sinyal alındığında bir bellek nesnesinin okunması güvenli olabilir. Ancak, bazı veri türlerinde atama işleminin birden fazla makine komutuna malolduğunu unutmayın, bir sinyal yakalayıcı çalışmaya başladığı anda eğer atomik değilse bir değişkene yapılan atama işleminin arasına girebilir.
  • Bir sinyal alındığında, bir bellek nesnesine yazma işlemi sadece değerin olabildiğince anlık bir değişikliğinde güvenli olabilir. Bu durumda eylemcinin çalışması birşeyi bozmaz.
Önceki Üst Ana Başlık Sonraki
Eylemci Çalışmadan İkinci Bir Sinyalin Alınması Başlangıç Atomik Veri Erişimi ve Sinyal İşleme
Bir Linux Kitaplığı Sayfası