GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana Interupsi ditangani di Linux?

Inilah tampilan tingkat tinggi dari pemrosesan tingkat rendah. Saya menjelaskan arsitektur tipikal yang sederhana, arsitektur sebenarnya bisa lebih kompleks atau berbeda dengan cara yang tidak penting pada tingkat detail ini.

Saat terjadi interupsi, prosesor akan melihat apakah interupsi tertutup. Jika ya, tidak ada yang terjadi sampai mereka dibuka kedoknya. Saat interupsi terbuka kedoknya, jika ada interupsi yang tertunda, prosesor akan memilih salah satunya.

Kemudian prosesor mengeksekusi interupsi dengan bercabang ke alamat tertentu di memori. Kode di alamat itu disebut interrupt handler. Saat prosesor bercabang di sana, ia menutupi interupsi (sehingga penangan interupsi memiliki kontrol eksklusif) dan menyimpan konten beberapa register di suatu tempat (biasanya register lain).

Penangan interupsi melakukan apa yang harus dilakukan, biasanya dengan berkomunikasi dengan periferal yang memicu interupsi untuk mengirim atau menerima data. Jika interupsi dimunculkan oleh pengatur waktu, penangan mungkin memicu penjadwal OS, untuk beralih ke utas yang berbeda. Saat handler selesai mengeksekusi, ia mengeksekusi instruksi return-from-interrupt khusus yang memulihkan register yang disimpan dan membuka kedok interupsi.

Penangan interupsi harus berjalan dengan cepat, karena mencegah interupsi lain berjalan. Di kernel Linux, pemrosesan interupsi dibagi menjadi dua bagian:

  • "Bagian atas" adalah penangan interupsi. Itu melakukan hal minimum yang diperlukan, biasanya berkomunikasi dengan perangkat keras dan menyetel bendera di suatu tempat di memori kernel.
  • “Bagian 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 berjalan dengan interupsi diaktifkan.

Seperti biasa pada topik ini, untuk informasi lebih lanjut, baca Driver Perangkat Linux; bab 10 adalah tentang interupsi.


Gilles telah menjelaskan kasus umum interupsi, berikut ini berlaku khusus untuk Linux 2.6 pada arsitektur Intel (bagian ini juga didasarkan pada spesifikasi Intel).

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

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

Pengecualian disebabkan oleh kesalahan pemrograman (f.e. Kesalahan pembagian , Kesalahan Laman , Luapan ) yang harus ditangani oleh kernel. Dia mengirimkan sinyal ke program dan mencoba memulihkan dari kesalahan.

Dua pengecualian berikut diklasifikasikan:

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

Interupsi dapat dikeluarkan oleh perangkat I/O (keyboard, adaptor jaringan, ..), penghitung waktu interval, dan (pada sistem multiprosesor) CPU lainnya. Ketika interupsi terjadi, CPU harus menghentikan instruksinya saat ini dan mengeksekusi interupsi yang baru tiba. Dia perlu menyimpan status proses lama yang terputus untuk (mungkin) melanjutkannya setelah interupsi ditangani.

Menangani interupsi adalah tugas sensitif:

  • Interupsi dapat terjadi kapan saja, kernel mencoba untuk menyingkir sesegera mungkin
  • Interupsi dapat diinterupsi oleh interupsi lain
  • Ada wilayah di kernel yang tidak boleh diinterupsi sama sekali

Dua level interupsi yang berbeda ditentukan:

  • Interupsi yang dapat disamarkan dikeluarkan oleh perangkat I/O; bisa di dua negara, bertopeng atau membuka kedok. Hanya interupsi terbuka yang sedang diproses.
  • Interupsi yang tidak dapat disembunyikan; malfungsi kritis (f.e. kegagalan perangkat keras); selalu diproses oleh CPU.

