Pengantar Sistem Operasi
Halo, Habr! Saya ingin menarik perhatian Anda serangkaian artikel-terjemahan dari satu literatur yang menarik menurut saya - OSTEP. Artikel ini membahas lebih dalam karya sistem operasi mirip-unix, yaitu, bekerja dengan proses, berbagai penjadwal, memori, dan komponen serupa lainnya yang membentuk OS modern. Asli semua bahan bisa Anda lihat di
sini . Harap dicatat bahwa terjemahannya dilakukan secara tidak profesional (cukup bebas), tetapi saya harap saya tetap memiliki makna umum.
Pekerjaan laboratorium tentang hal ini dapat ditemukan di sini:
Bagian lain:
Dan Anda dapat melihat saluran saya di
telegram =)
Alarm! Ada laboratorium untuk kuliah ini! menonton
githubAPI proses
Pertimbangkan contoh membuat proses pada sistem UNIX. Ini terjadi melalui dua system call
fork () dan
exec () .
Panggilan Fork ()

Pertimbangkan program yang melakukan panggilan fork (). Hasil implementasinya adalah sebagai berikut.

Pertama-tama, kita memasuki fungsi utama () dan menjalankan output dari string ke layar. String berisi pengenal proses, yang dalam aslinya disebut
PID atau pengidentifikasi proses. Identifier ini digunakan pada UNIX untuk merujuk pada suatu proses. Perintah selanjutnya akan memanggil fork (). Pada titik ini, salinan proses yang hampir pasti dibuat. Untuk OS, sepertinya sistem berjalan seolah-olah 2 salinan dari program yang sama, yang pada gilirannya akan keluar dari fungsi fork (). Proses anak yang baru dibuat (relatif terhadap proses induk yang membuatnya) tidak akan lagi dijalankan, dimulai dengan fungsi main (). Harus diingat bahwa proses anak bukanlah salinan persis dari proses induk, khususnya, ia memiliki ruang alamat sendiri, register sendiri, penunjuk sendiri untuk 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 akan menerima nilai yang sama dengan 0. Berdasarkan kode pengembalian ini, sudah dimungkinkan untuk memisahkan proses dan memaksa masing-masing dari mereka untuk melakukan pekerjaan mereka. Selain itu, pelaksanaan program ini tidak sepenuhnya ditentukan. Setelah membagi menjadi 2 proses, OS mulai mengikuti mereka, juga, dan merencanakan pekerjaan mereka. Jika dijalankan pada prosesor single-core, salah satu proses akan terus bekerja, dalam hal ini, orang tua, dan kemudian proses anak akan menerima kontrol. Ketika Anda memulai ulang, situasinya mungkin berbeda.
Panggilan tunggu ()

Pertimbangkan program berikut. Dalam program ini, karena kehadiran panggilan
tunggu () , proses induk akan selalu menunggu proses anak untuk menyelesaikan pekerjaannya. Dalam hal ini, kami mendapatkan output teks yang didefinisikan dengan ketat ke layar.

Panggil eksekutif ()

Pertimbangkan panggilan ke
exec () . Panggilan sistem ini berguna ketika kita ingin menjalankan program yang sama sekali berbeda. Di sini kita akan memanggil
execvp () untuk menjalankan program wc, yang merupakan program penghitungan kata. Apa yang terjadi ketika exec () dipanggil? Nama file yang dapat dieksekusi dan beberapa parameter diteruskan ke panggilan ini sebagai argumen. Setelah itu, kode dan data statis dari file yang dapat dieksekusi ini diunduh dan segmennya sendiri dengan kode ditimpa. Bagian memori yang tersisa, seperti tumpukan dan tumpukan, diinisialisasi ulang. Setelah itu OS hanya menjalankan program, melewatinya serangkaian argumen. Jadi, kami tidak membuat proses baru, kami hanya mengubah program yang sedang berjalan menjadi program yang berjalan lainnya. Setelah exec () dieksekusi, turunan memberi kesan bahwa program aslinya sepertinya tidak dimulai secara prinsip.
Komplikasi peluncuran ini benar-benar normal untuk shell Unix, dan memungkinkan shell ini untuk mengeksekusi kode setelah memanggil
fork () , tetapi sebelum memanggil
exec () . Contoh dari kode tersebut dapat menyesuaikan lingkungan shell dengan kebutuhan program yang diluncurkan, sebelum meluncurkannya secara langsung.
Shell hanyalah program pengguna. Dia menunjukkan kepada Anda baris prompt dan menunggu Anda untuk menulis sesuatu untuk itu. Dalam kebanyakan kasus, jika Anda menulis nama program di sana, shell akan menemukan lokasinya, memanggil metode fork (), dan kemudian, untuk membuat proses baru, ia akan memanggil beberapa jenis exec () dan menunggu untuk dieksekusi menggunakan panggilan wait (). Ketika proses anak berakhir, shell kembali dari panggilan wait () dan menampilkan prompt lagi dan menunggu perintah selanjutnya dimasukkan.
Memisahkan garpu () & exec () memungkinkan shell untuk melakukan hal-hal berikut, misalnya:
file wc> new_file.Dalam contoh ini, output dari wc diarahkan ke file. Cara shell mencapai ini cukup sederhana - saat membuat proses anak sebelum memanggil
exec () , shell menutup aliran output standar dan membuka file
new_file , sehingga semua output dari program
wc yang dijalankan akan diarahkan ke file alih-alih layar.
Pipa unix diimplementasikan dengan cara yang sama, dengan perbedaan bahwa mereka menggunakan panggilan pipe (). Dalam hal ini, aliran output dari proses akan terhubung ke antrian pipa yang terletak di kernel dimana aliran input dari proses lain akan dilampirkan.