Olay döngüsü - Event loop

Gelen bilgisayar bilimleri , olay döngü bir programlama yapısı ya da tasarım deseni olduğunu bekler ve gönderir olaylar veya mesajları bir de programın . Olay döngüsü, bazı dahili veya harici "olay sağlayıcılara" (genellikle bir olay gelene kadar isteği bloke eder) bir istekte bulunarak çalışır , ardından ilgili olay işleyicisini çağırır ("olayın gönderir"). Olay döngüsüne bazen mesaj gönderici , mesaj döngüsü , mesaj pompası veya çalıştırma döngüsü de denir .

Olay sağlayıcı , seçilebilen veya 'yoklanabilen' (gerçek yoklama değil Unix sistem çağrısı ) dosya arayüzünü takip ederse, olay döngüsü bir reaktör ile birlikte kullanılabilir . Olay döngüsü hemen hemen her zaman iletiyi oluşturan ile eşzamansız olarak çalışır.

Olay döngüsü , sıklıkla olduğu gibi, bir programın merkezi kontrol akış yapısını oluşturduğunda, ana döngü veya ana olay döngüsü olarak adlandırılabilir . Bu başlık uygundur, çünkü böyle bir olay döngüsü program içindeki en yüksek kontrol seviyesindedir.

İleti geçişi

Mesaj pompalarının, programın mesaj kuyruğundan (atanan ve genellikle temel işletim sistemine ait olan) mesajları işlenmek üzere programa 'pompaladığı' söylenir . En katı anlamda, bir olay döngüsü, süreçler arası iletişimi uygulama yöntemlerinden biridir . Aslında, Mach işletim sisteminin çekirdek düzeyinde bir bileşeni de dahil olmak üzere birçok sistemde mesaj işleme vardır . Olay döngüsü, mesaj geçişini kullanan sistemlerin özel bir uygulama tekniğidir .

Alternatif tasarımlar

Bu yaklaşım, bir dizi başka alternatifin aksine:

  • Geleneksel olarak, bir program yalnızca bir kez çalıştırılır ve ardından sonlandırılır. Bu tür bir program, bilgi işlemin ilk günlerinde çok yaygındı ve herhangi bir kullanıcı etkileşiminden yoksundu. Bu, özellikle komut satırına dayalı programlar biçiminde hala sıklıkla kullanılmaktadır . Herhangi bir parametre önceden ayarlanır ve program başladığında tek seferde iletilir.
  • Menü odaklı tasarımlar. Bunlar hala bir ana döngüye sahip olabilir, ancak genellikle olağan anlamda olay odaklı olarak düşünülmez . Bunun yerine, kullanıcıya, gerçekleştirmek istedikleri görev mevcut tek seçenek olana kadar sürekli daralan seçenekler sunulur. Menüler aracılığıyla sınırlı etkileşim mevcuttur.

kullanım

Grafik kullanıcı arayüzlerinin baskınlığı nedeniyle , çoğu modern uygulama bir ana döngüye sahiptir. get_next_message()Rutin, tipik olarak, işletim sistemi tarafından sağlanır ve blok bir mesaj kadar mevcuttur. Böylece döngüye yalnızca işlenecek bir şey olduğunda girilir.

function main
    initialize()
    while message != quit
        message := get_next_message()
        process_message(message)
    end while
end function

Dosya arayüzü

Unix altında , " her şey bir dosyadır " paradigması doğal olarak dosya tabanlı bir olay döngüsüne yol açar. Dosyalardan okuma ve dosyalara yazma, süreçler arası iletişim, ağ iletişimi ve cihaz kontrolünün tümü, bir dosya tanımlayıcı tarafından tanımlanan hedef ile dosya G/Ç kullanılarak gerçekleştirilir . Seçme ve anket sistem çağrıları dosya tanımlayıcıları bir dizi hal değişikliği, örneğin veri okunacak hazır olduğunda için izlenecek izin verir.

Örneğin, sürekli güncellenen bir dosyadan okuyan ve içeriğini bir soket üzerinden istemcilerle iletişim kuran X Pencere Sisteminde görüntüleyen bir program düşünün ( Unix etki alanı veya Berkeley ):

