Varsayılan işlem oluşturma mekanizması neden çatal?


46

UNIX sistemi süreç oluşturma çağrısı olan fork (), üst süreci kopyalayarak bir alt süreç oluşturur. Anladığım kadarıyla bunu neredeyse her zaman alt sürecin bellek alanını (metin bölümü dahil) değiştirmek için exec () çağrısı izliyor. Ebeveynin hafıza alanını çatalı () kopyalamak her zaman bana zararlı görünüyordu (her ne kadar atıkların en aza indirilebildiğini fark etsem de, bellek bölümleri kopyalanıncaya kadar kopyalanıyordu, böylece sadece işaretçiler kopyalandı). Her neyse, bu çoğaltma yaklaşımının süreç oluşturma için neden gerekli olduğunu bilen var mı?


3
Not olduğunu fork(2)Linux altında adam sayfanın mesajı: Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child. Hayal (ama kesin olarak bilmiyorum) bu diğer modern UNIX'ler için durum olduğunu.
larsks

4
Orijinal, PDP-11 Unix gerçekten, bir çatal işlemin tüm baytlarını gerçekten kopyaladı: ama sadece 64Kb çalıştırılabilir ve en fazla 64Kb veri vardı, bu yüzden 1975'te bile büyük bir yük değildi. 1990'dan bu yana HER UNIX ve UNIX'in benzeri bir şeyin yazı üzerine kopyalanan metin bölümleri olduğunu tahmin ediyorum, bu yüzden kitapların ve makalelerin neden "çatalla performans sorununu" daha fazla yaydığına bile emin değilim.
Bruce Ediger

Günümüzde çatal, vfork'a benzer bir şekilde uygulanmaktadır ( openbsd.org/cgi-bin/… ). Verimli, endişelenme.
Aki

Ayrıca bir çataldan sonra (veya en azından hemen çalışmaz) çalıştırmadığınız birçok kullanımın olduğunu unutmayın: boruları ve web sunucularını düşünün.
jfg956

Belki bir şey yavaş olurdu. Ancak @cjm, Microsoft'un CreateProcess kullandığı alternatifine baktığını söylediği gibi, CreateProcess yavaş olduğu için erken başlıkları uygulamak zorunda kaldılar (öncülük ettikleri tek şey olabilir). (Ayrıca konulara ihtiyaçları vardı çünkü selectkırıldılar, ama bu başka bir hikaye).
ctrl-alt-delor

Yanıtlar:


57

Arayüzü basitleştirmek için. Alternatif forkve execWindows ' CreateProcess işlevi gibi bir şey olurdu . Kaç tane parametrenin CreateProcessbulunduğuna ve birçoğunun daha da fazla parametre içeren yapılar olduğuna dikkat edin . Bunun nedeni , yeni işlem hakkında kontrol etmek isteyebileceğiniz her şeyin iletilmesi gerektiğidir CreateProcess. Aslında, CreateProcessyeterli parametreye sahip olmadığı için Microsoft, CreateProcessAsUser ve CreateProcessWithLogonW öğesini eklemek zorunda kaldı .

fork/execModel ile tüm bu parametrelere ihtiyacınız yok. Bunun yerine, sürecin belirli özellikleri arasında korunur exec. Bu, istediğiniz forkişlem niteliklerini (normalde kullandığınız fonksiyonları kullanarak) değiştirmenizi ve ardından değiştirmenizi sağlar exec . Linux'ta forkhiçbir parametresi yoktur ve execveyalnızca 3: çalıştırılacak program, onu vermek için komut satırı ve çevresi vardır. (Başka execfonksiyonlar da vardır, ancak execvegenel kullanım durumlarını basitleştirmek için C kütüphanesi tarafından sağlanan sarmalayıcılardır .)

Eğer farklı bir akım dizin olan bir süreç başlatmak istiyorsanız: fork, chdir, exec.

Stdin / stdout: komutunu yeniden yönlendirmek istiyorsanız fork, dosyaları açın / kapatın exec.

Eğer anahtar kullanıcılara isterseniz: fork, setuid, exec.

Bütün bunlar ihtiyaç duyulduğunda birleştirilebilir. Biri süreç özelliğinin yeni bir tür ile gelirse, değiştirmek gerekmez forkve exec.

Larksklerde de belirtildiği gibi, çoğu modern Unix yazma üzerine kopya kullanır, bu nedenle forkönemli bir ek yük içermez.


16
Mükemmel açıklama. “UNIX'i anlamayanlar, onu kötü bir şekilde yeniden icat etmeye mahkum edildi.” - Henry Spencer
Kyle Jones

1
Teşekkürler! Bir şansın var mı?
Ellen Spertus

1
@Aki, nope, CreateProcess () tam anlamıyla yeni bir işlem yapar ve sıfırdan oluşturur, çatal oluşturma.
psusi

2
Ancak, Unix'te bir yerde bir CreateProcess () eşdeğeri olmamalıdır? Aksi halde ilk süreç nasıl yaratılır? Mitolojik bir yaratıcı tanrıdan farklı olarak, ilk süreç kendini hiçlikten alamaz. ;-)
Steven Monday,

2
@StevenMonday, evet, ancak çekirdek başlatma kodunda ve dışarıdan erişilemiyor. Tüm bu parametrelere ihtiyaç duymuyor çünkü neredeyse her şey kodlanmış. Yalnızca ID 1, yani init işlemi şeklinde olabilir. Bundan sonra, işlemler sadece çatalla yaratılır.
cjm

5

Cjm'nin cevabına ek olarak, Tekli Unix Spesifikasyonu adlı bir fonksiyon tanımlar vfork(). Bu işlev çatal gibi çalışır, ancak çatallı işlemin exec familly işlevini çağırmak veya çağırmaktan başka bir şey yapması durumunda tanımsız davranışı olması dışında _exit().

Böylece hemen hemen tanımlanmış davranış ile tek kullanım:

pid_t ret = vfork();
if(ret == 0)
{
    exec(...);
    _exit(EXIT_FAILURE); //in case exec failed for any reason.
}

Peki ne yapar vfork? Bu ucuz bir şey fork. Yazma işlemine gerek kalmadan yapılan uygulamalarda, ortaya çıkan işlem bellek alanını orijinal işlemle paylaşacaktır (bu nedenle tanımlanmamış davranış). Yazma üzerine yazma uygulamalarında, yazma üzerine kopyalama uygulamalarının hızlı vforkolması nedeniyle aynı olmasına izin verilir fork().

Doğrudan yeni bir işlem oluşturabilen isteğe bağlı posix_spawnişlev (ve bir posix_spawnpişlev) de vardır. (Bir kütüphane çağrı kullanarak bunları uygulamak için de izin verilebilir forkve execve uygulanmasının örneği verilmiştir.)

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.