|
NetBSD Documentation:
Weshalb wir das traditionelle vfork() nutzen
|
vfork()
ist für den speziellen Fall wenn ein Child
Prozeß sich mit einem anderen Programm via exec()
überlagert und der Parent Prozeß bis dahin blockiert bleibt,
entwickelt worden. Ein traditionalles fork()
erfordert die
Duplikation aller Pages des Parent Prozesses im Child Prozeß- ist also
wesentlicher kostspieliger.
Das Mach VM System lieferte COW (Copy On Write), wodurch fork()
erheblich effizienter wurde; in BSD 4.4 wurde vfork()
dann als
Synonym zu fork()
gestaltet. Nach dem Release von NetBSD 1.3
wurde dann das traditionelle vfork()
erneut implementiert.
Erheblicher Aufwand wurde unternommen, COW im UVM zu verbessern,
jedoch stellte sich heraus, dass ein Zugriffs-teilendes vfork()
immer noch die bessere Lösung war. Der vollständige Build
von libc auf einem 200MHz PPro wird um einige Sekunden verkürzt.
vfork()
/exec()
durch 4.4BSD
vfork()
und COW:
- Durchlauf der vm_map des Parent Prozesses, wobei beschreibbare Teile des
Addressspeichers als COW markiert werden. Dies erfordert einen Aufruf
der pmap, Modifikationen der PTEs und ein Ausleeren des TLB.
- Erstellung einer vm_map für den Child Prozeß;, Kopie der
vm_map Einträge des Parent in die vm_map des Child. Wahlweiser Aufruf
der pmap zur Kopie der PTEs aus der Page Tabelle des Parent Prozesses in die
Page Tabelle des Child Prozesses.
- Blockierung des Parent Prozesses.
- Ausführung des Chid Prozesses. Wenn PTEs nicht kopiert wurden,
Erzeugung eines Page Fault um ein physisches Mapping der Text Page in
die aktuelle Page des Program Counters zu erzwingen.
- Child Prozeß ruft exec() auf und unmappt den gesamten Addressspeicher der
eben erst erstellt wurde, kreiert einen neuen. Dies bedeutet
ebenfalls, dass die vm_map des ELternprozesses durchlaufen werden muss, um die
COW Teile als nicht-COW zu markieren.
- Freigabe des Parent Prozesses.
- Ausführung des Parent Prozesses; bei Modifikation vorheriger R/W Daten die
R/O für COW markiert waren Erzeugung eines Page Fault. Zu diesem
Zeitpunkt werden keine Daten kopiert.
Das 3.0BSD/NetBSD vfork()
mit Addressspeicher-Teilung:
- Referenzierung des struct vmspace des Parent Prozesses.
- Blockierung des Parent Prozesses.
- Ausführung des Child Prozesses. Es werden keine Page Faults erzeugt, da
die Page Tabellen des Parent Prozesses genutzt werden, und alle PTEs gültig
sind.
- Child Prozeß ruft exec() auf, löscht die Referenzen zum
Parent und erzeugt eine neue.
- Freigabe des Parent Prozesses.
- Ausführung des Parent Prozesses. (Es werden keine Page Faults erzeugt, da
die vm_map des Parent Prozesses nicht modifiziert wurde.)
Es zeigt sich also, dass im Falle eines fork()
gefolgt von einem Aufrug von
exec()
die zweite Prozedur offensichtlich schneller ist. Selbst wenn die
verwendeten COW Algorithmen gut sind, so wird doch mehr Aufwand gefordert im
Vergleich zu der vmspace-sharing Prozedur.
Zurück zu NetBSD Dokumentation: Kernel
(Ihre Meinung)
$NetBSD: vfork.html,v 1.6 2004/10/30 22:34:03 jschauma Exp $
Copyright © 1994-2003
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.