Linux Üzerinde İnterrupt Handlerlara Kayıt Olma
İşletim sistemini koşturan işlemci üzerinde meydana gelen bir interrupt, işletim sisteminin donanım ile bağlantısını kurar. Aynı şekilde PC sistemlerine bağlı olan tüm donanımların, işletim sisteminde yazılımsal olarak bir karşılığı vardır. Bu yazılımsal karşılık driver olarak adlandırılır ve de işletim sisteminin donanımla haberleşmesini ve kontrol etmesini sağlar.
Interrupt handlerlar, donanımda meydana gelen işlemleri işletim sistemine bildirmek için kullanılırlar. Her donanıma ait bir sürücü her zaman olmada da genellikle işletim sistemi üzerinde tanımlıdır veya yüklüdür. Bu nedenle donanımı kontrol etmek için gereken tüm driverler de işletim sistemi ile birlikte yüklenir. Bu linux kernelinde driver modülü olarak adlandırılır ve genellikle C dili ile yazılır.
İlgili interrupt handler fonksiyonunu işlemek, tamamiyle o donanımı kontrol eden yazılımın sorumluluğudur. Bu yazılım ise modül olarak adlandırılır ve Linux çekirdeği modüler bir yapıya sahiptir. Bu şekilde işlemciye gelen interruptlar işlenerek yazılımcının driveri geliştirmesi için kullanılır.
Eğerki geliştirme yapılan donanım interrupta ihtiyaç duyuyorsa ilgili modül interrupt driven olarak tasarlanır. Bu yüzden yazılımda ilgili donanıma uygun interrupt handler fonksiyonuna kayıt olunmalıdır.
Genellikle çoğu donanım bir kesme fonksiyonuna ve onu işletecek bir sisteme ihtiyaç duyar.Bu sistem bir bare-metal sistem veya işletim çekirdeği sistemi olabilir.
Donanımı yönetecek ve haberleşecek olan kernel modülü, kernel içinden çağrılabilen request_irq() fonksiyonu ile ilgili interrupt handlerine kayıt edilir. Örnek olarak donanımcı klavye tuşuna basıldığındaki davranışara göre bir driver gerçekleştirmek istiyor ise bu interrupta kayıt olur. Bu sayede tanımlanan kesmeye atanılabilen bir fonksiyon sayesinde ilgili donanım eventi yazılımcıya verilebilmektedir. request-irq() fonksiyonu <linux/interrupt.h>kütüphanesi içerisinde tanımlanmıştır. Bu sayede bu header dosyasının çağrılabildiği her kaynak dosyasında bu fonksiyona erişilebilir. Örnek olarak aşağıda bir fonksiyon prototipi verilmiştir.
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char*name, void *dev);
request_irq fonksiyonunun ilk parametresi ilgili işlemciye ait interrupt numarasıdır. Bu numara sayesinde işlemcinin hangi interrupt'una kayıt olması gerektiği linux kerneline belirtilir. Örnek olarak klavye veya mause tıklama eventi veya monitor vga plug olarak verilebilir Fakat bu numaralar linux kerneli bu işlemci için modifiye edilirken elle hardcoded bir şekilde gömülmüştür.
Bu şekilde farklı işlemci mimarilerine göreaynı donanımların farklı bir numarası olabilir. Bu yüzden kernel geliştirilirken bu hususlara dikkat edilmelidir. Fakat işletim sisteminin mimari ayrımını kaldırmak için genellikle bu numaralar işlemci üreticileri tarafından aynı olmaya zorlanırlar. Bazı aygıtlar için ise bu değerlerin dinamik olarak linux kerneli tarafından atanılabildiğini de unutmayınız. Örnek olarak USB stickler ve PCI-Express...
request_irq fonksiyonunun ikinci parametresi ise kayıt olunması istenen kesmeye ait interrupt oluştuğunda işlemcinin program counter registerinin dallanacağı fonksiyonun memory adresidir. İşlemci PCR program counter registeri yüzünden dolaylı yoldan bu fonksiyona dallanarak gerekli işlemleri yapar. Bu fonksiyon veya interrupt handler veya kesme işleyicisi diyebileceğimiz bu fonksiyon, işletim sistemi koşarken interrupt oluştuğunda invoke edilirler.
Örnek olarak aşağıda bir interrupt handler fonksiyonu verilebilir.
typedef irq_return_t (irq_handler_t)(irq,void *);
yukardaki fonksiyon bir interrupt gerçeklestiği zaman bunu handle edebilecek bir fonksiyondur ve işlemci tarafından kernelin contextinin olmadığı bir yerde execute edilirler. İlk parametre hangi interruptun geldiği, ikinci parametre ise tamamiyle donanıma özgün bir struct pointer veya başka bir nesne olabilir.
Her donanıma ait interrupt aynı interrupt handlere sahip olmayabilir. Daha gelişmiş driverlerde daha fazla parametrre alan fonksiyonlar kullanılabilir.