Rumah  >  Artikel  >  Tutorial sistem  >  Panggilan sistem dalam Linux bukan kemasukan sah ke dalam kernel

Panggilan sistem dalam Linux bukan kemasukan sah ke dalam kernel

王林
王林ke hadapan
2024-03-19 10:34:02846semak imbas

Di Linux, panggilan sistem adalah satu-satunya cara untuk ruang pengguna mengakses kernel. Ia adalah satu-satunya pintu masuk yang sah ke kernel. Malah, kaedah lain seperti fail peranti dan /proc akhirnya dilakukan melalui panggilan sistem.

Biasanya, aplikasi diprogramkan melalui soket pengaturcaraan aplikasi (API) dan bukannya secara terus melalui panggilan sistem, dan soket pengaturcaraan ini sebenarnya tidak perlu sepadan dengan panggilan sistem yang disediakan oleh kernel. API mentakrifkan satu set soket pengaturcaraan yang digunakan oleh aplikasi. Ia boleh dilaksanakan sebagai satu panggilan sistem atau dengan memanggil berbilang panggilan sistem. Tiada masalah walaupun tiada panggilan sistem digunakan. Malah, API boleh dilaksanakan pada pelbagai sistem pengendalian yang berbeza, menyediakan soket yang sama kepada aplikasi, tetapi pelaksanaannya pada sistem sedemikian mungkin sangat berbeza.

Di dunia Unix, soket pengaturcaraan aplikasi yang paling popular adalah berdasarkan standard POSIX, dan Linux adalah serasi dengan POSIX.

Dari perspektif pengaturcara, mereka hanya perlu berurusan dengan API, dan kernel hanya menangani panggilan sistem; bagaimana fungsi perpustakaan dan aplikasi menggunakan panggilan sistem bukanlah kebimbangan kernel.

Panggilan sistem (sering dipanggil syscall dalam Linux) biasanya dipanggil melalui fungsi. Mereka biasanya memerlukan definisi satu atau beberapa parameter (input) dan mungkin menyebabkan beberapa kesan sampingan. Kesan sampingan ini diwakili oleh nilai pulangan panjang yang menunjukkan kejayaan (nilai 0) atau ralat (nilai negatif). Apabila ralat berlaku dalam panggilan sistem, kod ralat ditulis kepada pembolehubah global errno. Dengan memanggil fungsi perror(), pembolehubah ini boleh diterjemahkan ke dalam rentetan ralat yang boleh difahami oleh pengguna.

Terdapat dua keanehan dalam pelaksanaan panggilan sistem: 1) Terdapat kelayakan asmlinkage dalam pengisytiharan fungsi, yang digunakan untuk memberitahu pengkompil untuk hanya mengekstrak parameter fungsi daripada timbunan. 2) Panggilan sistem getXXX() ditakrifkan sebagai sys_getXXX() dalam kernel. Ini adalah konvensyen penamaan yang harus diikuti oleh semua panggilan sistem dalam Linux.

Nombor panggilan sistem: Di Linux, setiap panggilan sistem diberikan nombor panggilan sistem dan panggilan sistem boleh dikaitkan dengan nombor unik ini. Apabila proses ruang pengguna melaksanakan panggilan sistem, nombor panggilan sistem digunakan untuk menunjukkan panggilan sistem mana yang hendak dilaksanakan proses itu tidak menyebut nama panggilan sistem. Sebaik sahaja nombor panggilan sistem diperuntukkan, ia tidak boleh ditukar (jika tidak, aplikasi yang disusun akan ranap Jika panggilan sistem dipadamkan, nombor panggilan sistem yang didudukinya tidak dibenarkan untuk dikitar semula). Linux mempunyai panggilan sistem "tidak digunakan" sys_ni_syscall(), yang bukan sahaja mengembalikan -ENOSYS tetapi tidak melakukan apa-apa kerja lain Nombor ralat ini direka khusus untuk panggilan sistem yang tidak sah. Nampaknya jarang berlaku, tetapi jika panggilan sistem dipadamkan, fungsi ini bertanggungjawab untuk "mengisi jurang".

Kernel merekodkan senarai semua panggilan sistem berdaftar dalam jadual panggilan sistem dan menyimpannya dalam sys_call_table. Ia berkaitan dengan seni bina dan biasanya ditakrifkan dalam entri.s. Jadual ini memberikan nombor panggilan sistem yang unik kepada setiap panggilan sistem yang sah.

