Sistem Linux ialah sistem pengendalian yang menyokong pelaksanaan serentak pelbagai tugas Ia boleh menjalankan berbilang proses pada masa yang sama, dengan itu meningkatkan penggunaan dan kecekapan sistem. Walau bagaimanapun, jika pertukaran data dan kerjasama diperlukan antara proses ini, beberapa kaedah komunikasi antara proses (IPC) perlu digunakan, seperti baris gilir mesej, memori dikongsi, semaphore, dsb. Antaranya, isyarat ialah kaedah IPC yang agak mudah dan fleksibel, yang membolehkan satu proses menghantar mesej ringkas kepada proses lain untuk memberitahu bahawa beberapa peristiwa atau pengecualian telah berlaku. Terdapat dua jenis isyarat dalam sistem Linux, iaitu isyarat segerak dan isyarat tak segerak. Artikel ini akan menganalisis secara ringkas kaedah pemegang isyarat tak segerak Linux, termasuk makna, penjanaan, penghantaran, penerimaan, pemprosesan dan pengabaian isyarat tak segerak.
Apabila saya mula-mula mempelajari pengaturcaraan Linux, saya sentiasa merasakan bahawa pemegang isyarat tak segerak adalah perkara yang sangat ajaib Program pengguna boleh menggunakan panggilan sistem seperti singal untuk mendaftarkan fungsi pemprosesan isyarat (fungsi pemegang) untuk isyarat tertentu.
Kod binari program mempunyai aliran pelaksanaan tertentu dalam ingatan Mengapa program "terganggu" selepas menerima isyarat tak segerak dan kemudian melompat ke fungsi pemegang untuk dijalankan? Bagaimanakah kernel mempunyai keupayaan untuk membuat program membuat lompatan sedemikian. Tidak mustahil untuk mengubah suai kod program yang boleh dilaksanakan, bukan?
Selepas mempelajari beberapa pengetahuan kernel, saya menyedari bahawa selepas proses menerima isyarat, ia tidak serta-merta "terputus" Sebaliknya, ia mula-mula merekodkan penerimaan isyarat tertentu dalam struktur kawalan proses (task_struct), dan kemudian menunggu sehingga proses Apabila ia akan kembali dari mod kernel ke mod pengguna, proses "terganggu" dan fungsi pemegang dipanggil.
Bilakah proses pengguna akan kembali dari mod kernel ke mod pengguna? Secara amnya, terdapat tiga situasi utama: panggilan sistem (proses pengguna secara aktif memasuki kernel), gangguan (proses pengguna secara pasif memasuki kernel), dan pelaksanaan berjadual (proses pengguna berubah daripada menunggu pelaksanaan kepada dilaksanakan).
Ia mengambil masa tertentu untuk proses kembali dari keadaan kernel kepada keadaan pengguna selepas menerima isyarat. Tetapi masa ini secara amnya sangat singkat, sekurang-kurangnya gangguan jam akan membawa proses pengguna ke dalam kernel pada frekuensi yang agak tinggi (seperti sekali setiap 1 milisaat) (sudah tentu, hanya untuk proses pelaksanaan).
Apabila proses akan kembali dari mod kernel ke mod pengguna, jika terdapat isyarat yang perlu diproses, fungsi pemegang yang sepadan akan dipanggil (sudah tentu, pemegang mungkin tidak didaftarkan, dan kernel akan mengendalikan isyarat secara lalai). Ambil perhatian bahawa proses masih dalam mod kernel Bagaimanakah kernel memanggil fungsi pemegang dalam mod pengguna?
Bolehkah saya menghubunginya terus? Sudah tentu tidak. Kod kernel berjalan di bawah tahap keistimewaan CPU yang tinggi Jika fungsi pemegang dipanggil terus, fungsi pemegang juga akan dilaksanakan di bawah keistimewaan CPU yang sama. Kemudian pengguna akan dapat melakukan apa sahaja yang dia mahu dalam fungsi pemegang.
Oleh itu, pemegang panggilan mesti kembali ke mod pengguna dahulu. Tetapi selepas kembali ke mod pengguna, aliran program tidak lagi dikawal oleh kernel Adakah mungkin kernel benar-benar menukar kod boleh laku proses pengguna?
Pendekatan sebenar inti adalah agak bijak. Selepas proses pengguna memasuki kernel, ia akan meninggalkan alamat pemulangan pada tindanan kernel yang sepadan supaya proses itu boleh kembali. Cara kernel memanggil fungsi pemegang adalah untuk menukar sementara alamat pemulangan pada tindanan, dan kemudian kembali mengikut proses asal untuk kembali ke mod pengguna. Akibatnya, pulangan ini pergi ke fungsi pemegang. (Sudah tentu, bukan sahaja alamat pemulangan yang perlu diubah suai, tetapi keseluruhan timbunan panggilan.)
Walaupun alamat pemulangan telah ditukar buat sementara waktu, proses pengguna akhirnya akan kembali ke alamat pemulangan asal. Jadi, di manakah alamat pemulangan asal dan timbunan panggilannya harus disimpan? Ruang tindanan kernel proses adalah terhad, dan ia juga perlu menangani panggilan sistem yang mungkin berlaku dalam fungsi pemegang, jadi adalah tidak realistik untuk kernel untuk meletakkan maklumat ini pada tindanan kernel, dan ia hanya boleh ditolak ke timbunan pengguna.
Apabila fungsi pemegang dilaksanakan, proses pelaksanaan kembali ke kernel. Begitu juga, disebabkan oleh tahap keistimewaan CPU yang berbeza, anda tidak boleh hanya menggunakan arahan RET untuk kembali daripada fungsi pemegang kepada kernel. Panggilan sistem perlu dilaksanakan.
Selepas pemegang dilaksanakan, mengapa kita perlu kembali ke kernel dan kemudian kembali dari kernel ke alamat pemulangan asal? Ia akan menjadi sangat mudah jika anda terus kembali ke alamat pemulangan asal. Dan ia tidak sukar untuk melakukan ini Alamat pemulangan asal dan timbunan panggilannya telah ditolak ke timbunan pengguna Kernel hanya perlu melakukan sedikit manipulasi pada timbunan panggilan fungsi pemegang.
1. Kembali ke alamat pemulangan asal bukan hanya bermakna kembali ke alamat itu Anda perlu memulihkan keseluruhan adegan (terutamanya daftar dan sebagainya). Sudah tentu, kernel juga boleh menekan beberapa kod pada timbunan pengguna untuk menyelesaikan perkara ini;
2. Kini mungkin terdapat lebih daripada satu isyarat untuk diproses Sebaiknya biarkan pengguna memproses kembali ke kernel dan meneruskan pemprosesan isyarat lain
Untuk kembali ke kernel, pertama, kernel menolak alamat pemulangan ke tindanan pengguna sebelum kembali ke fungsi pemegang, supaya ia boleh kembali ke alamat yang ditentukan apabila kembali dari pemegang. Alamat yang ditentukan ini sebenarnya juga pada tindanan pengguna proses Kernel meletakkan beberapa arahan pada alamat ini (meletakkan kod boleh laku pada tindanan) untuk membenarkan proses memanggil panggilan sistem yang dipanggil sigreturn.
Timbunan pengguna sebelum kembali ke fungsi pemegang adalah kira-kira seperti berikut:
Data asal -> Arahan untuk memanggil sigreturn (biar alamatnya a) -> Alamat pemulangan asal dan timbunan panggilannya -> Alamat pemulangan (nilai ialah a) -> Pembolehubah timbunan pemegang
Inti meletakkan arahan sigreturn pada timbunan panggilan fungsi pemegang, yang merupakan amalan dalam Linux 2.4. Setiap kali fungsi pemegang pengguna dipanggil, begitu banyak arahan perlu disalin ke timbunan pengguna, yang tidak baik.
Linux 2.6 mempunyai halaman yang dipanggil halaman vsyscall, yang mengandungi beberapa arahan yang disediakan oleh kernel untuk program pengguna, termasuk memanggil arahan sigreturn. Halaman vsyscall ini dipetakan ke penghujung ruang alamat maya setiap proses, dikongsi oleh semua proses pengguna dan dibaca sahaja untuk proses pengguna. Dengan cara ini, tidak perlu memasukkan arahan sigreturn ke dalam timbunan panggilan fungsi pemegang. Hanya tetapkan alamat pemulangan fungsi pemegang kepada kod yang sepadan dalam halaman vsyscall.
Untuk memanggil sigreturn secara automatik untuk kembali ke kernel selepas pemegang dilaksanakan, kernel melakukan banyak perkara. Jadi bolehkah kita bersetuju untuk membenarkan pengguna memanggil sigreturn sendiri?
Sudah tentu, ini mungkin. Hanya untuk menjadikan mekanisme pemprosesan isyarat sebagai mekanisme yang lengkap, kernel tidak melakukan ini. Jika tidak, jika pengguna terlupa untuk memanggil sigreturn dalam fungsi pemegang, proses itu mungkin ranap tanpa sebab. Dan sukar bagi pengkompil untuk mencari ralat sedemikian.
Selepas proses memanggil panggilan sistem sigreturn dan memasuki semula kernel, alamat pemulangan asal dan timbunan panggilannya yang ditekan pada timbunan pengguna diperolehi. Akhirnya, kernel akan mengubah suai tindanan supaya proses kembali ke alamat pemulangan asal apabila ia kembali ke ruang pengguna.
Artikel ini menganalisis secara ringkas kaedah pemegang isyarat tak segerak Linux, termasuk makna, penjanaan, penghantaran, penerimaan, pemprosesan dan pengabaian isyarat tak segerak. Dengan memahami dan menguasai pengetahuan ini, kami boleh menguasai pengetahuan teras pemprosesan isyarat Linux, dengan itu meningkatkan kestabilan dan kecekapan sistem. Sudah tentu, pemegang isyarat tak segerak Linux mempunyai banyak ciri dan penggunaan lain, yang memerlukan pembelajaran dan penyelidikan berterusan. Saya harap artikel ini dapat memberi inspirasi dan bantuan kepada anda.
Atas ialah kandungan terperinci Analisis ringkas mengenai pemegang isyarat tak segerak linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!