Interrupt öğesinin
hardware signal assertion işlemci pimine neden oldu. Ama Linux işletim sisteminin bunu nasıl ele aldığını bilmek istiyorum.
Bir kesinti meydana geldiğinde ne olur?
İşte düşük seviyeli işlemenin üst düzey görünümü. Basit bir tipik mimariyi tanımlıyorum, gerçek mimariler daha karmaşık olabilir veya bu ayrıntı düzeyinde önemli olmayan şekillerde farklılık gösterebilir.
interrupt oluştuğunda, işlemci kesintilerin maskelenip maskelenmediğine bakar. Eğer öyleyse, maskeleri kaldırılana kadar hiçbir şey olmaz. Kesmeler maskesiz hale geldiğinde, beklemede herhangi bir kesinti varsa, işlemci bir tane alır.
Daha sonra işlemci, bellekteki belirli bir adrese dallayarak kesmeyi gerçekleştirir. Bu adresteki koda kesme işleyici denir. İşlemci orada dallandığında, kesmeleri maskeler (böylece kesme işleyicisi özel kontrole sahiptir) ve bazı kayıtların içeriğini bir yerde (genellikle diğer kayıtlar) kaydeder.
Kesme işleyicisi, tipik olarak veri göndermek veya almak için kesmeyi tetikleyen çevre birimiyle iletişim kurarak yapması gerekenleri yapar. Kesme zamanlayıcı tarafından yükseltildiyse, işleyici farklı bir iş parçacığına geçmek için OS zamanlayıcısını tetikleyebilir. İşleyici yürütmeyi bitirdiğinde, kaydedilen kayıtları geri yükleyen ve kesintileri kaldıran özel bir kesme-kesme komutu yürütür.
Kesme işleyicisi hızlı bir şekilde çalışmalıdır, çünkü başka bir kesmenin çalışmasını engeller. Linux çekirdeğinde, kesme işlemi iki bölüme ayrılır:
Gilles zaten açıklanan bir kesinti genel durumu, aşağıdakiler özellikle bir Intel mimarisi üzerinde Linux 2.6 için geçerlidir (bunun bir kısmı Intel'in özelliklerine dayanmaktadır).
Kesme işlemi, işlemci tarafından yürütülen talimatların sırasını değiştiren bir olaydır.
İki farklı tür kesinti vardır:
İstisnalar, çekirdek tarafından işlenmesi gereken programlama hataları (fe Bölme hatası, Sayfa Hatası, Taşma) . Programa bir sinyal gönderir ve hatadan kurtulmaya çalışır.
Aşağıdaki iki istisna sınıflandırılmıştır:
Kesmeler G/Ç aygıtları (klavye, ağ adaptörü, ..), aralık zamanlayıcıları ve (çok işlemcili sistemlerde) diğer CPU'lar tarafından verilebilir. Bir kesme meydana geldiğinde, CPU mevcut talimatını durdurmalı ve yeni gelen kesme işlemini yürütmelidir. Kesinti ele alındıktan sonra (muhtemelen) devam ettirmek için eski kesilen işlem durumunu kaydetmesi gerekir.
Kesmeleri ele almak hassas bir iştir:
İki farklı kesme seviyesi tanımlanmıştır:
Her donanım aygıtının kendi Kesme İsteği (IRQ) hattı vardır. IRQ'lar 0'dan başlayarak numaralandırılır. Tüm IRQ hatları Programlanabilir Kesme Kontrolörüne (PIC) bağlanır. PIC, IRQ'ları dinler ve CPU'ya atar. Belirli bir IRQ hattını devre dışı bırakmak da mümkündür.
Modern çok işlemli Linux sistemleri genellikle IRQ isteklerini CPU'lar arasında eşit olarak dağıtan daha yeni Gelişmiş PIC'yi (APIC) içerir.
Bir kesme veya istisna ile işlenmesi arasındaki orta adım, Kesme Tanımlayıcı Tablosudur (IDT). Bu tablo, her kesme veya özel durum vektörünü (bir sayı) belirtilen bir işleyiciyle ilişkilendirir (örn. Bölme hatası
divide_error() işlevi tarafından işlenir.
IDT aracılığıyla çekirdek, meydana gelen kesme veya istisnayı tam olarak nasıl ele alacağını bilir.
Peki, bir kesinti meydana geldiğinde çekirdek ne yapar?
İlk olarak kesme işlemiyle uğraşan katılımcılar, çevresel donanım aygıtları, kesme denetleyicisi, CPU, işletim sistemi çekirdeği ve sürücülerdir. Kesme donanımından çevrebirim aygıtları sorumludur. İşletim sistemi çekirdeğinden dikkat çekmek istediklerinde kesme istek satırlarını kullanırlar. Bu sinyaller, kesinti sinyallerinin toplanmasından sorumlu olan kesinti kontrolörü ile çoklanır. Ayrıca kesme sinyallerinin CPU'ya geçme sırasının belirlenmesinden de sorumludur. Kesme denetleyicisi, belirli kesme isteği satırını (IRQL) geçici olarak devre dışı bırakabilir ve yeniden etkinleştirebilir (IRQL maskeleme). Kesme kontrolörü toplanan kesme isteklerini sırayla CPU'ya aktarır. Her komutun yürütülmesi tamamlandıktan sonra CPU, kesme denetleyicisinden bekleyen herhangi bir kesinti isteği olup olmadığını kontrol eder. CPU, dahili CPU kontrol kaydında bekleme isteği VE Kesinti Etkinleştir bayrağı ayarlandığını tespit ederse, CPU kesme işlemine başlar. Gördüğünüz gibi, CPU'daki Kesme bayrağını manipüle ederek ve kesme kontrolörü ile iletişim kurarak, Linux çekirdeği kesme kabulünü kontrol edebilir. Örneğin, Linux belirli bir aygıttan kesintilerin kabulünü devre dışı bırakabilir veya kesinti kabulünü devre dışı bırakabilir.
İşlemci bir kesme isteği aldığında ne olur? İlk olarak, CPU Kesinti Bayrağını sıfırlayarak kesintileri otomatik olarak devre dışı bırakır. Kesme işlemi tamamlandığında bunlar yeniden etkinleştirilir. Aynı zamanda CPU, kesilen kodun yürütülmesine devam etmesini sağlayacak şekilde CPU'yu kullanıcı modundan çekirdek moduna geçirmek için minimum miktarda çalışma yapar. CPU, kontrolün geçirileceği kodun adresini bulmak için Linux çekirdeği tarafından doldurulmuş özel CPU kontrol yapılarına danışır. Bu adres, Linux çekirdeğinin bir parçası olan ilk kesme işleyici talimatının adresidir.
Kesme işleme çekirdeğinin ilk adımı olarak, sistemde ne tür bir olay olduğunu belirlemek için alınan kesme vektörünü tanımlar. Kesme vektörü, Linux'un bununla başa çıkmak için hangi eylemleri gerçekleştireceğini tanımlar. İkinci adım olarak Linux geri kalan program tarafından potansiyel olarak kullanılabilen (CPU tarafından otomatik olarak kaydedilmeyen) diğer CPU kayıtlarını kaydeder. Bu çok önemli bir eylemdir, çünkü Linux'un kesintiye uğramış programa göre kesintileri şeffaf bir şekilde ele almasına izin verir. Üçüncü adım olarak, Linux, çekirdek ortamını ayarlayarak ve bunun için gereken CPU durumunu ayarlayarak çekirdek moduna geçmeyi başarır. Ve son olarak, vektöre bağlı kesme işleyici denir. (X86 mimarisiyle ilgili örnek için ek ayrıntıları almak üzere Arch\x86\kernel\entry_32.S'de BUILD_INTERRUPT3 makrosuna bakabilirsiniz.) Çevre aygıtları için bu bir do_IRQ () rutini. (Arch\x86\kernel\irq.c dosyasına bakın)
Vektör bağımlı kesme işleyicisi genellikle irq_enter () ve irq_exit () çağrılarıyla sarılır. Bu fonksiyonların bir çifti içinde bulunan kod alanı, bu tür diğer alanlara göre atomiktir ve ayrıca cli/sti çiftlerine göre atomiktir. Irq_enter () ve irq_exit () de kesme işlemi ile ilgili bazı istatistikleri yakalar. Son olarak, çekirdek, alınan kesmenin vektörüne atanan irq numarasını bulmak için vector_irq tablosuna bakar ve handle_irq () öğesini (Arch\x86\kernel\irq_32.c'den) çağırır.
Bu noktada Linux'ta kesme işleminin ortak kısmı sona erer, çünkü çekirdek irq tanımlayıcısının bir parçası olarak aygıt sürücüsü tarafından yüklenen cihaza bağlı kesme işleyici rutinine bakar ve onu çağırır. Bu tür bir işleyici sürücü tarafından yüklenmemişse, çekirdek yalnızca kesme denetleyicisindeki kesmeyi onaylar ve genel kesme işleyicisinden çıkar.
Kesme işleme çekirdeği bittikten sonra, önceden kesilmiş olan programın durumunu geri yükler ve bu programın yürütülmesini sürdürür.
Teori açısından, neredeyse her şey açıklanmıştır. Ancak, çekirdek kesme işleme kodu çerçevesi hakkında açıklama arıyorsanız, aşağıdaki bağlantıyı yapmalısınız: Çekirdek kesme işleme içinde bir kod yürüyüşü
Ve hala kesme ve kesme işleyicileri hakkında teori arıyorsanız, o zaman bunu okumanızı öneririz: Kesme ve kesme işleyicilerini anlama