Senkron IO

Senkron Blocking

IO işlemlerinde ilk seçeneğimiz senkron - Blocking IO modelidir. Bu modelde bir process IO talebinde bulunduğunda, işlem tamamlanana kadar ilgili process bloklanır. Linux çekirdeği bu durumda IO bekleme sürecinde bloklanan process'den CPU kaynağını geri alarak, uygun başka bir process'e tahsis eder. IO işlemi tamamlana kadar IO Wait durumunda bloklanan process'e bir daha asla CPU kaynağı tahsis edilmez. Böylelikle IO beklemelerinin sistemin geri kalanına etkisi minimum olur.

Senkron IO - Blocking

Tipik bir örnek verecek olursak, bir process read() fonksiyonuyla sistemden veri talebinde bulunduğunda ilgili sistem çağrısıyla kullanıcı kipinden kernel kipine context switch gerçekleştirilir ve sistem çağrısı tamamlanana kadar bloklanır. Çağrı tamamlandığında (okunan veri kullanıcı kipinde erişilebilecek bir tampona kopyalandığında veya herhangi bir hata oluştuğunda) ilgili process çalışmaya kaldığı yerden devam eder.

Bu geleneksel modelde her tür IO işlemi uygulamayı blokladığından, aynı anda uygulamada farklı işlemlerin yapılması gerekiyorsa thread kullanımı gerekecektir. Örnek olarak aynı anda 2 seri portu ve 20 farklı TCP soketini dinleyen bir uygulama yapmak istiyorsak, sadece IO işlemleri için toplamda 22 farklı thread kullanmamız gerekecektir. Aksi takdirde herhangi birinde IO nedeniyle karşılaşacağımız bloklanma nedeniyle, diğerlerinde veri gelmiş olsa dahi verinin işlenememesine, dolayısıyla uygulamanın toplamda olması gerekenden yavaş ve verimsiz çalışmasına yol açacaktır.

Senkron Non-Blocking

Senkron IO işleminin diğer bir varyasyonu, Non/Blocking IO modelidir.

Bu modelde IO işlemi yapılacak aygıt O_NONBLOCK bayrağı ile Non/Blocking modda açılır. IO kaynağı bu durumda iken herhangi bir read() işlemi yapıldığında bloklanmak yerine, verinin varsa hazır olan kısmı kernel kipininden kullanıcı kipindeki tampon alanına kopyalanır, veri henüz hazır değilse EWOULDBLOCK hatası döner, sistem çağrısı başka bir sinyal vb. yüzünden kesintiye uğramışsa da standart EAGAIN hatası ile döner. Böylelikle her halikarda bloklanmaksızın read() işlemi gerçeklenmiş olur.

Senkron IO - Non/Blocking

Non/Blocking IO modelinde ihtiyaç duyduğumuz veriye tek seferde ulaşamayız. Bloklanmıyor olmanın negatif yönü, parça parça elde edeceğimiz verileri bir döngü ile tamamlanana kadar okumak zorunda oluşumuzdur. Bu aynı zamanda kod karmaşıklığını da artıracaktır. Ancak bloklanılmadığı için, verinin tamamını okumak amacıyla kurulan döngüde sadece okuma işlemi değil, diğer başka kontrol ve işlemlerin de yapılması mümkün olacaktır.

Benzer bir süreç yazma write() fonksiyonları için de geçerlidir.

Bu modelin asıl dezavantajı kod karmaşıklığını artırmasından ziyade, daha fazla sistem çağrısı gerektiriyor olmasıdır. Aynı işlem bloklanan bir modelde olsa idi tek bir sistem çağrısı ile yapılabilecekken, Non/Blocking IO modelinde bir döngü içerisinde tamamlana kadar, belirsiz sayıda sistem çağrısı yapılmak zorunda kalınmaktadır. Sistem çağrılarının genel maliyeti ve kullanıcı kipi -> kernel kipi context switch'lerinin sürekli yapılıyor olması sistem performansını önemli ölçüde düşürecektir.

Non/Blocking IO modu standart dosyalar üzerinde pek fazla anlam taşımaz. Asıl olarak soket işlemleri, FIFO ve pipe kullanımı, terminal, seri port vb. gibi aygıtlardan okuma ve yazmalarda kullanımı anlamlıdır.

Standart bir dosyayı Non/Blocking modda O_NONBLOCK bayrağı ile açsanız dahi, gerçekte değişen hiç bir şey olmaz. Linux tüm bu tarz dosya işlemlerini tampon kullanarak buffered biçimde gerçekleştirir. Herhangi bir yazma işlemi yapıldığında kullanıcı kipinden alınan veri doğrudan depolama birimine yazılmak yerine, kernel tarafından tutulan page cache tablolarına yazılır. Bu şekilde write çağrıları çok daha hızlı dönecektir. Ancak page cache tablolarında yer kalmadığında, yenilerini açmak için yapılan işlemler nedeniyle write() çağrıları uygulamayı bloklar (standart bir dosya Non/Blocking modda açılmış olsa dahi)

Benzer şekilde standart bir dosya bu modda okunmaya çalışıldığında kernel tarafından veriler disk üzerinden page cache içerisine alınır ve buradan kullanıcı kipine kopyalanır. Hatta özellikle sıralı erişim yapılan dosyalarda kernel, uygulama henüz talep etmeden, daha önden giderek o anki dosya ofsetinden ileriye doğru okuma yapıp page cache tabloları içerisine veri okumaya devam eder. Bu işlem read-ahead modu olarak da adlandırılır. Böylece uygulama katmanında sonradan yapılacak read() işlemleri doğrudan page cache içerisinden karşılanabilmektedir. İstenen verinin cache'te olmaması durumunda verinin diskten okunup getirilmesi için gereken süre zarfında read() fonksiyonu da bloklanacaktır.

Not: 2014 Eylül'ünde Milosz Tanski tarafından hazırlanan bir patch ile readv2() sistem çağrısının O_NONBLOCK bayrağı ile standart dosyalar üzerinde de tam bir Non/Blocking çalışma desteği sunulmaya başlanmıştır. Detaylı testler sonrası ileride güvenle kullanılabilir hale geleceği öngörülmektedir. http://lwn.net/Articles/612483 adresinden ek bilgilere ulaşabilirsiniz.

results matching ""

    No results matching ""