Setiap perangkat keras memiliki jalur Interrupt Request (IRQ) sendiri. IRQ diberi nomor mulai dari 0. Semua jalur IRQ terhubung ke Programmable Interrupt Controller (PIC). PIC mendengarkan IRQ dan menugaskannya ke CPU. Dimungkinkan juga untuk menonaktifkan jalur IRQ tertentu.
Sistem Linux multiprosesing modern umumnya menyertakan 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 penangan tertentu (f.e. Membagi kesalahan 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 apakah ada IRQ dari (A)PIC
  • Jika demikian, hubungi IDT untuk memetakan vektor yang diterima ke suatu fungsi
  • Memeriksa apakah interupsi dikeluarkan oleh sumber resmi
  • Menyimpan register dari proses yang terputus
  • Panggil fungsi yang sesuai untuk menangani interupsi
  • Muat register yang baru saja disimpan dari proses yang terputus dan coba untuk melanjutkannya

Pertama-tama peserta yang terlibat dalam penanganan interupsi adalah perangkat perangkat keras periferal, pengontrol interupsi, CPU, kernel sistem operasi, dan driver. Perangkat perangkat keras periferal bertanggung jawab atas pembangkitan interupsi. Mereka menegaskan jalur permintaan interupsi ketika mereka menginginkan perhatian dari kernel sistem operasi. Sinyal-sinyal ini dimultipleks oleh pengontrol interupsi, yang bertanggung jawab untuk pengumpulan sinyal interupsi. Ini juga bertanggung jawab untuk menentukan urutan di mana sinyal interupsi akan diteruskan ke CPU. Pengontrol interupsi dapat menonaktifkan jalur permintaan interupsi tertentu (IRQL) untuk sementara dan mengaktifkannya kembali (masking IRQL). Pengontrol interupsi meneruskan permintaan interupsi yang dikumpulkan ke CPU secara berurutan. CPU setelah penyelesaian setiap instruksi CPU memeriksa apakah ada permintaan interupsi yang 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 memanipulasi 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 jika prosesor menerima permintaan interupsi? Pertama, CPU secara otomatis menonaktifkan interupsi dengan menyetel ulang Bendera Interupsi. Mereka akan diaktifkan kembali setelah penanganan interupsi selesai. Pada saat yang sama CPU membuat jumlah pekerjaan minimal yang diperlukan untuk mengalihkan CPU dari mode pengguna ke mode kernel sedemikian rupa sehingga 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 oleh kontrol. Alamat ini adalah alamat dari instruksi pertama interrupt handler, yang merupakan bagian dari kernel Linux.

Sebagai langkah awal penanganan interupsi, kernel mengidentifikasi vektor interupsi yang diterima untuk mengidentifikasi jenis peristiwa apa yang telah terjadi di sistem. Vektor interupsi menentukan tindakan apa yang akan diambil Linux untuk menanganinya. Sebagai langkah kedua, Linux menyimpan register CPU lainnya (yang tidak disimpan oleh CPU secara otomatis) dan yang berpotensi dapat digunakan oleh program yang diinterupsi. Ini adalah tindakan yang sangat penting, karena memungkinkan Linux menangani interupsi secara transparan terkait dengan program yang diinterupsi. Sebagai langkah ketiga, Linux menyelesaikan peralihan ke mode kernel dengan menyetel lingkungan kernel dan menyetel status CPU yang diperlukan untuknya. Dan terakhir, vektor penangan interupsi dependen dipanggil. (Anda dapat melihat makro BUILD_INTERRUPT3 di arch\x86\kernel\entry_32.S untuk mendapatkan detail tambahan untuk contoh terkait arsitektur x86) Dalam kasus perangkat periferal, ini adalah rutinitas do_IRQ(). (Lihat ke arch\x86\kernel\irq.c)

Penangan interupsi yang bergantung pada vektor biasanya dibungkus dengan panggilan ke irq_enter() dan irq_exit(). Area kode yang terlampir dalam sepasang fungsi ini, bersifat atomik terhadap area lain semacam itu dan juga bersifat atomik terhadap pasangan cli/sti. Irq_enter() dan irq_exit() juga menangkap beberapa statistik yang terkait dengan penanganan interupsi. Terakhir, kernel melihat ke dalam tabel vector_irq untuk menemukan nomor irq yang ditetapkan ke 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 rutinitas penangan interupsi yang bergantung pada perangkat yang diinstal oleh driver perangkat sebagai bagian dari deskriptor irq dan memanggilnya. Jika penangan seperti itu belum diinstal oleh driver, kernel cukup mengakui interupsi pada pengontrol interupsi dan keluar dari penangan interupsi umum.

Setelah akhir penanganan interupsi, kernel akan mengembalikan status program yang telah diinterupsi sebelumnya dan melanjutkan eksekusi program ini.


Linux
  1. Bagaimana saya menggunakan cron di Linux

  2. Cara Menginstal NodeJS Di Linux

  3. Bagaimana \n dan \r ditangani secara berbeda di Linux dan Windows?

  1. Cara menginstal Python di Linux

  2. Cara menginstal Java di Linux

  3. Cara mempartisi disk di Linux

  1. Cara menggunakan BusyBox di Linux

  2. Cara menggunakan Perintah Su di Linux

  3. Pengantar Interupsi Linux dan CPU SMP Affinity