Biarkan saya memecahnya.
Saat Anda menjalankan yang dapat dieksekusi, urutan panggilan sistem dijalankan, terutama fork()
dan execve()
:
fork()
menciptakan proses turunan dari proses pemanggilan, yang (sebagian besar) merupakan salinan persis dari induknya, keduanya masih menjalankan executable yang sama (menggunakan halaman memori copy-on-write, sehingga efisien). Ini mengembalikan dua kali: Pada induknya, ia mengembalikan PID anak. Pada anak, itu mengembalikan 0. Biasanya, proses panggilan anak mengeksekusi segera:
execve()
mengambil path lengkap ke executable sebagai argumen dan menggantikan proses pemanggilan dengan executable. Pada titik ini proses yang baru dibuat mendapatkan ruang alamat virtual sendiri yaitu memori virtual, dan eksekusi dimulai pada titik masuknya (dalam keadaan yang ditentukan oleh platform aturan ABI untuk proses baru).
Pada titik ini, ELF loader kernel telah memetakan segmen teks dan data yang dapat dieksekusi ke dalam memori, seolah-olah ia telah menggunakan mmap()
panggilan sistem (masing-masing dengan pemetaan read-only dan private read-write). BSS juga dipetakan seolah-olah dengan MAP_ANONYMOUS. (BTW, saya mengabaikan tautan dinamis di sini untuk kesederhanaan: Linker dinamis open()
s dan mmap()
semua perpustakaan dinamis sebelum melompat ke titik masuk utama yang dapat dieksekusi.)
Hanya beberapa halaman yang benar-benar dimuat ke dalam memori dari disk sebelum yang baru dijalankan () ed mulai menjalankan kodenya sendiri. Halaman selanjutnya adalah halaman permintaan sesuai kebutuhan, jika / ketika proses menyentuh bagian-bagian dari ruang alamat virtualnya. (Pra-memuat halaman kode atau data apa pun sebelum mulai mengeksekusi kode ruang pengguna hanya merupakan pengoptimalan kinerja.)
File yang dapat dieksekusi diidentifikasi oleh inode pada level yang lebih rendah. Setelah file mulai dieksekusi, kernel menjaga konten file tetap utuh dengan referensi inode, bukan dengan nama file, seperti untuk deskriptor file terbuka atau pemetaan memori yang didukung file. Jadi Anda dapat dengan mudah memindahkan executable ke lokasi lain dari sistem file atau bahkan pada sistem file yang berbeda. Sebagai catatan tambahan, untuk memeriksa berbagai stat proses, Anda dapat mengintip ke /proc/PID
direktori (PID adalah ID Proses dari proses yang diberikan). Anda bahkan dapat membuka file yang dapat dieksekusi sebagai /proc/PID/exe
, bahkan sudah dihapus dari disk.
Sekarang mari kita gali langkahnya:
Saat Anda memindahkan file dalam sistem file yang sama, panggilan sistem yang dijalankan adalah rename()
, yang hanya mengganti nama file ke nama lain, inode file tetap sama.
Sedangkan antara dua sistem file yang berbeda, dua hal terjadi:
Konten file yang disalin terlebih dahulu ke lokasi baru, oleh read()
danwrite()
Setelah itu, file tidak terhubung dari direktori sumber menggunakan unlink()
dan jelas file tersebut akan mendapatkan inode baru pada sistem file baru.
rm
sebenarnya hanya unlink()
-ing file yang diberikan dari pohon direktori, jadi memiliki izin menulis pada direktori akan membuat Anda cukup untuk menghapus file dari direktori itu.
Sekarang untuk bersenang-senang, bayangkan apa yang terjadi ketika Anda memindahkan file antara dua file files dan Anda tidak memiliki izin untuk unlink()
file dari sumber?
Nah, file akan disalin ke tujuan pada awalnya ( read()
, write()
) dan kemudian unlink()
akan gagal karena izin tidak mencukupi. Jadi, file tersebut akan tetap berada di kedua sistem file !!