Apa yang dilakukan program ketika mengirim sinyal SIGKILL?

39

Ketika saya biasa killall -9 namemembunuh program, negara menjadi zombie. Beberapa menit kemudian, itu benar-benar berhenti. Jadi, apa yang terjadi selama menit-menit itu?

haikun he
sumber

Jawaban:

66

Program ini sebenarnya tidak pernah menerima sinyal SIGKILL, karena SIGKILL sepenuhnya ditangani oleh sistem operasi / kernel.

Ketika SIGKILL untuk proses tertentu dikirim, penjadwal kernel segera berhenti memberikan proses itu lagi waktu CPU untuk menjalankan kode ruang pengguna. Jika proses memiliki utas yang mengeksekusi kode ruang pengguna pada CPU / core lain pada saat penjadwal membuat keputusan ini, utas tersebut akan dihentikan juga. (Dalam sistem single-core ini dulunya jauh lebih sederhana: jika satu-satunya inti CPU dalam sistem menjalankan penjadwal, itu menurut definisi tidak menjalankan proses pada saat yang sama!)

Jika proses / utas mengeksekusi kode kernel (mis. Panggilan sistem, atau operasi I / O yang terkait dengan file yang dipetakan memori) pada saat SIGKILL, prosesnya menjadi sedikit rumit: hanya beberapa panggilan sistem yang dapat disela, sehingga kernel secara internal menandai proses sebagai "sekarat" khusus sampai sistem panggilan atau operasi I / O diselesaikan. Waktu CPU untuk menyelesaikannya akan dijadwalkan seperti biasa. Panggilan sistem yang dapat terputus atau operasi I / O akan memeriksa apakah proses yang memanggilnya sekarat pada titik pemberhentian yang sesuai, dan akan keluar lebih awal dalam kasus itu. Operasi tanpa gangguan akan selesai, dan akan memeriksa keadaan "sekarat" sebelum kembali ke kode ruang pengguna.

Setelah rutinitas kernel dalam proses diselesaikan, status proses diubah dari "mati" menjadi "mati" dan kernel mulai membersihkannya, mirip dengan ketika sebuah program keluar secara normal. Setelah pembersihan selesai, kode hasil yang lebih besar dari 128 akan diberikan (untuk menunjukkan bahwa proses tersebut terbunuh oleh sinyal; lihat jawaban ini untuk detail yang berantakan ), dan proses akan beralih ke keadaan "zombie" . Induk dari proses yang terbunuh akan diberitahukan dengan sinyal SIGCHLD.

Akibatnya, proses itu sendiri tidak akan pernah mendapatkan kesempatan untuk benar-benar memproses informasi bahwa ia telah menerima SIGKILL.

Ketika suatu proses dalam keadaan "zombie" itu berarti proses tersebut sudah mati, tetapi proses induknya belum mengakui ini dengan membaca kode keluar dari proses mati menggunakan wait(2)panggilan sistem. Pada dasarnya satu-satunya sumber daya yang dikonsumsi proses zombie adalah slot dalam tabel proses yang menyimpan PID-nya, kode keluar dan beberapa "statistik vital" lainnya dari proses pada saat kematiannya.

Jika proses orang tua meninggal sebelum anak-anaknya, proses anak yatim secara otomatis diadopsi oleh PID # 1, yang memiliki tugas khusus untuk terus menelepon wait(2)sehingga setiap proses anak yatim tidak akan bertahan sebagai zombie.

Jika proses zombie perlu beberapa menit untuk dihapus, ini menunjukkan bahwa proses induk zombie sedang berjuang atau tidak melakukan tugasnya dengan baik.

Ada deskripsi yang tidak jelas tentang apa yang harus dilakukan jika terjadi masalah zombie dalam sistem operasi mirip Unix: "Anda tidak dapat melakukan apa pun untuk zombie itu sendiri, karena mereka sudah mati. Sebaliknya, bunuh master zombie jahat! " (Yaitu proses induk dari zombie yang merepotkan)

telcoM
sumber
5
Apa yang terjadi jika prosesnya dalam panggilan kernel (misalnya melakukan I / O) ketika SIGKILL dikirim?
gidds
9
@gidds Entah I / O akan dibatalkan untuk mengeksekusi SIGKILL, atau SIGKILL akan ditunda hingga I / O selesai. Ini adalah perbedaan antara status sleep 'S' dan 'D' di ps: 'S' adalah untuk I / O menunggu bahwa kernel dapat membatalkan untuk mengirimkan sinyal, dan 'D' untuk mereka yang tidak bisa.
zwol
6
Itu tidak sepenuhnya akurat untuk mengatakan jadwal segera berhenti memberikan waktu proses CPU. Sisi kernel dari penanganan sinyal masih dijalankan oleh proses itu, tetapi proses tersebut hanya akan mengeksekusi kode kernel sehingga Anda benar ketika Anda mengatakan program tidak pernah menerima sinyal. Proses ini akan mengeksekusi kode kernel yang bertanggung jawab untuk sebagian besar pembersihan sumber daya (file terbuka, memori virtual, dll.) Langkah terakhir dari kode pembersihan ini adalah mengubah status proses menjadi zombie dan memanggil penjadwal. Maka itu tidak akan pernah dijadwalkan lagi.
kasperd
4
@gidds Setidaknya ada empat kondisi berbeda yang dapat dijalankan. Proses ini dapat menjalankan kode kernel saat ini atau dapat juga tidur di salah satu dari tiga kondisi tidur yang berbeda. Status tidur dapat menjadi interruptible, non-interruptible, atau non-interruptible kecuali untuk sinyal mematikan. Jika dalam tidur yang tidak terputus, ia akan dibiarkan tidur selama yang diperlukan dan hanya setelah ia bangun ia akan memiliki kesempatan untuk mati. Jika berada di salah satu dari dua negara tidur lainnya itu akan dibangunkan segera dan dijadwalkan segera setelah ada CPU yang tersedia untuk itu.
kasperd
2
@gidds Apa yang terjadi selanjutnya tergantung pada kode kernel yang dijalankannya. Terlepas dari apakah sudah berjalan atau pertama harus dibangunkan dan kemudian dapat mulai menjalankan kode kernel itu pada saat itu akan diizinkan untuk melanjutkan. Dan kode kernel tersebut bertanggung jawab untuk memperhatikan bahwa proses telah diperintahkan untuk mati dan bertindak sesuai dengan itu. Sebagian besar waktu cara yang tepat untuk menghadapinya dalam kode kernel adalah mengembalikan kesalahan dari fungsi apa pun yang dijalankannya. Setelah tumpukan panggilan kernel dibatalkan, kode penanganan sinyal dapat mengambil alih sesaat sebelum kembali ke mode pengguna.
kasperd