Adalah sukar bagi program ruang pengguna untuk melaksanakan terus kod kernel. Mereka tidak boleh memanggil fungsi secara langsung dalam ruang kernel, kerana kernel berada dalam ruang alamat yang dilindungi Aplikasi harus memberitahu sistem dalam beberapa bentuk, memberitahu kernel bahawa ia perlu melaksanakan panggilan sistem, dan sistem bertukar kepada keadaan kernel. panggilan kernel linux , supaya kernel boleh melaksanakan panggilan sistem bagi pihak aplikasi. Mekanisme untuk memberitahu kernel ini dilaksanakan melalui gangguan lembut. Gangguan lembut pada sistem x86 dibentuk oleh arahan int$0x80. Arahan ini akan mencetuskan pengecualian, menyebabkan sistem bertukar kepada mod kernel dan melaksanakan pengendali pengecualian No. 128. Program ini ialah pengendali panggilan sistem, dan namanya ialah system_call(). dalam entri Disusun dalam bahasa himpunan dalam fail .s.

Semua panggilan sistem terperangkap dalam kernel dalam bentuk yang sama seperti sistem Linux bendera merah, jadi hanya memerangkap dalam ruang kernel tidak mencukupi. Oleh itu, nombor panggilan sistem mesti dihantar ke kernel. Pada x86, pemindahan ini dicapai dengan meletakkan nombor panggilan dalam daftar eax sebelum mencetuskan softirq. Dengan cara ini, setelah pengendali panggilan sistem dijalankan, data boleh diperolehi daripada eax. System_call() yang disebutkan di atas menyemak kesahihan nombor panggilan sistem yang diberikan dengan membandingkannya dengan NR_syscallls. Jika ia kurang daripada atau sama dengan NR_syscalls, fungsi mengembalikan -ENOSYS Jika tidak, panggilan sistem yang sepadan dilaksanakan: call*sys_call_table(,%eax,4);

.

Oleh kerana entri dalam jadual panggilan sistem disimpan dalam jenis 32-bit (4-bait), kernel perlu membahagikan nombor panggilan sistem yang diberikan dengan 4, dan kemudian gunakan hasilnya untuk menanyakan kedudukan peranti dalam jadual . Seperti yang ditunjukkan dalam Rajah 1:

Telah disebutkan bahawa bukan sahaja nombor panggilan sistem, tetapi juga beberapa input parameter luaran diperlukan. Cara paling mudah ialah menyimpan parameter ini dalam daftar sama seperti menghantar nombor panggilan sistem. Pada sistem x86 ebx, ecx, edx, esi dan edi simpan 5 parameter pertama mengikut urutan. Dalam kes yang jarang berlaku di mana enam atau lebih parameter diperlukan, daftar berasingan harus digunakan untuk menyimpan penunjuk yang menunjuk ke alamat ruang pengguna bagi semua parameter tersebut. Nilai pulangan ke ruang pengguna juga dihantar melalui daftar. Pada sistem x86, ia disimpan dalam daftar eax.

Panggilan sistem mesti menyemak dengan teliti sama ada semua parameternya sah dan sah. Panggilan sistem dilaksanakan dalam ruang kernel. Jika pengguna dibenarkan menghantar input haram ke kernel, keselamatan dan kestabilan sistem akan menghadapi ujian yang hebat. Ujian yang paling penting ialah untuk mengesan sama ada penunjuk jam tangan yang disediakan oleh pengguna adalah sah Sebelum kernel menerima penunjuk jam tangan ruang pengguna, kernel mesti memastikan:

1) Kawasan memori video yang ditunjuk oleh tangan jam adalah milik ruang pengguna

2) Kawasan ingatan yang ditunjuk oleh jarum meter berada di ruang alamat proses

3) Jika ia membaca, ingatan baca hendaklah ditandakan sebagai boleh dibaca. Jika menulis, ingatan video hendaklah ditandakan sebagai boleh ditulis.

Inti menyediakan dua cara untuk melengkapkan pengesanan yang diperlukan dan menyalin data berulang-alik antara ruang kernel dan ruang pengguna. Salah satu daripada dua kaedah ini mesti dipanggil.

内核调用用户态函数_内核调用call_linux 内核调用