def main():
    file_fd = open("logfile.log")
    x_fd = open_display()
    construct_interface()
    while True:
        rlist, _, _ = select.select([file_fd, x_fd], [], []):
        if file_fd in rlist:
            data = file_fd.read()
            append_to_display(data)
            send_repaint_message()
        if x_fd in rlist:
            process_x_messages()

İşleme sinyalleri

Unix'te dosya arayüzüne uymayan birkaç şeyden biri asenkron olaylardır ( sinyaller ). Sinyaller , görevin geri kalanı askıya alınırken çalışan küçük, sınırlı kod parçaları olan sinyal işleyicilerde alınır; görev bloke edilirken bir sinyal alınır ve işlenirse select(), seçim EINTR ile erken dönecektir ; görev CPU'ya bağlıyken bir sinyal alınırsa, görev, sinyal işleyici dönene kadar talimatlar arasında askıya alınır.

Bu nedenle, sinyalleri işlemenin bariz bir yolu, sinyal işleyicilerin genel bir bayrak ayarlaması ve select()çağrıdan hemen önce ve sonra bayrak için olay döngüsünü kontrol etmesidir; ayarlanmışsa, sinyali dosya tanımlayıcılardaki olaylarla aynı şekilde ele alın. Ne yazık ki, bu bir yarış durumuna yol açar : bayrağın kontrol edilmesi ile çağrı arasında hemen bir sinyal gelirse select(), select()başka bir nedenle (örneğin, sinirli bir kullanıcı tarafından kesintiye uğramak) geri dönene kadar ele alınmayacaktır .

POSIX tarafından ulaşılan çözüm , pselect()çağrıya benzeyen select()ancak sigmaskbir sinyal maskesini tanımlayan ek bir parametre alan çağrıdır . Bu, bir uygulamanın ana görevdeki sinyalleri maskelemesine, ardından select()çağrı süresince maskeyi kaldırmasına, böylece sinyal işleyicilerin yalnızca uygulama G/Ç bağlıyken çağrılmasına olanak tanır . Ancak, uygulamaları pselect()her zaman güvenilir olmamıştır; 2.6.16'dan önceki Linux sürümlerinde bir pselect()sistem çağrısı yoktur, glibc'yi aynı yarış koşuluna eğilimli bir yöntemle taklit etmeye zorlamaktan pselect()kaçınılması amaçlanmıştır.

Alternatif, daha taşınabilir bir çözüm, "bir sinyal işleyicinin diğer ucu ana programda izlenen bir boruya bir bayt yazdığı" self-pipe hilesini kullanarak asenkron olayları dosya tabanlı olaylara dönüştürmektir select(). In Linux çekirdeği sürümü 2.6.22, yeni bir sistem çağrısı signalfd()özel dosya tanımlayıcı üzerinden sinyallerin alınması olanak sağlayan eklendi.

Uygulamalar

Windows uygulamaları

On Microsoft Windows işletim sistemi, bir süreç kullanıcı ile etkileşimde olduğu zorundadır kabul ve neredeyse kaçınılmaz bir yapılır, gelen mesajlar, tepki mesajı döngü bu süreçte. Windows'ta bir mesaj, oluşturulan ve işletim sistemine empoze edilen bir olaya eşittir. Bir olay, diğerleri arasında kullanıcı etkileşimi, ağ trafiği, sistem işleme, zamanlayıcı etkinliği, süreçler arası iletişim olabilir. Etkileşimli olmayan, yalnızca G/Ç olayları için Windows, G/Ç tamamlama bağlantı noktalarına sahiptir . G/Ç tamamlama bağlantı noktası döngüleri, Mesaj döngüsünden ayrı olarak çalışır ve kutudan çıktığı haliyle Mesaj döngüsüyle etkileşime girmez.

En "kalp" Win32 uygulamaları olan WinMain () çağırır fonksiyonu, () getMessage bir döngüde. GetMessage(), bir mesaj veya "olay" alınana kadar engeller ( engellemeyen bir alternatif olarak PeekMessage() işleviyle ). İsteğe bağlı bazı işlemlerden sonra , mesajı WindowProc olarak da bilinen ilgili işleyiciye gönderen DispatchMessage() öğesini çağırır . Normalde, özel WindowProc() içermeyen mesajlar , varsayılan olan DefWindowProc'a gönderilir . DispatchMessage() , iletinin HWND tanıtıcısının WindowProc'unu çağırır ( RegisterClass() işleviyle kayıtlı ).

Mesaj siparişi

Microsoft Windows'un daha yeni sürümleri, programcıya, mesajların sistem ve çevre birimleri tarafından algılandıkları sırayla bir uygulamanın mesaj döngüsüne teslim edileceğini garanti eder. Bu garanti, çok iş parçacıklı uygulamaların tasarım sonuçları düşünüldüğünde çok önemlidir .

Ancak bazı iletilerin, her zaman en son alınan iletiler veya farklı belgelenmiş önceliğe sahip iletiler gibi farklı kuralları vardır.

X Pencere Sistemi

Xlib olay döngüsü

Xlib'i doğrudan kullanan X uygulamaları XNextEvent, işlevler ailesi etrafında oluşturulmuştur ; XNextEventolay kuyruğunda bir olay görünene kadar engeller, bunun üzerine uygulama bunu uygun şekilde işler. Xlib olay döngüsü yalnızca pencere sistemi olaylarını işler; diğer dosyalarda ve aygıtlarda beklemesi gereken uygulamalar gibi ilkel öğelerden kendi olay döngüsünü oluşturabilir ConnectionNumber, ancak pratikte çoklu iş parçacığı kullanma eğilimindedir .

Çok az program Xlib'i doğrudan kullanır. Daha yaygın durumda, Xlib tabanlı GUI araç takımları genellikle olay eklemeyi destekler. Örneğin, dayalı araç setleri Xt intrinsics var XtAppAddInput()ve XtAppAddTimeout().

X uygulaması rastgele bir durumda, örneğin içinde kesintiye uğramış olabileceğinden, bir sinyal işleyiciden Xlib işlevlerini çağırmanın güvenli olmadığını lütfen unutmayın XNextEvent. X11R5, X11R6 ve Xt için bir çözüm için [1]'e bakın .

GLib olay döngüsü

GLib olay döngü orijinal olarak kullanılmak üzere oluşturulmuştur GTK ama şimdi örneğin hem de olmayan GUI uygulamaları, kullanılan D-Bus . Sorgulanan kaynak , uygulamanın ilgilendiği dosya tanımlayıcılarının koleksiyonudur ; yoklama bloğu, bir sinyal geldiğinde veya bir zaman aşımı süresi sona erdiğinde (örneğin, uygulama bir zaman aşımı veya boşta görev belirtmişse) kesintiye uğrayacaktır . GLib, dosya tanımlayıcı ve alt sonlandırma olayları için yerleşik desteğe sahip olsa da, hazırla-kontrol et-gönder modelinde işlenebilecek herhangi bir olay için bir olay kaynağı eklemek mümkündür. [2]

GLib olay döngüsünde oluşturulan uygulama kitaplıkları GStreamer ve GnomeVFS'nin eşzamansız G/Ç yöntemlerini içerir , ancak GTK en görünür istemci kitaplığı olmaya devam eder. Pencereleme sisteminden gelen olaylar ( X'te , X soketini okuyun ) GDK tarafından GTK olaylarına çevrilir ve uygulamanın widget nesnelerinde GLib sinyalleri olarak yayınlanır.

macOS Core Foundation çalıştırma döngüleri

İş parçacığı başına tam olarak bir CFRunLoop'a izin verilir ve isteğe bağlı olarak birçok kaynak ve gözlemci eklenebilir. Kaynaklar daha sonra, kuyruk oluşturma ve mesajların gönderilmesini organize eden çalışma döngüsü aracılığıyla gözlemcilerle iletişim kurar.

CFRunLoop Abstract olan kakao (non bir işlev çağrısına eş herhangi bir mesaj sağlayan bir NSRunLoop olarak yansıtıcı herhangi bir nesneye sevk için sıraya edilecek çalışma zamanları).

Ayrıca bakınız

Referanslar

Dış bağlantılar