Neden vfork veya forklu bir çocuk exit () yerine _exit () öğesini çağırmalı?


12

Man sayfasından vfork():

vfork (), çocuk (2) veya _exit (2) yürütmek için bir çağrı yapana kadar ebeveynin askıya alınması bakımından çataldan () farklıdır. Çocuk, execve () öğesi çocuk tarafından verilinceye kadar, yığını dahil tüm belleği üst öğesiyle paylaşır. Çocuk geçerli işlevden veya call exit () işlevinden geri dönmemeli, _exit () öğesini çağırabilir.

Çocuk neden _exit()sadece aramaktan ziyade kullanmalı exit()? Bu hem uygulanabilir umut vfork()ve fork().


Yanıtlar:


11

Daha önce görüldüğü gibi , vforkalt işlemin ebeveynin belleğine erişmesine izin vermez. exitC kütüphanesi işlevi (bu yüzden olmasıdır sıklıkla yazılı olarak exit(3)). C akışlarını yıkama ve kapatma (bildirilen işlevlerle açılan dosyalar stdio.h) ve kayıtlı kullanıcı tanımlı işlevleri yürütme gibi çeşitli temizleme görevlerini gerçekleştirir atexit. Tüm bu görevler, işlem belleğine okuma ve yazma işlemlerini içerir.

_exittemizlemeden çıkar. Bu _exit(2), genellikle sistem çağrı numarasını bir işlemci kaydına yerleştirerek ve belirli bir işlemci talimatı (sistem çağrı işleyicisine dallanma) yürüterek uygulanan doğrudan bir sistem çağrısıdır (bu nedenle şu şekilde yazılır ). Bunun işlem belleğine erişmesi gerekmez, bu nedenle daha sonra yapmak güvenlidir vfork.

Bundan sonra fork, böyle bir kısıtlama yoktur: ebeveyn ve çocuk süreci artık tamamen özerktir.


vfork, alt işlemin ebeveynin belleğine erişmesine izin vermiyor mu? Ama aynı adres alanını paylaştıklarını düşündüm, böylece çocuk ebeveynlerin adres alanına erişebilir. Bu anlayış yanlış mıydı?
Sen

Çataldan sonra, böyle bir kısıtlama yoktur: ebeveyn ve çocuk süreci artık tamamen özerktir. Bu çatal bir çocuktan bir çıkış () çağırabileceğim anlamına mı geliyor ?
Sen

1
@Sen: Çocuğun ebeveynin belleğine erişmesine izin verilmiyor. Eğer denerseniz, işe yarayabilir, çünkü çekirdek sizi korumaz. Ama etki sizin niyetiniz olmayabilir; örneğin, derleyiciniz bir kayıtta bir değer bırakmaya karar verirse, üst işlem tarafından görülmez.
Gilles 'SO- kötü olmayı bırak'

@Sen: Bir çataldan sonra, çağrı çıkışı veya başka bir işlev yapabilirsiniz. Her işlem bir çataldan sonra başlar (Linux'ta, ilk işlem bile initçekirdek tarafından çatallanır).
Gilles 'SO- kötü olmayı bırak'

3

exitatexitkopyalanan bölümün dışındaki verilere erişerek kaydedilen arama işlevleri gibi ek temizleme işlemleri yapın . _exitçekirdek içi dışında herhangi bir temizleme olmadan doğrudan sistem araması yapar.


... ve fork () her şeyi kopyaladığına dikkat edilmelidir, böylece exit () öğesini çağırabilirsiniz ve mevcut fonksiyondan kesinlikle geri dönebilirsiniz.
derobert

3

Alt süreç sona erdiğinde stdio (veya diğer) arabelleklerinin yıkanmasını önlemek için _exit () alt çağrısına sahipsiniz. Alt süreç üst sürecin tam bir kopyasını oluşturduğundan, alt süreç hala üst öğenin "stdout" veya "stderr" içinde sahip olduğu her şeye sahiptir, <stdio.h> arabellekleri arabelleğe alınır. Üst işlemdeki arabellekler dolduğunda ve temizlendiğinde, alt işlemin atexit işleyicilerinden biri ve diğerinden üst öğeden çıkış () çağırarak çift çıkış alabilirsiniz (ve bu durum uygun olmayan zamanlarda).

Yukarıdaki cevabın stdio.h özellikleri üzerine yoğunlaştığının farkındayım, ancak yukarıdaki fikirlerden birinin gösterdiği gibi, bu fikir muhtemelen diğer tamponlu I / O'ya da yansıyor.


1

exit(): - G / Ç akışlarını ve daha fazlasını kapatmak gibi bir temizleme görevi gerçekleştirir ve sonra çekirdeğe döner. _exit(): - doğrudan çekirdeğe gelir (temizleme görevi gerçekleştirmeyin).

fork() : hem ebeveyn hem de çocuk farklı dosya tablosuna sahiptir, bu nedenle çocuk tarafından yapılan değişiklik ebeveynin ortam parametrelerini etkilemez ve bunun tersi de geçerlidir.

vfork(): hem üst hem de alt öğe aynı dosya tablosunu kullanır, bu nedenle alt öğenin yaptığı değişiklik üst öğenin ortam parametrelerini etkiler. Örneğin var=10, var++alt öğe tarafından çalıştırılan ve daha sonra üst öğe çalıştırılan bazı değişkenler , üst öğe var++çıktısının etkisini de görebilirsiniz .

Ben kullanırsanız söylediği gibi exit()içinde vfork()sonra tüm i / o zaten kapalıdır. Bu nedenle, üst öğe düzgün çalışsa bile, tüm değişkenler temizlendiğinden ve tüm akışlar kapatıldığından, doğru çıktıyı alamazsınız.

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.