Mengapa zombie menunggu anaknya?

11

Saya menggali melalui berbagai sumber, tetapi tidak dapat menemukan deskripsi yang baik tentang anatomi menuai anak. Ini adalah kasus sederhana dari apa yang ingin saya pahami.

$ 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

Mengapa zombie menunggu anak itu?

Bisakah Anda menjelaskan yang ini? Apakah saya perlu tahu C dan membaca kode sumber Bash untuk mendapatkan pemahaman yang lebih luas tentang ini atau apakah ada dokumentasi? Saya sudah berkonsultasi:

GNU bash, versi 4.3.42 (1) -release (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP Rab 13 Jul 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


sumber
2
Harus dicatat bahwa ini benar-benar tidak ada hubungannya dengan bash (selain fakta bahwa jika Anda memilih untuk menggunakan bash sebagai shell Anda, banyak proses akan dimulai oleh bash). Shell lain (tcsh, ksh, zsh, & c) semuanya memulai proses, dan menjalankan fungsi OS yang sama untuk mengatasinya.
jamesqf
@ jamesqf Menarik. Jika Anda ingin memperluas komentar Anda menjadi jawaban yang lengkap, itu akan bagus.
1
Kecuali bahwa itu bukan jawaban, hanya menunjukkan bahwa Anda telah mencari jawaban di tempat yang salah :-) Buku bagus tentang pemrograman sistem * nix harus memberikan jawaban yang jauh lebih baik daripada yang bisa saya tulis.
jamesqf

Jawaban:

17

Zombie tidak menunggu anaknya. Seperti proses zombie lainnya, ia tetap ada sampai orang tuanya mengumpulkannya.

Anda harus menampilkan semua proses yang terlibat untuk memahami apa yang terjadi, dan melihat PPID juga. Gunakan baris perintah ini:

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

Induk dari proses yang Anda bunuh adalah cat. Apa yang terjadi adalah bahwa bash menjalankan perintah latar belakang cat <( sleep 100 & wait )dalam sebuah subkulit. Karena satu-satunya hal yang dilakukan subkulit ini adalah mengatur beberapa pengalihan dan kemudian menjalankan perintah eksternal, subkulit ini diganti oleh perintah eksternal. Inilah rundown:

  • Bash asli (12126) panggilan forkuntuk mengeksekusi perintah latar belakang cat <( sleep 100 & wait )pada anak (14247).
    • Anak (14247) panggilan pipeuntuk membuat pipa, lalu forkuntuk membuat anak untuk menjalankan proses substitusi sleep 100 & wait.
      • Cucu (14248) panggilan forkuntuk berjalan sleep 100di latar belakang. Karena cucu tidak interaktif, proses latar belakang tidak berjalan dalam kelompok proses yang terpisah. Kemudian cucu menunggu untuk sleepkeluar.
    • Anak (14247) panggilan setpgid(itu adalah pekerjaan latar belakang di shell interaktif sehingga mendapat kelompok proses sendiri), kemudian execvedijalankan cat. (Saya sedikit terkejut bahwa proses substitusi tidak terjadi pada kelompok proses latar belakang.)
  • Anda membunuh cucu (14248). Orang tuanya sedang berjalan cat, yang tidak tahu apa-apa tentang proses anak dan tidak memiliki panggilan bisnis wait. Karena orang tua cucu tidak memetiknya, cucu tetap tinggal sebagai zombie.
  • Akhirnya, catkeluar - baik karena Anda membunuhnya, atau karena sleepkembali dan menutup pipa sehingga catmelihat akhir inputnya. Pada saat itu, orang tua zombie mati, jadi zombie dikumpulkan oleh init dan init menuai itu.

Jika Anda mengubah perintah ke

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

kemudian catberjalan dalam proses terpisah, bukan pada anak dari proses bash asli: anak pertama harus tinggal di belakang untuk berjalan echo done. Dalam hal ini, jika Anda membunuh cucu, itu tidak tetap sebagai zombie, karena anak (yang masih menjalankan bash pada saat itu) menuai itu.

Lihat juga Bagaimana linux menangani proses zombie dan Bisakah zombie memiliki anak yatim? Akankah anak-anak yatim diganggu dengan menuai zombie?

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Saya terkejut dengan hal kelompok proses juga. Sepertinya itu bug dan sekarang sudah diperbaiki di cabang master bash.
PSkocik
"Pesta asli menunggu anaknya (14247)." Kenapa atau bagaimana? Anak itu seharusnya berjalan di latar belakang dan tidak ada panggilan eksplisit. Apa perbedaan antara bash asli (14246) menunggu 14247 dan 14247 (yang sedang berjalan cat) tidak menunggu 14248 (menunggu sleep)? Apakah ada ingatan tentang siapa yang menunggu siapa, yang hilang oleh anak (14247) dan bash asli (14246) tidak, atau mungkin daftar sinyal seperti SIGCHLD tentang siapa yang harus dipanggil dan 14247 (sekarang berjalan bash) berhenti berlangganan dari dengan salam untuk 14248?
1
@ Thomas maksud saya bahwa bash panggilan asli waitpada anaknya, yaitu menuai itu. Saya bisa melihat bagaimana ini membingungkan, saya telah menghapus kalimat yang bahkan tidak pada titik yang tepat secara kronologis berbicara. Informasi bahwa suatu proses telah mati, pergi ke orang tua proses itu, suatu proses tidak dapat "berlangganan" untuk menerima informasi tentang kematian beberapa proses lainnya.
Gilles 'SANGAT berhenti menjadi jahat'
6

Zombie tidak menunggu anak itu. Sebaliknya, zombie adalah dengan proses yang sudah meninggal (dengan sendiri, atau dibunuh - seperti dalam contoh Anda), memiliki kode, data dan tumpukan deallocated, dan sekarang hanya berisi kode keluar nya, menunggu induknya untuk memanggil wait(2)untuk mengambilnya (dan akhirnya membersihkan entri proses dengan lengkap dari tabel proses)

Dalam contoh Anda, ketika tidur selesai (atau terbunuh), orang tua akan membaca status keluar, dan menuai zombie. Lihat yang disebutkan di atas wait(2)untuk detailnya.

Matija Nalis
sumber