it-swarm-id.com

Bagaimana Interrupt ditangani di Linux?

Saya hanya tahu bahwa Interrupt adalah hardware signal assertion disebabkan pada pin prosesor. Tapi saya ingin tahu bagaimana OS Linux menanganinya.
Apa saja hal-hal yang terjadi ketika interupsi terjadi?

35
Sen

Berikut tampilan tingkat tinggi dari pemrosesan tingkat rendah. Saya menggambarkan arsitektur khas yang sederhana, arsitektur nyata dapat lebih kompleks atau berbeda dalam cara yang tidak penting pada tingkat detail ini.

Ketika interupsi terjadi, prosesor akan melihat jika interupsi disamarkan. Jika mereka, tidak ada yang terjadi sampai mereka membuka kedok. Ketika interupsi dibuka kedoknya, jika ada interupsi yang tertunda, prosesor akan mengambilnya.

Kemudian prosesor mengeksekusi interupsi dengan bercabang ke alamat tertentu dalam memori. Kode di alamat itu disebut interrupt handler . Ketika prosesor bercabang di sana, masker akan menyela (sehingga pengendali interupsi memiliki kontrol eksklusif) dan menyimpan konten beberapa register di suatu tempat (biasanya register lain).

Interrupt handler melakukan apa yang harus dilakukan, biasanya dengan berkomunikasi dengan perangkat yang memicu interupsi untuk mengirim atau menerima data. Jika interupsi dinaikkan oleh timer, pawang mungkin memicu penjadwal OS, untuk beralih ke utas yang berbeda. Ketika pawang selesai dieksekusi, ia menjalankan instruksi kembali-dari-interupsi khusus yang mengembalikan register yang disimpan dan membuka kedok interupsi.

Interrupt handler harus berjalan dengan cepat, karena mencegah interupsi lainnya berjalan. Di kernel Linux, pemrosesan interupsi dibagi menjadi dua bagian:

  • "Bagian atas" adalah penangan interrupt. Itu tidak perlu minimum, biasanya berkomunikasi dengan perangkat keras dan menetapkan bendera di suatu tempat di memori kernel.
  • "Setengah bawah" melakukan pemrosesan lain yang diperlukan, misalnya menyalin data ke dalam memori proses, memperbarui struktur data kernel, dll. Ini dapat memakan waktu dan bahkan memblokir menunggu beberapa bagian lain dari sistem karena beroperasi dengan gangguan yang diaktifkan.

Seperti biasa pada topik ini, untuk informasi lebih lanjut, baca Linux Device Drivers ; bab 1 adalah tentang interupsi.

Gilles sudah dijelaskan kasus umum interupsi, yang berikut ini berlaku khusus untuk Linux 2.6 pada arsitektur Intel (bagian dari ini juga didasarkan pada spesifikasi Intel).

Interupsi adalah peristiwa yang mengubah urutan instruksi yang dijalankan oleh prosesor.
Ada dua macam interupsi:

  • Interrupt sinkron (Pengecualian) diproduksi oleh CPU saat memproses instruksi
  • Interupsi asinkron (Interrupt) yang dikeluarkan oleh perangkat perangkat keras lainnya

Pengecualian disebabkan oleh kesalahan pemrograman (fe Divide error, Page Fault, Overflow) yang harus ditangani oleh kernel . Dia mengirim sinyal ke program dan mencoba memulihkan dari kesalahan.

Dua pengecualian berikut diklasifikasikan:

  • Pengecualian yang terdeteksi oleh prosesor dihasilkan oleh CPU saat mendeteksi kondisi yang tidak normal; dibagi menjadi tiga kelompok: Kesalahan secara umum dapat diperbaiki, Perangkap laporkan eksekusi, Batalkan adalah kesalahan serius.
  • Pengecualian terprogram yang diminta oleh programmer, ditangani seperti jebakan.

