Rumah > Artikel > Tutorial sistem > Tidur sistem Linux (System Suspend) dan pengendalian gangguan peranti
Bahagian ini menyelesaikan masalah terutamanya: Bagaimana untuk menggantung gangguan peranti (IRQ) apabila sistem memasuki keadaan tidur? Bagaimana untuk memulihkan IRQ peranti apabila membangunkan sistem?
Biasanya, selepas sistem memasuki keadaan tidur, IRQ (Talian Permintaan Interupsi) semua peranti akan dilumpuhkan. Titik masa tertentu ialah selepas fasa penggantungan lewat peranti. Di bawah ialah kod yang berkaitan (kod yang tidak berkaitan ditinggalkan).
“
statik int suspend_enter(suspend_state_t state, bool *wakeup)
{……
ralat = dpm_suspend_late(PMSG_SUSPEND);----fasa penggantungan lewat
ralat = platform_suspend_prepare_late(state);
Kod berikut akan melumpuhkan irq setiap peranti
ralat = dpm_suspend_noirq(PMSG_SUSPEND);——Masuk ke peringkat noirq
ralat = platform_suspend_prepare_noirq(negeri);
……
}
”
Dalam fungsi dpm_suspend_noirq, device_suspend_noirq akan dipanggil secara bergilir-gilir untuk setiap peranti dalam sistem untuk melaksanakan fungsi panggil balik suspend dalam kes noirq peranti Sudah tentu, fungsi suspend_device_irqs akan dipanggil sebelum ini untuk melumpuhkan irqs semua. peranti.
Idea di sebalik perkara ini ialah: selepas setiap pemacu peranti menyelesaikan penggantungan lewat, adalah wajar bahawa peranti yang digantung ini tidak lagi boleh mencetuskan gangguan. Jika masih terdapat beberapa peranti yang tidak digantung dengan betul, maka strategi terbaik kami ialah menutup irq peranti untuk mengelakkan gangguan daripada diserahkan. Di samping itu, dalam kod yang lalu (merujuk kepada pengendali gangguan), kami tidak mengendalikan situasi peranti yang berkongsi IRQ dengan baik. Terdapat masalah sedemikian: selepas peranti yang berkongsi IRQ digantung sepenuhnya, jika gangguan dicetuskan, peranti itu pemandu akan Pengendali gangguan tidak bersedia. Dalam sesetengah senario, pengendali gangguan akan mengakses ruang alamat IO peranti yang digantung, menyebabkan isu yang tidak dapat diramalkan. Isu ini sukar untuk nyahpepijat, jadi kami memperkenalkan suspend_device_irqs() dan fungsi panggil balik dalam fasa noirq peranti.
Semasa proses resume sistem, sebelum proses resume awal setiap peranti, IRQ setiap peranti akan dibuka semula Kod khusus adalah seperti berikut (beberapa kod yang tidak berkaitan telah dipadamkan):
“
statik int suspend_enter(suspend_state_t state, bool *wakeup)
{……
platform_resume_noirq(state);---Lakukan resume dalam fasa noirq
dpm_resume_noirq(PMSG_RESUME);-----Irq akan dipulihkan di sini dan kemudian memasuki peringkat resume awal
platform_resume_early(negeri);
dpm_resume_early(PMSG_RESUME);
……}
”
Dalam fungsi dpm_resume_noirq, panggilan balik noirq setiap pemacu peranti akan dipanggil. Selepas itu, fungsi resume_device_irqs dipanggil untuk melengkapkan enable setiap peranti irq.
2. Mengenai Bendera IRQF_NO_SUSPEND
Sudah tentu, sesetengah gangguan perlu kekal boleh dicetuskan semasa proses penggantungan-sambung semula keseluruhan sistem (termasuk semasa fasa noirq, termasuk fasa di mana CPU tanpa but ditolak ke keadaan luar talian dan sistem ditetapkan semula kepada dalam talian selepas sistem disambung semula). Contoh mudah ialah gangguan pemasa, sebagai tambahan kepada IPI dan beberapa gangguan peranti tujuan khas.
Apabila meminta gangguan, bendera IRQF_NO_SUSPEND boleh digunakan untuk memaklumkan subsistem IRQ ini ialah jenis gangguan yang diterangkan dalam perenggan sebelumnya: ia perlu kekal didayakan semasa proses penggantungan-sambung semula sistem. Dengan bendera ini, suspend_device_irqs tidak akan melumpuhkan IRQ, membenarkan gangguan kekal didayakan semasa proses penggantungan dan sambung semula. Sudah tentu, ini tidak menjamin bahawa gangguan boleh membangunkan sistem. Jika anda ingin mencapai tujuan bangun tidur, sila hubungi enable_irq_wake.
Perlu diambil perhatian bahawa bendera IRQF_NO_SUSPEND mempengaruhi semua peranti yang menggunakan IRQ ini (IRQ boleh dikongsi oleh berbilang peranti, tetapi ini tidak digunakan dalam ARM). Jika IRQ dikongsi oleh berbilang peranti, dan setiap peranti telah mendaftarkan pengendali gangguan yang sepadan, dan jika salah seorang daripada mereka menggunakan bendera IRQF_NO_SUSPEND semasa memohon gangguan, maka apabila sistem digantung (merujuk kepada selepas suspend_device_irqs), ia bermaksud sebab setiap IRQ telah dilumpuhkan), pengendali gangguan semua peranti pada IRQ boleh dicetuskan dan dilaksanakan secara normal, walaupun sesetengah peranti tidak menetapkan bendera IRQF_NO_SUSPEND apabila memanggil request_irq (atau fungsi pendaftaran gangguan lain). Oleh sebab itu, kita harus mengelak daripada menggunakan dua bendera IRQF_NO_SUSPEND dan IRQF_SHARED pada masa yang sama sebanyak mungkin.
3 Antara muka bangun tidur gangguan sistem: enable_irq_wake() dan disable_irq_wake()
Sesetengah gangguan boleh membangunkan sistem daripada keadaan tidur, yang kita panggil "gangguan yang boleh membangunkan sistem". . Sampukan sedemikian biasanya kelihatan sebagai sampukan I/O biasa semasa keadaan kerja Hanya apabila bersiap untuk mendayakan fungsi sistem bangun tidur, beberapa konfigurasi dan tetapan khas akan dimulakan.
Konfigurasi dan tetapan sedemikian mungkin berkaitan dengan logik pemprosesan isyarat pada sistem perkakasan (seperti SOC Kita boleh mempertimbangkan gambarajah blok HW berikut:
).Isyarat gangguan persisian dihantar ke "modul pemprosesan isyarat gangguan umum" dan "modul penerima isyarat gangguan khusus". Apabila bekerja seperti biasa, kami akan menghidupkan logik pemprosesan "modul pemprosesan isyarat gangguan umum" dan mematikan logik pemprosesan "modul penerima isyarat gangguan khusus". Walau bagaimanapun, apabila sistem memasuki keadaan tidur, ada kemungkinan bahawa "modul pemprosesan isyarat gangguan umum" telah dimatikan Pada masa ini, kita perlu memulakan "modul penerima isyarat gangguan khusus" untuk menerima isyarat gangguan, supaya. modul penggantungan-sambung semula sistem ( Selalunya ia merupakan satu-satunya blok HW yang boleh berfungsi dalam keadaan digantung) dan boleh dikejutkan oleh isyarat gangguan seperti biasa. Sebaik sahaja bangun, adalah lebih baik untuk mematikan "modul menerima isyarat gangguan khusus" untuk membolehkan pemprosesan gangguan persisian kembali ke mod kerja biasa Pada masa yang sama, ia juga mengelakkan gangguan yang tidak perlu kepada modul gantung-sambung semula sistem.
Subsistem IRQ menyediakan dua fungsi antara muka untuk melengkapkan fungsi ini: fungsi enable_irq_wake() digunakan untuk membuka talian gangguan persisian yang menuju ke modul pengurusan kuasa sistem (iaitu, modul gantung-sambung semula di atas), dan antara muka lain Ia adalah disable_irq_wake(), yang digunakan untuk menutup pelbagai blok HW pada laluan dari talian gangguan persisian ke modul pengurusan kuasa sistem.
Memanggil enable_irq_wake akan menjejaskan pemprosesan suspend_device_irqs dalam proses penggantungan sistem Kodnya adalah seperti berikut:
“
bool statik suspend_device_irq(struct irq_desc *desc)
{
……
jika (set_irqd_is_wakeup(&desc->irq_data)) {
irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
kembali benar;
}
Tinggalkan kod sampukan Lumpuhkan
}
”
Dalam erti kata lain, sebaik sahaja enable_irq_wake dipanggil untuk menetapkan gangguan peranti sebagai sumber bangun sistem digantung, gangguan dalam persisian tidak akan dilumpuhkan, tetapi akan ditandakan dengan bendera IRQD_WAKEUP_ARMED. Untuk gangguan yang bukan sumber bangun tidur, IRQS_SUSPENDED akan ditanda dalam fungsi suspend_device_irq dan irq peranti akan dilumpuhkan. Semasa proses bangun sistem (resume_device_irqs), gangguan yang telah dilumpuhkan akan didayakan semula.
Sudah tentu, jika beberapa peristiwa berlaku semasa proses penggantungan (contohnya, sumber wakeup menjana isyarat yang sah), mengakibatkan penggantungan ini digugurkan, maka peristiwa pengguguran ini juga akan dimaklumkan kepada modul teras PM. Acara itu tidak perlu dimaklumkan kepada modul teras PM dengan serta-merta, secara amnya, urutan penggantungan akan menyemak acara bangun yang belum selesai pada satu ketika.
Semasa proses penggantungan sistem, setiap gangguan daripada sumber wakeup akan menamatkan proses suspend atau membangunkan sistem (jika sistem telah memasuki keadaan suspend). Walau bagaimanapun, selepas melaksanakan suspend_device_irqs, sampukan biasa disekat Pada masa ini, walaupun HW mencetuskan isyarat sampukan, ia tidak boleh melaksanakan pengendali sampukannya. Apakah yang berlaku kepada IRQ sebagai sumber bangun tidur? Walaupun gangguannya tidak bertopeng, pengendali gangguannya tidak akan dilaksanakan (Isyarat HW pada masa ini hanya digunakan untuk membangunkan sistem). Satu-satunya pengendali gangguan yang mempunyai peluang untuk melaksanakan ialah IRQ yang ditandakan dengan bendera IRQF_NO_SUSPEND, kerana gangguan mereka sentiasa didayakan. Sudah tentu, gangguan ini tidak sepatutnya memanggil enable_irq_wake untuk menetapkan sumber bangun tidur.
4 Mengganggu dan Menggantung-untuk-Melahu
Suspend-to-idle (juga dikenali sebagai keadaan "freeze") ialah keadaan pengurusan kuasa sistem yang agak baharu Kod yang berkaitan adalah seperti berikut:
“
statik int suspend_enter(suspend_state_t state, bool *wakeup)
{
……
Peringkat penggantungan lewat setiap peranti
noirq fasa penangguhan setiap peranti
jika (nyatakan == PM_SUSPEND_BEBASKAN) {
bekukan_masuk();
goto Platform_wake;
}
……
}
”
Operasi Pembekuan dan penggantungan sebelum ini pada asasnya adalah sama: mula-mula membekukan proses dalam sistem, dan kemudian menggantung pelbagai peranti dalam sistem Perbezaannya ialah selepas penggantungan noirq selesai, pembekuan tidak akan melumpuhkan proses bukan BSP tersebut . pemproses dan fasa penggantungan syscore, tetapi memanggil fungsi freeze_enter untuk menolak semua pemproses ke keadaan terbiar. Pada masa ini, sebarang gangguan yang didayakan boleh membangunkan sistem. Dan ini bermakna bahawa bendera IRQF_NO_SUSPEND (yang IRQnya tidak bertopeng semasa proses suspend_device_irqs) mampu membangunkan pemproses daripada keadaan melahu (namun, perlu diperhatikan bahawa isyarat ini tidak mencetuskan isyarat bangun sistem), dan gangguan biasa tidak boleh membangunkan pemproses dalam keadaan melahu kerana IRQ mereka dinyahdayakan.
Bagaimana pula dengan gangguan bangun yang boleh membangunkan sistem? Memandangkan gangguannya tidak bertopeng, sistem juga boleh dibangkitkan daripada keadaan gantung hingga terbiar. Keseluruhan proses adalah sama seperti membangunkan sistem daripada keadaan digantung Satu-satunya perbezaan ialah: laluan pemprosesan gangguan untuk membangunkan sistem daripada keadaan beku, dan laluan pemprosesan bangun untuk membangunkan sistem daripada keadaan digantung. memerlukan pengurusan kuasa khas HW BLOCK Penyertaan dalam logik pengendalian gangguan.
5 Bendera IRQF_NO_SUSPEND dan fungsi enable_irq_wake tidak boleh digunakan pada masa yang sama
Untuk peranti, adalah tidak munasabah untuk menggunakan bendera IRQF_NO_SUSPEND apabila memohon gangguan dan memanggil enable_irq_wake untuk menetapkan sumber bangun pada masa yang sama Sebab utama adalah seperti berikut:
1. Jika IRQ tidak dikongsi, gunakan bendera IRQF_NO_SUSPEND untuk menunjukkan bahawa anda ingin memastikan gangguan terbuka semasa proses gantung-sambung semula keseluruhan sistem (termasuk peringkat selepas suspend_device_irqs) supaya pengendali gangguannya boleh dipanggil seperti biasa. . Memanggil fungsi enable_irq_wake menunjukkan bahawa anda ingin menetapkan isyarat irq peranti sebagai sumber gangguan, jadi anda tidak mengharapkan untuk memanggil pengendali gangguannya. Kedua-dua keperluan ini jelas saling eksklusif.
2 Baik bendera IRQF_NO_SUSPEND mahupun fungsi enable_irq_wake adalah untuk satu pengendali gangguan, tetapi untuk semua pengendali berdaftar di IRQ. Adalah tidak masuk akal untuk berkongsi sumber bangun tidur dan sumber gangguan tanpa penggantungan pada IRQ yang sama.
Walau bagaimanapun, dalam keadaan yang sangat istimewa, IRQ boleh ditetapkan sebagai sumber bangun dan juga menetapkan bendera IRQF_NO_SUSPEND. Agar logik kod menjadi betul, kod pemacu peranti perlu memenuhi beberapa keperluan khas.
Atas ialah kandungan terperinci Tidur sistem Linux (System Suspend) dan pengendalian gangguan peranti. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!