it-swarm-id.com

Bagaimana saya bisa menemukan implementasi panggilan sistem kernel Linux?

Saya mencoba memahami bagaimana fungsi, katakan mkdir, bekerja dengan melihat sumber kernel. Ini adalah upaya untuk memahami internal kernel dan bernavigasi di antara berbagai fungsi. Saya tahu mkdir didefinisikan dalam sys/stat.h. Saya menemukan prototipe:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

Sekarang saya perlu melihat di mana file C fungsi ini diimplementasikan. Dari direktori sumber, saya mencoba

ack "int mkdir"

yang ditampilkan

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

Tapi tidak ada yang cocok dengan definisi di sys/stat.h.

Pertanyaan

  1. File mana yang memiliki implementasi mkdir?
  2. Dengan definisi fungsi seperti di atas, bagaimana saya bisa mengetahui file mana yang memiliki implementasi? Apakah ada pola yang diikuti kernel dalam mendefinisikan dan mengimplementasikan metode?

CATATAN: Saya menggunakan kernel 2.6.36-rc1 .

376
Navaneeth K N

Panggilan sistem tidak ditangani seperti panggilan fungsi biasa. Dibutuhkan kode khusus untuk melakukan transisi dari ruang pengguna ke ruang kernel, pada dasarnya sedikit kode Majelis inline yang disuntikkan ke program Anda di situs panggilan. Kode samping kernel yang "menangkap" panggilan sistem juga merupakan hal-hal tingkat rendah yang mungkin tidak perlu Anda pahami secara mendalam, setidaknya pada awalnya.

Di include/linux/syscalls.h di bawah direktori source kernel Anda, Anda menemukan ini:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

Kemudian di /usr/include/asm*/unistd.h, Anda menemukan ini:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Kode ini mengatakan mkdir(2) adalah panggilan sistem # 83. Dengan kata lain, panggilan sistem dipanggil dengan nomor, bukan dengan alamat seperti dengan panggilan fungsi normal di dalam program Anda sendiri atau ke fungsi di perpustakaan yang terhubung dengan program Anda. Kode lem inline Assembly yang saya sebutkan di atas menggunakan ini untuk melakukan transisi dari ruang pengguna ke kernel, dengan mengambil parameter Anda.