Interupsi dapat dikeluarkan oleh perangkat I/O (keyboard, adaptor jaringan, ..), timer interval dan (pada sistem multiprosesor) CPU lainnya. Ketika terjadi interupsi, CPU harus menghentikan instruksi yang sekarang dan menjalankan interupsi yang baru tiba. Ia perlu menyimpan status proses terputus lama untuk (mungkin) melanjutkannya setelah interupsi ditangani.

Menangani interupsi adalah tugas yang sensitif:

  • Interupsi dapat terjadi kapan saja, kernel mencoba keluar dari jalan sesegera mungkin
  • Interupsi dapat diinterupsi oleh interupsi lain
  • Ada beberapa daerah di kernel yang tidak boleh diganggu sama sekali

Dua level interupsi yang berbeda didefinisikan:

  • Interupsi maskable yang dikeluarkan oleh perangkat I/O; bisa di dua negara, bertopeng atau terbuka kedok. Hanya interupsi terbuka yang diproses.
  • Interupsi nonmaskable ; kerusakan kritis (mis. kegagalan perangkat keras); selalu diproses oleh CPU.

Setiap perangkat keras memiliki garis Permintaan Interupsi (IRQ) sendiri. IRQ dinomori mulai dari 0. Semua jalur IRQ terhubung ke Programmable Interrupt Controller (PIC). PIC mendengarkan IRQ dan menetapkannya ke CPU. Dimungkinkan juga untuk menonaktifkan jalur IRQ tertentu.
Sistem Linux multiprosesor modern umumnya mencakup Advanced PIC (APIC) yang lebih baru, yang mendistribusikan permintaan IRQ secara merata di antara CPU.

Langkah tengah antara interupsi atau pengecualian dan penanganannya adalah Interrupt Descriptor Table (IDT). Tabel ini mengaitkan setiap vektor interupsi atau pengecualian (angka) dengan handler yang ditentukan (mis. Kesalahan pembagian ditangani oleh fungsi divide_error()).

Melalui IDT, kernel tahu persis bagaimana menangani interupsi atau pengecualian yang terjadi.


Jadi, apa yang dilakukan kernel ketika terjadi interupsi?

  • CPU memeriksa setelah setiap instruksi jika ada IRQ dari PIC (A)
  • Jika demikian, hubungi IDT untuk memetakan vektor yang diterima ke suatu fungsi
  • Cek apakah interupsi dikeluarkan oleh sumber yang diotorisasi
  • Menyimpan register dari proses yang terputus
  • Panggil fungsi yang sesuai untuk menangani interupsi
  • Muat register yang baru disimpan dari proses terputus dan cobalah untuk melanjutkannya
22
wag

Pertama-tama peserta yang terlibat dalam penanganan interupsi adalah perangkat perangkat keras periferal, pengontrol interupsi, CPU, kernel sistem operasi dan driver. Perangkat perangkat periferal bertanggung jawab atas pembangkitan interupsi. Mereka menegaskan baris permintaan interupsi ketika mereka menginginkan perhatian dari kernel sistem operasi. Sinyal-sinyal ini multiplexing oleh interrupt controller, yang bertanggung jawab untuk pengumpulan sinyal interrupt. Ini juga bertanggung jawab untuk menentukan urutan di mana sinyal interupsi akan diteruskan ke CPU. Pengendali interupsi untuk sementara waktu dapat menonaktifkan jalur permintaan interupsi (IRQL) sementara dan mengaktifkannya kembali (penyembunyian IRQL). Pengendali interupsi mengumpulkan permintaan interupsi yang dikumpulkan ke CPU secara berurutan. CPU setelah penyelesaian setiap instruksi yang dilakukan CPU memeriksa apakah ada permintaan interupsi menunggu dari pengontrol interupsi. Jika CPU menemukan bahwa ada permintaan tunggu dan Interrupt Enable flag diatur dalam register kontrol CPU internal, maka CPU akan memulai penanganan interupsi. Seperti yang Anda lihat, dengan manipulasi pada bendera Interrupt di CPU dan komunikasi dengan pengontrol interupsi, kernel Linux dapat mengontrol penerimaan interupsi. Misalnya, Linux dapat menonaktifkan penerimaan interupsi dari perangkat tertentu atau menonaktifkan penerimaan interupsi sama sekali.

