Pengantar Sistem Operasi
Hai Habr! Saya ingin menyampaikan kepada Anda serangkaian artikel-terjemahan dari salah satu literatur yang menarik menurut saya - OSTEP. Materi ini membahas cukup mendalam tentang cara kerja sistem operasi mirip unix, yaitu bekerja dengan proses, berbagai penjadwal, memori, dan komponen serupa lainnya yang membentuk sebuah OS modern. Anda dapat melihat semua materi asli di sini
Pekerjaan laboratorium mengenai hal ini dapat ditemukan di sini:
Bagian lain:
Anda juga dapat memeriksa saluran saya di
Alarm! Ada laboratorium untuk kuliah ini! Lihat
API Proses
Mari kita lihat contoh pembuatan proses dalam sistem UNIX. Itu terjadi melalui dua panggilan sistem garpu() ΠΈ exec ().
Garpu panggilan()
Pertimbangkan sebuah program yang membuat panggilan fork(). Hasil pelaksanaannya adalah sebagai berikut.
Pertama-tama, kita masuk ke fungsi main() dan mencetak string ke layar. Baris tersebut berisi pengidentifikasi proses yang dalam bahasa aslinya disebut PID atau pengenal proses. Pengidentifikasi ini digunakan di UNIX untuk merujuk ke suatu proses. Perintah selanjutnya akan memanggil fork(). Pada titik ini, salinan proses yang hampir sama persis dibuat. Untuk OS, sepertinya ada 2 salinan program yang sama yang berjalan di sistem, yang selanjutnya akan keluar dari fungsi fork(). Proses anak yang baru dibuat (sehubungan dengan proses induk yang membuatnya) tidak akan lagi dieksekusi, dimulai dari fungsi main(). Harus diingat bahwa proses anak bukanlah salinan persis dari proses induk; khususnya, ia mempunyai ruang alamatnya sendiri, registernya sendiri, penunjuknya sendiri ke instruksi yang dapat dieksekusi, dan sejenisnya. Dengan demikian, nilai yang dikembalikan ke pemanggil fungsi fork() akan berbeda. Secara khusus, proses induk akan menerima nilai PID dari proses anak sebagai pengembalian, dan anak tersebut akan menerima nilai yang sama dengan 0. Dengan menggunakan kode pengembalian ini, Anda kemudian dapat memisahkan proses dan memaksa masing-masing proses untuk melakukan tugasnya sendiri. . Namun, pelaksanaan program ini tidak didefinisikan secara ketat. Setelah dibagi menjadi 2 proses, OS mulai memantaunya, serta merencanakan pekerjaannya. Jika dijalankan pada prosesor inti tunggal, salah satu proses, dalam hal ini proses induk, akan terus bekerja, dan kemudian proses anak akan menerima kendali. Saat memulai ulang, situasinya mungkin berbeda.
Panggilan tunggu()
Perhatikan program berikut ini. Dalam program ini, karena adanya panggilan tunggu() Proses induk akan selalu menunggu hingga proses anak selesai. Dalam hal ini, kita akan mendapatkan keluaran teks yang ditentukan secara ketat di layar
exec() panggilan
Pertimbangkan tantangannya exec (). System call ini berguna ketika kita ingin menjalankan program yang benar-benar berbeda. Di sini kami akan menelepon eksekutif() untuk menjalankan program wc yang merupakan program penghitungan kata. Apa yang terjadi ketika exec() dipanggil? Panggilan ini meneruskan nama file yang dapat dieksekusi dan beberapa parameter sebagai argumen. Setelah itu kode dan data statis dari file yang dapat dieksekusi ini dimuat dan segmennya sendiri dengan kode tersebut ditimpa. Area memori yang tersisa, seperti tumpukan dan heap, diinisialisasi ulang. Setelah itu OS hanya mengeksekusi program tersebut, meneruskan serangkaian argumen. Jadi kami tidak membuat proses baru, kami hanya mengubah program yang sedang berjalan menjadi program lain yang sedang berjalan. Setelah menjalankan panggilan exec() di turunannya, tampaknya program aslinya tidak berjalan sama sekali.
Komplikasi startup ini sepenuhnya normal untuk shell Unix, dan memungkinkan shell tersebut mengeksekusi kode setelah dipanggil garpu(), tapi sebelum panggilan exec (). Contoh kode tersebut adalah menyesuaikan lingkungan shell dengan kebutuhan program yang diluncurkan, sebelum meluncurkannya.
Kulit - hanya program pengguna. Dia menunjukkan baris undangan dan menunggu Anda menulis sesuatu di dalamnya. Dalam kebanyakan kasus, jika Anda menulis nama program di sana, shell akan menemukan lokasinya, memanggil metode fork(), dan kemudian memanggil beberapa jenis exec() untuk membuat proses baru dan menunggu hingga selesai menggunakan a tunggu() panggilan. Ketika proses anak keluar, shell akan kembali dari panggilan wait() dan mencetak prompt lagi dan menunggu perintah selanjutnya dimasukkan.
Perpecahan fork() & exec() memungkinkan shell melakukan hal-hal berikut, misalnya:
file wc > file_baru.
Dalam contoh ini, output dari program wc dialihkan ke sebuah file. Cara shell mencapai hal ini cukup sederhana - dengan membuat proses anak sebelum memanggil exec (), shell menutup keluaran standar dan membuka file file baru, dengan demikian, semua keluaran dari program yang berjalan selanjutnya wc akan dialihkan ke file, bukan ke layar.
pipa Unix diimplementasikan dengan cara yang sama, dengan perbedaan bahwa mereka menggunakan panggilan pipe(). Dalam hal ini, aliran keluaran proses akan dihubungkan ke antrian pipa yang terletak di kernel, dimana aliran masukan dari proses lain akan dihubungkan.
Sumber: www.habr.com