Linux Sistem Programlama
  • Kapak
  • Önsöz
  • Sistem Programlamaya Giriş
    • Tarihçe
    • Standartlar
    • Sistem Çağrıları
    • API ve ABI
  • Linux Çekirdeği
  • Kabuk
  • Dosya Sistemi
  • Kullanıcı, Grup ve Erişim Yetkileri
  • Process Kavramı
  • Dosya İşlemleri
  • IO Modelleri
    • Senkron IO
    • Asenkron IO
  • Sinyaller
    • Temel Kavramlar
    • Sinyal Yakalama ve Gönderme
    • Signal-Safe Kavramı
    • Sinyal Kümeleri
    • Sinyal Bloklama
    • Sinyal İle Birlikte Veri Gönderimi
    • Sinyal ve Core Dump
    • RealTime Sinyaller
    • File Descriptor Üzerinden Sinyal İşleme
    • Genel Değerlendirme
  • Thread Kullanımı
    • Thread Oluşturma
    • Thread Türleri
    • Thread Sonlandırma
    • Mutex Kullanımı
    • SpinLock & Mutex Karşılaştırması
    • Futex
  • Semafor Kullanımı
    • Semafor ve Mutex Karşılaştırması
    • Semafor Türleri
    • Semafor Operasyonları
  • Shared Memory Kullanımı
  • Memory Mapped IO
  • Soket Kullanımı
    • Soket API
    • TCP Soketleri
    • UDP Soketleri
    • UNIX Soketleri
    • Birden Çok İstemciyle Çalışma
  • Timer Kullanımı
    • Basit Timer Yapıları
    • POSIX Timer API
    • Event Loop İçinde Kullanım
  • Daemon Oluşturma
  • Capabilities API
  • Paylaşımlı Kütüphaneler
    • Kütüphane Gereksinimi
    • Statik Kütüphaneler
    • Kod Referanslarının Ele Alınması
    • Paylaşımlı Kütüphanelerin Oluşturulması
    • Dinamik Yükleme
    • Derleme Zamanında Kütüphanelerin Aranması
    • Çalışma Zamanında Kütüphanelerin Aranması
    • Statik ve Dinamik Kütüphanelerin Beraber Kullanılması
    • Versiyon Yönetimi
  • Process'ler Arası Haberleşme
  • Memory Allocation
  • Memory Barriers
  • Hata Ayıklama Yöntemleri
    • GNU Debugger
    • Strace
  • GNU Build Sistemi Araçları
    • Make
    • Autoconf, Automake
  • Ek Bölümler
    • Derleyici Optimizasyonları
    • Clang ve LLVM
    • İçsel ve Anonim Fonksiyonlar
      • İçsel Fonksiyonlar
      • Anonim Fonksiyonlar
    • FreeTDS ile SqlServer Bağlantısı
  • Kaynak Dosyalar
Powered by GitBook
On this page
  • Senkron Blocking
  • Senkron Non-Blocking

Was this helpful?

  1. IO Modelleri

Senkron IO

PreviousIO ModelleriNextAsenkron IO

Last updated 5 years ago

Was this helpful?

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.

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.

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. adresinden ek bilgilere ulaşabilirsiniz.

http://lwn.net/Articles/612483
Senkron IO - Blocking
Senkron IO - Non/Blocking