Apa yang terjadi ketika prosesor menerima permintaan interupsi? Pertama, CPU secara otomatis menonaktifkan interupsi dengan mengatur ulang Bendera Interrupt. Mereka akan diaktifkan kembali setelah penanganan interupsi selesai. Pada saat yang sama CPU membuat jumlah minimal pekerjaan yang diperlukan untuk mengalihkan CPU dari mode pengguna ke mode kernel sedemikian rupa yang memungkinkannya melanjutkan eksekusi kode yang terputus. CPU berkonsultasi dengan struktur kontrol CPU khusus yang diisi oleh kernel Linux untuk menemukan alamat kode yang akan diteruskan kontrol. Alamat ini adalah alamat instruksi pertama interrupt handler, yang merupakan bagian dari kernel Linux.

Sebagai langkah pertama interrupt handling kernel mengidentifikasi vektor interrupt yang diterima untuk mengidentifikasi peristiwa apa yang telah terjadi dalam sistem. Interrupt vector mendefinisikan tindakan apa yang akan dilakukan Linux untuk menanganinya. Sebagai langkah kedua, Linux menyimpan sisa register CPU (yang tidak disimpan oleh CPU secara otomatis) dan yang berpotensi dapat digunakan oleh program yang terputus. Ini adalah tindakan yang sangat penting, karena memungkinkan Linux untuk menangani interupsi secara transparan terkait dengan program yang terganggu. Sebagai langkah ketiga, Linux menyelesaikan peralihan ke mode kernel dengan mengatur lingkungan kernel dan mengatur status CPU yang diperlukan untuk itu. Dan akhirnya, penangan interupsi tergantung vektor disebut. (Anda dapat melihat BUILD_INTERRUPT3 makro di Arch\x86\kernel\entry_32.S untuk mengambil detail tambahan untuk contoh arsitektur terkait x86). Dalam hal perangkat periferal ini adalah rutin do_IRQ (). (Lihatlah Arch\x86\kernel\irq.c)

Handler interupsi tergantung vektor biasanya dibungkus oleh panggilan ke irq_enter () dan irq_exit (). Area kode yang terlampir di dalam sepasang fungsi-fungsi ini, adalah atomik sehubungan dengan area-area lain yang demikian dan juga atomik berkenaan dengan pasangan-pasangan cli/sti. Irq_enter () dan irq_exit () juga menangkap beberapa statistik yang terkait dengan penanganan interupsi. Akhirnya, kernel melihat ke tabel vector_irq untuk menemukan nomor irq yang ditetapkan untuk vektor interupsi yang diterima dan memanggil handle_irq () (dari Arch\x86\kernel\irq_32.c).

Pada titik ini bagian umum dari penanganan interupsi di Linux berakhir, karena kernel melihat rutin interrupt handler yang tergantung pada perangkat yang diinstal oleh driver perangkat sebagai bagian dari deskriptor irq dan memanggilnya. Jika handler tidak diinstal oleh driver, kernel hanya mengakui interrupt pada interrupt controller dan pergi untuk keluar dari general interrupt handler.

Setelah akhir penanganan kernel interupsi mengembalikan keadaan program yang terputus sebelumnya dan melanjutkan eksekusi program ini.

8
ZarathustrA

Dari aspek teori, hampir semuanya sudah dijelaskan. Tetapi jika Anda mencari penjelasan tentang kerangka kode penanganan interupsi kernel, tautan berikut harus Anda: Sebuah kode berjalan di dalam penanganan interupsi kernel

Dan jika Anda masih mencari teori tentang interrupt dan interrupt handler, maka saya sarankan membaca ini: Memahami interrupt dan interrupt handler

3
trukna