copy_to_user(): Tulis data ke ruang pengguna, memerlukan 3 parameter. Parameter pertama ialah alamat memori destinasi dalam ruang proses. Yang kedua ialah alamat sumber dalam ruang kernel

.Yang ketiga ialah lebar data (bilangan bait) yang perlu disalin.

copy_from_user(): Membaca data dari ruang pengguna memerlukan 3 parameter. Parameter pertama ialah alamat memori destinasi dalam ruang proses. Yang kedua ialah sumber dalam ruang kernel

Alamat yang ketiga ialah lebar data (bilangan bait) yang perlu disalin.

Nota: Kedua-dua ini boleh menyebabkan halangan. Situasi ini berlaku apabila halaman yang mengandungi data pengguna ditukar kepada cakera dan bukannya dalam memori matematik. Pada masa ini, linux kernel memanggil, dan proses akan tidur sehingga pengendali kesalahan halaman menggantikan halaman dari cakera keras kembali ke memori kimia.

Inti dalam konteks proses semasa melaksanakan panggilan sistem, dan penunjuk semasa menghala ke tugas semasa, iaitu proses yang menyebabkan panggilan sistem. Dalam konteks proses, kernel boleh tidur (seperti apabila panggilan sistem menyekat atau secara eksplisit memanggil jadual()) tetapi boleh diduduki. Apabila panggilan sistem kembali, kawalan kekal dalam system_call(), yang akhirnya bertanggungjawab untuk beralih kepada ruang pengguna dan membenarkan proses pengguna untuk terus melaksanakan.

Sangat mudah untuk menambah masa panggilan sistem pada Linux Cara mereka bentuk dan melaksanakan panggilan sistem adalah dilema. Langkah pertama dalam melaksanakan panggilan sistem ialah menentukan tujuannya. Tujuan ini harus jelas dan unik. Jangan cuba menulis panggilan sistem pelbagai guna. ioctl ialah bahan pengajaran bahagian belakang. Parameter, nilai pulangan dan kod ralat panggilan sistem baharu adalah sangat penting. Sebaik sahaja panggilan sistem disusun, mendaftarkannya sebagai panggilan sistem akan datang adalah tugas yang membosankan, biasanya mengikut langkah berikut:

1) Tambahkan entri di penghujung jadual panggilan sistem (biasanya terletak di entri.s). Mengira dari 0, kedudukan kemasukan sistem dalam jadual ialah nombor panggilan sistemnya. Seperti yang pertama

10 panggilan sistem diberikan kepada panggilan sistem nombor 9

2) Untuk sebarang seni bina, nombor panggilan sistem mesti ditakrifkan dalam include/asm/unistd.h

3) Panggilan sistem mesti dikompilasi ke dalam imej kernel (tidak boleh dikompilasi ke dalam modul). Ini hanya perlu dimasukkan ke dalam fail berkaitan di bawah kernel/.

Secara amnya, panggilan sistem disokong oleh pustaka C Program pengguna boleh menggunakan panggilan sistem (atau menggunakan fungsi perpustakaan, yang kemudiannya dipanggil) dengan memasukkan fail pengepala standard dan memautkan dengan perpustakaan C. Nasib baik, Linux sendiri menyediakan satu set makro untuk akses terus kepada panggilan sistem. Ia akan menetapkan daftar dan memanggil arahan int$0x80. Makro ini ialah _syscalln(), dengan n berjulat dari 0 hingga 6. Ia mewakili bilangan parameter yang perlu dihantar kepada panggilan sistem. Ini kerana makro mesti mengetahui dengan tepat berapa banyak hujah yang ditolak ke dalam daftar dan dalam susunan yang mana. Ambil panggilan sistem terbuka sebagai contoh:

Panggilan sistem open() ditakrifkan seperti berikut:

longopen(constchar*nama fail,intflags,intmode)

Cara untuk terus memanggil makro panggilan sistem ini ialah:

#defineNR_open5

_syscall3(panjang,buka,constchar*,nama fail,int,bendera,int,mod)

Dengan cara ini, aplikasi boleh terus menggunakan open(). Cuma panggil panggilan sistem open() dan terus letakkan makro di dalam aplikasi. Untuk setiap makro, terdapat 2+2*n parameter. Maksud setiap parameter adalah mudah dan jelas, dan tidak akan diterangkan secara terperinci di sini.

Atas ialah kandungan terperinci Panggilan sistem dalam Linux bukan kemasukan sah ke dalam kernel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:itcool.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam