Di Unix setiap kali kita ingin membuat proses baru, kita memotong proses saat ini, membuat proses anak baru yang persis sama dengan proses induk; kemudian kami melakukan panggilan sistem exec untuk mengganti semua data dari proses induk dengan yang untuk proses baru.
Mengapa kita membuat salinan dari proses induk di tempat pertama dan tidak membuat proses baru secara langsung?
process
architecture
fork
sarthak
sumber
sumber
Jawaban:
Jawaban singkatnya adalah,
fork
ada di Unix karena mudah masuk ke sistem yang ada saat itu, dan karena sistem pendahulunya di Berkeley menggunakan konsep garpu.Dari Evolusi Sistem Berbagi Waktu Unix (teks yang relevan telah disorot ):
Sejak kertas itu, Unix telah berevolusi.
fork
diikutiexec
bukan lagi satu-satunya cara untuk menjalankan program.vfork diciptakan untuk menjadi garpu yang lebih efisien untuk kasus di mana proses baru bermaksud untuk melakukan exec tepat setelah garpu. Setelah melakukan vfork, proses induk dan anak berbagi ruang data yang sama, dan proses induk ditangguhkan hingga proses anak mengeksekusi program atau keluar.
posix_spawn membuat proses baru dan mengeksekusi file dalam satu panggilan sistem. Dibutuhkan banyak parameter yang memungkinkan Anda secara selektif berbagi file terbuka pemanggil dan menyalin disposisi sinyalnya dan atribut lainnya ke proses baru.
sumber
posix_spawn()
untuk melakukan pekerjaan post-fork replumbing yang sama yang dapat dilakukan dengan mudah menggunakanfork()
dan kode inline membuat argumen yang meyakinkan untukfork()
menjadi lebih mudah digunakan.[Aku akan mengulangi sebagian dari jawabanku dari sini .]
Mengapa tidak hanya memiliki perintah yang menciptakan proses baru dari awal? Bukankah tidak masuk akal dan tidak efisien untuk menyalin satu yang hanya akan segera diganti?
Bahkan, itu mungkin tidak seefisien karena beberapa alasan:
"Copy" yang diproduksi oleh
fork()
adalah sedikit abstraksi, karena kernel menggunakan copy-on-write sistem ; semua yang benar-benar harus dibuat adalah peta memori virtual. Jika salinan kemudian segera memanggilexec()
, sebagian besar data yang akan disalin jika telah dimodifikasi oleh aktivitas proses tidak pernah benar-benar harus disalin / dibuat karena proses tidak melakukan apa pun yang memerlukan penggunaannya.Berbagai aspek penting dari proses anak (misalnya, lingkungannya) tidak harus diduplikasi secara individual atau ditetapkan berdasarkan analisis konteks yang kompleks, dll. Mereka hanya diasumsikan sama dengan proses pemanggilan, dan ini adalah sistem yang cukup intuitif yang kita kenal.
Untuk menjelaskan # 1 sedikit lebih jauh, memori yang "disalin" tetapi tidak pernah diakses tidak pernah benar-benar disalin, setidaknya dalam banyak kasus. Pengecualian dalam konteks ini mungkin jika Anda melakukan proses bercabang, maka proses induk harus keluar sebelum anak diganti dengan sendiri
exec()
. Saya katakan mungkin karena banyak dari orang tua bisa di-cache jika ada memori bebas yang cukup, dan saya tidak yakin sejauh mana ini akan dieksploitasi (yang akan tergantung pada implementasi OS).Tentu saja, itu tidak di permukaan membuat menggunakan salinan lebih efisien daripada menggunakan batu tulis kosong - kecuali "batu tulis kosong" secara harfiah bukan apa-apa, dan harus melibatkan alokasi. Sistem dapat memiliki templat proses kosong / baru generik yang disalin dengan cara yang sama, 1 tetapi kemudian tidak akan benar-benar menyimpan apa pun dibandingkan garpu copy-on-write. Jadi # 1 hanya menunjukkan bahwa menggunakan proses kosong "baru" tidak akan lebih efisien.
Butir # 2 menjelaskan mengapa menggunakan garpu kemungkinan lebih efisien. Lingkungan anak diwarisi dari orang tuanya, bahkan jika itu adalah eksekusi yang sama sekali berbeda. Misalnya, jika proses induk adalah shell, dan anak itu browser web,
$HOME
masih sama untuk keduanya, tetapi karena keduanya kemudian dapat mengubahnya, ini harus dua salinan terpisah. Yang ada di anak diproduksi oleh aslinyafork()
.1. Strategi yang mungkin tidak masuk akal secara literal, tetapi poin saya adalah menciptakan sebuah proses melibatkan lebih dari menyalin gambar itu ke dalam memori dari disk.
sumber
fork()
dapat sangat cepat (seperti yang disebutkan GL, pada urutan 27 jalur perakitan). Melihat ke arah lain, jika Anda ingin "membuat proses dari awal,"fork()
harganya hanya sedikit lebih dari mulai dari proses yang dibuat kosong (27 baris perakitan + biaya penutupan pegangan file). Jadi,fork
menangani kedua garpu dan membuat dengan baik, sementaracreate
hanya bisa menangani membuat dengan baik.fork
sebenarnya disalin semua memori proses, dan itu sangat mahal.Saya pikir alasan Unix hanya memiliki
fork
fungsi untuk menciptakan proses baru adalah hasil dari filosofi UnixMereka membangun satu fungsi yang melakukan satu hal dengan baik. Itu menciptakan proses anak.
Apa yang dilakukan seseorang dengan proses baru kemudian tergantung pada programmer. Dia dapat menggunakan salah satu
exec*
fungsi dan memulai program yang berbeda, atau dia tidak dapat menggunakan exec dan menggunakan dua contoh dari program yang sama, yang dapat bermanfaat.Jadi Anda mendapatkan tingkat kebebasan yang lebih besar karena Anda bisa menggunakannya
dan selain itu Anda hanya perlu mengingat
fork
danexec*
panggilan fungsi, yang pada tahun 1970-an harus Anda lakukan.sumber
Ada dua filosofi penciptaan proses: bercabang dengan warisan, dan berkreasi dengan argumen. Unix menggunakan garpu, jelas. (OSE, misalnya, dan VMS menggunakan metode create.) Unix memiliki karakteristik bawaan BANYAK, dan lebih banyak lagi ditambahkan secara berkala. Melalui pewarisan, karakteristik baru ini dapat ditambahkan TANPA MENGUBAH PROGRAM YANG ADA! Menggunakan model buat-dengan-argumen, menambahkan karakteristik baru berarti menambahkan argumen baru ke panggilan buat. Model Unix lebih sederhana.
Ini juga memberi model fork-without-exec yang sangat berguna, di mana suatu proses dapat membagi dirinya menjadi beberapa bagian. Ini sangat penting ketika tidak ada async I / O, dan berguna ketika mengambil keuntungan dari banyak CPU dalam suatu sistem. (Pra-utas.) Saya telah melakukan ini banyak selama bertahun-tahun, bahkan baru-baru ini. Pada dasarnya itu memungkinkan untuk menggabungkan beberapa 'program' ke dalam satu program, sehingga sama sekali tidak ada ruang untuk korupsi atau ketidakcocokan versi, dll.
Model fork / exec juga memberikan kemampuan bagi anak tertentu untuk mewarisi lingkungan yang secara radikal aneh, mengatur antara fork dan exec. Hal-hal seperti deskriptor file yang diwarisi, khususnya. (Perpanjangan dari stdio fd's.) Model create tidak menawarkan kemampuan untuk mewarisi apa pun yang tidak dibayangkan oleh pencipta panggilan buat.
Beberapa sistem juga dapat mendukung kompilasi dinamis kode asli, di mana proses ini berlaku menulis program kode asli sendiri. Dengan kata lain, ia menginginkan program baru yang sedang menulis sendiri, TANPA harus melalui siklus kode-sumber / kompiler / penghubung, dan menempati ruang disk. (Saya percaya ada sistem bahasa Verilog yang melakukan ini.) Model garpu mendukung ini, model buatan biasanya tidak.
sumber
Fungsi garpu () tidak hanya untuk menyalin proses ayah, itu mengembalikan nilai yang merujuk bahwa proses adalah proses ayah atau anak, gambar di bawah ini menjelaskan bagaimana Anda dapat menggunakan garpu () sebagai ayah dan putra:
seperti yang ditunjukkan ketika proses adalah ayah garpu () mengembalikan proses ID anak yang
PID
lain itu kembali0
misalnya Anda dapat memanfaatkannya jika Anda memiliki proses (server web) yang menerima permintaan dan pada setiap permintaan itu dibuat
son process
untuk memproses permintaan ini, di sini ayah dan anak-anaknya memiliki pekerjaan yang berbeda.SO, tidak menjalankan salinan proses bukanlah hal yang tepat seperti garpu ().
sumber
fork
jika Anda menganggap Anda inginfork
di tempat pertamaPengalihan I / O paling mudah diimplementasikan setelah garpu dan sebelum exec. Anak, karena menyadari bahwa ia adalah anak, dapat menutup deskriptor file, membuka yang baru, dup () atau dup2 () mereka untuk memasukkannya ke nomor fd yang tepat, dll, semua tanpa mempengaruhi orangtua. Setelah melakukan itu, dan mungkin perubahan variabel lingkungan yang diinginkan (juga tidak mempengaruhi induk), ia dapat mengeksekusi program baru di lingkungan yang disesuaikan.
sumber
Saya pikir semua orang di sini tahu bahwa cara kerja garpu, tetapi pertanyaannya adalah mengapa kita perlu membuat duplikat yang tepat dari orang tua menggunakan garpu? Answer ==> Ambil contoh server (tanpa garpu), sementara klien-1 mengakses server, jika pada saat yang sama klien kedua-2 tiba dan ingin mengakses server tetapi server tidak memberikan izin kepada yang baru tiba client-2 karena server sibuk melayani client-1 sehingga client-2 harus menunggu. Setelah semua layanan ke client-1 selesai, client-2 sekarang dapat mengakses server. Sekarang pertimbangkan apakah pada saat bersamaan klien-3 tiba, jadi klien-3 harus menunggu sampai semua layanan ke klien-2 selesai. Ambil skenario di mana ribuan klien perlu mengakses server pada saat yang sama ... maka semua klien harus tunggu (server sibuk !!).
Ini dihindari dengan membuat (menggunakan garpu) salinan duplikat yang tepat (yaitu anak) dari server, di mana setiap anak (yang merupakan duplikat yang tepat dari induknya yaitu server) didedikasikan untuk klien yang baru tiba, sehingga secara bersamaan semua klien mengakses sama server.
sumber
fork
panggilan yang menyalin proses induk adalah bahwa Anda tidak harus memiliki dua program terpisah - tetapi memiliki program terpisah (misalnya,inetd
) dapat membuat sistem lebih modular.