Merhaba,
Bu makalemde,özellikle hardware programlama düzeyinde sıklıkla kullandığımız veya kullanmak zorunda olduğumuz 'volatile' anahtar sözcüğüne değineceğim.
Özellikle 'hardware' olarak belirtmemdeki sebep,bu alanda yaşadığım bir deneyim neticesinde konuya bağlı kalmak için belirtiyorum.
Ancak geliştirmekte olduğunuz kod,amacına uygun olarak belli kullanım gereksinimleri doğurur. Dolayısıyla 'hardware' olarak sınırlanamaz.
-volatile nedir ve neden kullanmalıyız?
Bu anahtar kelimeyi tanıtmadan evvel,derleyici bazında kod optimizasyon konusunda biraz bilgi sahibi olmamız gerekir. Bu noktada kullandığımız derleyici ve derleyiciden istediğimiz işlevler önem teşkil etmektedir.
Daha açık olarak: Gelişmiş derleyiciler geliştirici isteği dışında kodların işleyiş mantığına müdahalede bulunur. Buradaki amaç,gereksiz kod boyutundan ve çalışma zamanından feragat etmektir.
Örneğin tanımladığımız bir değişkeni hiçbir yerde kullanmıyorsak bunun uygulama boyutuna gereksiz etkisi vardır. Veya uygulama çalışma esnasında sıkça başvurulan bir alan(değişken,fonksiyon vb) çalışma zamanına olumsuz etki edebilir. Bu noktada derleyici optimizasyon özelliği devreye girer.
Sık sık başvurulan alanların değerleri,daha hızlı erişim amaçlı çeşitli şekillerde saklanarak optimizasyon sağlanılır.
Optimizasyona gerek duyulan örnek:
int c = 0;
for(int i =0; i<100;i++)
{
c = i;
}
Bu kod parçasında 'c' değişkeni tanımlanmış fakat herhangi bir yerde kullanılmamıştır.
Veya aşağıdaki kod parçası önrek verilebilir:
if(false){
printf(".....");
}
Bu kullanımda hiçbir zaman if içerisine girilmeyecektir. Bu durumda uygulama boyutu düşünülerek
optimizasyon uygulanır.
Ancak derleyici tarafından sağlanan optimizasyon özelliğini kullanmak geliştirici insiyatifine verilmiştir. Dolayısıyla geliştirici bu özelliği kullanmak istediğini/istemediğini belirtebilir.
Derleyici optimizasyon özelliğini kullanmak yarar sağlayacağı için önerilir. Fakat optimizasyon durumları bazı istenmeyen sonuçları meydana getirebilir. Bu sonuçlardan biri de sıklıkla başvurulan/çağrılan(değer yazılıp,değer okunan) alanlardır. Bu şekilde kullanımda olan alanlara hızlıca erişim sağlanabilmesi için(çalışma zamanı) değeri genelde cache kısmında saklanır.
Ancak bu işleyiş çok işlemcili cihazlarda istenmeyen durumlar meydana getirebilir.
Örneğin böyle bir alanın işleyişini aynı anda birden fazla işlemci erişmesi(işleme alması) durumunda,
biri nihayi değer yazarken diğeri bu değeri değiştirebilir. Yani birden fazla thread'in aynı anda erişmesi bu durumu yaşatabilir. Böyle bir durumda işlemin sonucu dolayısıyla ilgili alanın değeri değişecektir. Örneğin SD kart okuma esnasında ilgili donanımın hazır olup olmadığını belirleyen kritik değer alanı böyle bir tehdit altında olmamalıdır. Veya bir donanım REG(register) değeri için de aynı durum sözkonusudur. Sonuç itibariyle böyle bir durumun yaşanmaması için ihtimal bırakmamalıyız.Bunun için başvurulacak anahtar kelime 'volatile''dir.
'volatile' olarak tanımlanmış bir alan,derleyici optimizasyon işleminden emin olmak içindir.
Yani derleyici 'volatile' olarak tanımlanmış bir alana optimizasyon işlemi uygulamaz.
Ayrıca,'volatile' tanımlanmış bir alanın değeri "cache" yerine main(ana) memory'e yazılır ve okunur.
Bu alanın değeri 'cache'a yazılıp okunmadığı için yukarıda anlatılan istenmeyen sonuçlara karşı bir miktar garantiye alınmıştır. Ancak bu tanımlama tek başına yeterli değildir.
Örneğin birden fazla Thread 'volatile' bir değişkenin değerini main memory'dan aynı anda işleme alırsa risk meydana gelir.
Bu durumdan tamamen emin olmak için "mutex" ile "lock/unlock"(Cpp için) ile garantiye almalıyız.
Örnek:
#include<mutex>
std::mutex _mutex;
volatile int i;
volatile int REG;
_mutex.lock();//kilitle
for(i =0 ; i<32; i++)
{
REG = i << 10;
REG = ..
REG = ..
}
_mutex.unlock();//kilidi kaldır.
//...
NOT: Bu yazıda Cpp kullanım örneği verilmiştir. Diğer teknolojiler için eşdeğer yöntemler kullanmalısınız.
Örneğin Java için aşağıdaki örnekler verilebilir:
1:
volatile int count = 0;
public synchronized void increment() {
count++;
}
2:
Lock lock = new Lock();
volatile int count = 0;
public int inc(){
lock.lock();
count++;
lock.unlock();
return count;
}
Bu makaleyi hazırlamamın nedeni,embedded linux alanındaki çalışmalarımda karşılaştığım bir "main memory" problemi ve buna getirdiğim çözümü size aktarmaktır.
Kitaplarda ve eğitimlerde "volatile" ve "lock" konuları anlatılır. Ancak genellikle "eşzamanlı main memory erişimi nadir olabilecek(düşük/çok düşük ihtimal) bir durumdur" şeklinde(yaklaşık olarak) açıklar. Risk ihtimali milyarda bir olsa da buna önlem alınmalıdır.
--------------
Hiç yorum yok:
Yorum Gönder