Saya mencoba memahami bagaimana suatu fungsi, katakanlah mkdir
, bekerja dengan melihat sumber kernel. Ini adalah upaya untuk memahami internal kernel dan menavigasi di antara berbagai fungsi. Saya tahu mkdir
didefinisikan dalam sys/stat.h
. Saya menemukan prototipenya:
/* 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 file C mana 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);
Tetapi tidak satupun dari mereka yang cocok dengan definisi di sys/stat.h
.
Pertanyaan
- Berkas mana yang memiliki
mkdir
implementasi? - Dengan definisi fungsi seperti di atas, bagaimana cara 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.
Jawaban yang Diterima:
Panggilan sistem tidak ditangani seperti panggilan fungsi biasa. Dibutuhkan kode khusus untuk membuat transisi dari ruang pengguna ke ruang kernel, pada dasarnya sedikit kode perakitan inline yang disuntikkan ke dalam program Anda di situs panggilan. Kode sisi 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 sumber 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. Artinya, panggilan sistem dipanggil dengan nomor, bukan dengan alamat seperti panggilan fungsi normal dalam program Anda sendiri atau ke fungsi di perpustakaan yang terhubung ke program Anda. Kode lem perakitan sebaris yang saya sebutkan di atas menggunakan ini untuk membuat transisi dari pengguna ke ruang kernel, dengan membawa parameter Anda bersamanya.
Sedikit bukti lain bahwa ada 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 artinya open(2)
kelebihan beban, fitur C++, bukan C, namun antarmuka syscall kompatibel dengan C. (Ini tidak sama dengan fitur varargs C, yang memungkinkan satu fungsi mengambil sejumlah argumen yang bervariasi.)
Untuk menjawab pertanyaan pertama Anda, tidak ada satu file pun 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 satu panggilan sistem 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. Misalnya, implementasi ext4 disebut ext4_mkdir()
, didefinisikan dalam fs/ext4/namei.c
.
Adapun pertanyaan kedua Anda, ya ada pola untuk semua ini, tetapi tidak ada satu aturan pun. 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 di fs/namei.c
. mmap(2)
, misalnya, dimulai di mm/mmap.c
, karena ini adalah bagian dari subsistem manajemen memori (“mm”) kernel.
Saya sarankan Anda mendapatkan salinan "Memahami Kernel Linux" oleh Bovet dan Cesati.