Sedikit bukti lain yang sedikit aneh di sini adalah tidak selalu ada daftar parameter yang ketat untuk panggilan sistem: open(2), misalnya, dapat mengambil 2 atau 3 parameter. Itu berarti open(2) adalah kelebihan beban , fitur C++, bukan C, namun antarmuka syscall kompatibel dengan C. (Ini bukan hal yang sama dengan C's fitur varargs , yang memungkinkan fungsi tunggal untuk mengambil sejumlah variabel argumen.)

Untuk menjawab pertanyaan pertama Anda, tidak ada file tunggal di mana mkdir() ada. Linux mendukung banyak sistem file yang berbeda dan masing-masing memiliki implementasi sendiri dari operasi "mkdir". Lapisan abstraksi yang memungkinkan kernel menyembunyikan semua yang ada di balik panggilan sistem tunggal disebut VFS . Jadi, Anda mungkin ingin mulai menggali fs/namei.c, Dengan vfs_mkdir(). Implementasi aktual dari kode modifikasi sistem file tingkat rendah ada di tempat lain. Sebagai contoh, implementasi ext4 disebut ext4_mkdir(), didefinisikan dalam fs/ext4/namei.c .

Adapun pertanyaan kedua Anda, ya ada pola untuk semua ini, tetapi tidak ada aturan tunggal. Apa yang sebenarnya Anda butuhkan adalah pemahaman yang cukup luas tentang cara kerja kernel untuk mencari tahu di mana Anda harus mencari panggilan sistem tertentu. Tidak semua panggilan sistem melibatkan VFS, jadi rantai panggilan sisi-kernelnya tidak semuanya dimulai dari fs/namei.c. mmap(2), misalnya, dimulai pada mm/mmap.c , karena ini adalah bagian dari subsistem manajemen memori ("mm") dari kernel.

Saya sarankan Anda mendapatkan salinan " Memahami Kernel Linux " oleh Bovet dan Cesati.

388
Warren Young

Ini mungkin tidak menjawab pertanyaan Anda secara langsung, tetapi saya telah menemukan strace sangat keren ketika mencoba memahami panggilan sistem yang mendasarinya, dalam tindakan, yang dibuat bahkan untuk perintah Shell yang paling sederhana sekalipun. misalnya.

strace -o trace.txt mkdir mynewdir

Sistem memanggil perintah mkdir mynewdir akan dibuang ke trace.txt untuk kesenangan menonton Anda.

86
Banjer

Tempat yang baik untuk membaca sumber kernel Linux adalah Linux cross-reference (LXR) ¹. Pencarian mengembalikan kecocokan yang diketik (prototipe fungsi, deklarasi variabel, dll.) Selain hasil pencarian teks gratis, jadi lebih mudah daripada hanya grep (dan lebih cepat juga).

LXR tidak memperluas definisi preprosesor. Panggilan sistem memiliki nama mereka hancur oleh preprocessor di semua tempat. Namun, sebagian besar (semua?) Panggilan sistem ditentukan dengan salah satu SYSCALL_DEFINEx keluarga makro. Karena mkdir membutuhkan dua argumen, pencarian untuk SYSCALL_DEFINE2(mkdir mengarah ke deklarasi mkdir syscall :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

baik, sys_mkdirat berarti itu adalah mkdirat syscall, jadi mengkliknya hanya akan membawa Anda ke deklarasi di include/linux/syscalls.h, tetapi definisinya tepat di atas.

Pekerjaan utama mkdirat adalah memanggil vfs_mkdir (VFS adalah lapisan sistem file generik). Menyukai yang menunjukkan dua hasil pencarian: deklarasi di include/linux/fs.h, dan definisi beberapa baris di atas. Pekerjaan utama vfs_mkdir adalah untuk memanggil implementasi spesifik sistem file: dir->i_op->mkdir. Untuk mengetahui bagaimana ini diimplementasikan, Anda perlu beralih ke implementasi sistem file individual, dan tidak ada aturan keras-dan-cepat - bahkan bisa menjadi modul di luar pohon kernel.

¹ LXR adalah program pengindeksan. Ada beberapa situs web yang menyediakan antarmuka untuk LXR, dengan set versi yang sedikit berbeda dan antarmuka web yang sedikit berbeda. Mereka cenderung datang dan pergi, jadi jika yang Anda gunakan tidak tersedia, lakukan pencarian web untuk "referensi silang linux" untuk menemukan yang lain.

Panggilan sistem biasanya dibungkus dengan SYSCALL_DEFINEx() macro, itulah mengapa grep sederhana tidak menemukannya:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

Nama fungsi akhir setelah makro diperluas akhirnya menjadi sys_mkdir. Makro SYSCALL_DEFINEx() menambahkan hal-hal seperti boilerplate yang harus dimiliki oleh setiap definisi syscall.

22
stefanha

Catatan: file .h tidak define fungsi. Ini dinyatakan dalam file .h itu dan didefinisikan (diterapkan) di tempat lain. Ini memungkinkan kompiler untuk memasukkan informasi tentang tanda tangan fungsi (prototipe) untuk memungkinkan pemeriksaan jenis argumen dan mencocokkan jenis yang dikembalikan ke konteks panggilan apa pun dalam kode Anda.

Secara umum .h (header) file dalam C digunakan untuk mendeklarasikan fungsi dan mendefinisikan makro.

mkdir khususnya adalah panggilan sistem. Mungkin ada GNU libc wrapper di sekitar pemanggilan sistem itu (hampir pasti adalah, pada kenyataannya). Implementasi kernel yang sebenarnya dari mkdir dapat ditemukan dengan mencari sumber kernel dan panggilan sistem pada khususnya.

Perhatikan bahwa juga akan ada implementasi semacam kode pembuatan direktori untuk setiap sistem file. Lapisan VFS (sistem file virtual) menyediakan API umum yang dapat dipanggil oleh lapisan sistem panggilan. Setiap sistem file harus mendaftarkan fungsi untuk lapisan VFS untuk dipanggil. Ini memungkinkan sistem file yang berbeda untuk mengimplementasikan semantik mereka sendiri untuk bagaimana direktori disusun (misalnya jika mereka disimpan menggunakan semacam skema hashing untuk membuat pencarian entri tertentu lebih efisien). Saya menyebutkan ini karena Anda mungkin akan tersandung fungsi pembuatan direktori spesifik sistem file ini jika Anda mencari pohon kode sumber Linux.

17
Jim Dennis

Tidak ada implementasi yang Anda temukan cocok dengan prototipe di sys/stat.h Mungkin mencari pernyataan sertakan dengan file header ini akan lebih sukses?

8
greg0ire

Berikut adalah beberapa posting blog yang sangat bagus yang menggambarkan berbagai teknik untuk memburu kode sumber kernel tingkat rendah.

6
An̲̳̳drew