Neden bir zombi çocuğunu bekliyor?


11

Farklı kaynakları araştırıyorum, ancak çocuk hasatının anatomisinin iyi bir tanımını bulamıyorum. Bu anlamak istediğim şeyin basit bir örneğidir.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

Zombi çocuğu neden bekliyor?

Bunu açıklayabilir misin? Bunu daha iyi anlamak için C'yi bilmem ve Bash kaynak kodunu okumam gerekiyor mu yoksa herhangi bir belge var mı? Zaten danıştım:

GNU bash, sürüm 4.3.42 (1) -çalışma (x86_64-pc-linux-gnu)

Linux 4.4.0-31-jenerik # 50-Ubuntu SMP Çar 13 Temmuz 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
Bunun gerçekten bash ile bir ilgisi olmadığını belirtmelisiniz (eğer bash'ı kabuk olarak kullanmayı seçerseniz, birçok işlem onun tarafından başlatılacaktır). Diğer mermiler (tcsh, ksh, zsh ve c) süreçleri başlatır ve bunlarla başa çıkmak için esasen aynı işletim sistemi işlevlerini çalıştırır.
jamesqf

@jamesqf İlginç. Yorumunuzu tam teşekküllü bir cevaba dönüştürmek istiyorsanız, bu harika olurdu.

1
Bu gerçekten bir cevap değil, sadece yanlış yerlerde cevap aradığınıza dikkat çekerek :-) * nix sistem programlama hakkında iyi bir kitap yazabileceğimden çok daha iyi bir cevap vermelidir.
jamesqf

Yanıtlar:


17

Zombi çocuğunu beklemiyor. Herhangi bir zombi süreci gibi, ebeveynleri toplayana kadar etrafta kalır.

Neler olup bittiğini anlamak için tüm süreçleri göstermeli ve PPID'ye de bakmalısınız. Bu komut satırını kullanın:

ps -t $(tty) -O ppid,pgid

Öldürdüğün sürecin ebeveyni cat. Olan şey, cat <( sleep 100 & wait )bash'ın alt komutta background komutunu çalıştırmasıdır. Bu alt kabuğun yaptığı tek şey bir yeniden yönlendirme ayarlamak ve daha sonra harici bir komut çalıştırmak olduğundan, bu alt kabuk yerine harici komut kullanılır. İşte yıkık:

  • Orijinal bash (12126) , bir çocukta forkarka plan komutunu yürütmek için çağrıda bulunur cat <( sleep 100 & wait )(14247).
    • Çocuk (14247) pipe, bir boru oluşturmayı, ardından forkişlem ikamesini çalıştıracak bir çocuk oluşturmayı çağırır sleep 100 & wait.
      • Torun (14248) arka planda forkkoşmaya çağırıyor sleep 100. Torun etkileşimli olmadığından, arka plan işlemi ayrı bir işlem grubunda çalışmaz. Sonra torun sleepçıkmayı bekliyor .
    • Çocuk (14247) çağırır setpgid(etkileşimli bir kabukta arka plan işi, bu yüzden kendi işlem grubunu alır), sonra execvekoşar cat. (Arka plan süreç grubunda süreç ikamesinin gerçekleşmemesine biraz şaşırdım.)
  • Torunu öldürüyorsun (14248). Ebeveyn çalışıyor cat, herhangi bir alt süreç hakkında hiçbir şey bilmiyor ve iş çağrısı yok wait. Torunun ebeveyni onu biçmediği için torun bir zombi olarak geride kalır.
  • Sonunda, catya çıkarırsınız - ya öldürürsünüz ya sleepda boruyu geri döndürür ve kapatır, böylece catgirişinin sonunu görür. Bu noktada, zombi ebeveynleri ölür, böylece zombi init tarafından toplanır ve init onu biçer.

Komutu olarak değiştirirseniz

{ cat <( sleep 100 & wait ); echo done; } &

daha sonra catorijinal bash işleminin alt öğesinde değil, ayrı bir işlemde çalışır: ilk çocuk çalıştırmak için geride kalmalıdır echo done. Bu durumda, torunu öldürürseniz, bir zombi olarak kalmaz, çünkü çocuk (o noktada hala bash çalıştırır) onu biçer.

Ayrıca bkz. Linux zombi sürecini nasıl ele alır ve bir zombi yetim olabilir mi? Yetim çocuklar zombi toparlarken rahatsız olacaklar mı?


Süreç grubu olayına da şaşırdım. Görünüşe göre bu bir hataydı ve şimdi bash ana dalında düzeltildi.
PSkocik

"Orijinal bash çocuğunu bekler (14247)." Neden veya ne şekilde? Çocuğun arka planda çalışması gerekiyor ve açık bir çağrı yok. 14247 için bekleyen orijinal bash (14246) ile 14248 (bekliyor) için beklemeyen 14247 (çalışan cat) arasındaki fark nedir sleep? Kimin kimin beklediğine dair bir anı var mı, çocuğun (14247) kaybettiği ve orijinal bash (14246), SIGCHLD gibi kimin çağrılması gerektiği ve 14247 (şimdi çalışıyor bash) ile abonelikten kaldırılan sinyallerin bir listesi var mı? 14248 ile ilgili olarak?

1
@tomas Orijinal bash waitçocuğunu çağırıyor demekti , yani onu biçiyor. Bunun nasıl kafa karıştırıcı olabileceğini görebiliyorum, kronolojik olarak konuşan doğru noktada bile olmayan bu cümleyi kaldırdım. Bir sürecin öldüğü bilgisi o sürecin ebeveynine gider, bir süreç başka bir sürecin ölümü hakkında bilgi almak için “abone olamaz”.
Gilles 'SO- kötü olmayı kes'

6

Zombi çocuğu beklemiyor. Bunun yerine, zombi zaten (kendi tarafından veya öldürüldü - gibi örnekte) öldüğü süreç, kodunu, verilerini vardı ve yığın ayırmanın ve şimdi sadece üst aramasını bekliyorsun, kendi çıkış kodu içeren geri almak için (ve son olarak proses girişini proses tablosundan tamamen temizleyin)wait(2)

Örneğin, uyku sona erdiğinde (veya öldürüldüğünde), ebeveyn çıkış durumlarını okuyacak ve zombileri toplayacaktır. Ayrıntılar için yukarıda belirtilenlere wait(2)bakı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.