Fork () ve vfork () arasındaki fark nedir?


13

Fork () ve vfork () arasındaki farkı ayrıntılı olarak anlamak istiyorum. Adam sayfasını tamamen sindiremedim.

Ayrıca meslektaşlarımdan birinin " Mevcut Linux'ta vfork () yoktur, onu çağırsanız bile dahili olarak fork () diyecektir " yorumunu açıklamak istiyorum .

Yanıtlar:


24

Man sayfaları genellikle kısa referans belgeleridir. Vikipedi kavramsal açıklamalara başvurmak için daha iyi bir yerdir.

Fork bir işlemi kopyalar: ana süreçle hemen hemen aynı olan bir alt süreç oluşturur (en belirgin fark, yeni işlemin farklı bir işlem kimliğine sahip olmasıdır). Özellikle, çatal (kavramsal olarak) tüm üst sürecin belleğini kopyalamalıdır.

Bu oldukça maliyetli olduğundan, vfork kopyanın gerekli olmadığı ortak bir özel durumu ele almak için icat edildi. Genellikle, alt işlemin yaptığı ilk şey yeni bir program görüntüsü yüklemektir, bu yüzden böyle olur:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

execveÇağrı yükleri, yeni bir yürütülebilir programı ve bu cümledeki yeni çalıştırılabilir kod ve taze bir veri belleğine tarafından sürecin kod ve veri hafızası. Yani tarafından oluşturulan tüm hafıza kopyası tamamen forkboştu.

Böylece vforkçağrı icat edildi. Belleğin bir kopyasını oluşturmaz. Bu nedenle vforkucuzdur, ancak alt süreçte işlemin yığınına veya yığın alanına erişmediğinizden emin olmanız gerektiğinden kullanımı zordur. Üst işlem yürütmeye devam ettiğinden, okumak bile bir sorun olabilir. Örneğin, bu kod bozulur (çocuğun veya ebeveynin önce bir zaman dilimi alıp almamasına bağlı olarak çalışabilir veya çalışmayabilir):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Vfork'un icadından bu yana, daha iyi optimizasyonlar icat edilmiştir. Linux dahil olmak üzere çoğu modern sistem, işlem belleğindeki sayfaların çağrı sırasında kopyalanmadığı , ancak daha sonra ebeveyn veya çocuk sayfaya ilk yazdığı bir yazma -kopyalama kopyası kullanır fork. Diğer bir deyişle, her sayfa paylaşılan olarak başlar ve her iki işlem de o sayfaya yazılana kadar paylaşılan kalır; yazan işlem yeni bir fiziksel sayfa alır (aynı sanal adresle). Yazarken kopyala, vfork'u çoğunlukla işe yaramaz hale getirir, çünkü kullanılabilir forkolduğu durumlarda herhangi bir kopya oluşturmaz vfork.

Linux vfork'u elinde tutuyor. forkSistem çağrısı hala gerçek bellek kopyalama olmasa bile, sürecin sanal bellek tablonun bir kopyasını almalı; vforkbunu yapmasına bile gerek yok. Çoğu uygulamada performans artışı göz ardı edilebilir.


1
Bu parlak cevap için teşekkürler .. Çatal () yaparken, çocuk yine de yeni bir işlem kimliği ve ilişkili Sanal alanı alacak, o zaman neden hala sürecin sanal bellek tablosunun bir kopyasını almalı? O kısımda net değilim.
Sen

@Sen: forksonraki yazma üzerine kopyaların iki işlemden yalnızca birini etkilemesi için ayrı bir sanal bellek eşlemesi oluşturması gerekir.
Gilles 'SO- kötü olmayı bırak'

Üst sürecin çalıştığından emin misiniz?
qbolec

2

fork()Ve vfork()sistem çağrıları farklıdır.

Sistem fork()çağrısı, ayrı belleğe sahip iki özdeş işlem üretir. Sistem vfork()çağrısı aynı belleği paylaşan iki işlem üretir.

vfork()Ebeveyn ile çocuk sona erecek bekleyecek. Üst öğe, programın paylaştığı değişkenlerden devralınır. Bu nedenle, çocuk çağrıldıktan sonra, çocuğun içinde değiştirilen tüm değişkenler yine de ebeveynin içinde değiştirilecektir.

Daha fazla bilgi için buraya tıklayın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.