Untuk menjawab pertanyaan itu, Anda harus memahami bagaimana sinyal dikirim ke suatu proses dan bagaimana suatu proses ada di kernel.
Setiap proses direpresentasikan sebagai bagian task_struct
dalam kernel (definisi ada di sched.h
file header dan dimulai di sini ). Struct yang menyimpan informasi tentang proses; misalnya pid. Informasi penting ada pada baris 1566 di mana sinyal yang terkait disimpan. Ini diatur hanya jika sinyal dikirim ke proses.
Proses mati atau proses zombie masih memiliki task_struct
. Struct tetap, sampai proses induk (alami atau dengan adopsi) telah memanggil wait()
setelah menerima SIGCHLD
untuk menuai proses anaknya. Ketika sinyal dikirim, sinyal signal_struct
disetel. Tidak masalah apakah sinyalnya mudah ditangkap atau tidak, dalam hal ini.
Sinyal dievaluasi setiap kali ketika proses berjalan. Atau tepatnya, sebelum proses akan berjalan. Prosesnya kemudian di TASK_RUNNING
negara. Kernel menjalankan schedule()
rutin yang menentukan proses berjalan berikutnya sesuai dengan algoritma penjadwalannya. Dengan asumsi proses ini adalah proses yang berjalan berikutnya, nilai signal_struct
dievaluasi, apakah ada sinyal menunggu untuk ditangani atau tidak. Jika penangan sinyal didefinisikan secara manual (melalui signal()
atau sigaction()
), fungsi terdaftar dieksekusi, jika bukan tindakan default sinyal dieksekusi. Tindakan default tergantung pada sinyal yang dikirim.
Misalnya, SIGSTOP
penangan default sinyal akan mengubah status proses saat ini menjadi TASK_STOPPED
dan kemudian menjalankan schedule()
untuk memilih proses baru untuk dijalankan. Perhatikan, SIGSTOP
tidak dapat ditangkap (seperti SIGKILL
), oleh karena itu tidak ada kemungkinan untuk mendaftarkan penangan sinyal manual. Jika ada sinyal yang tidak dapat ditonton, tindakan default akan selalu dijalankan.
Untuk pertanyaan Anda:
Proses yang mati atau mati tidak akan pernah ditentukan oleh penjadwal untuk berada dalam TASK_RUNNING
status lagi. Dengan demikian kernel tidak akan pernah menjalankan penangan sinyal (default atau didefinisikan) untuk sinyal yang sesuai, sinyal mana pun itu. Oleh karena itu exit_signal
tidak akan pernah diatur lagi. Sinyal "disampaikan" untuk proses dengan menetapkan signal_struct
dalam task_struct
proses, tapi tidak ada yang lain akan terjadi, karena proses tidak akan berjalan lagi. Tidak ada kode untuk dijalankan, semua yang tersisa dari proses adalah struct proses itu.
Namun, jika proses induk menuai anaknya wait()
, kode keluar yang diterimanya adalah ketika proses "awalnya" mati. Tidak masalah jika ada sinyal yang menunggu untuk ditangani.
kill
itu sendiri mengembalikan 0 atau 1?Proses zombie pada dasarnya sudah mati. Satu-satunya hal adalah bahwa belum ada yang mengakui kematiannya sehingga ia terus menempati entri dalam tabel proses serta blok kontrol (struktur yang dipertahankan oleh kernel Linux untuk setiap utas dalam aktivitas). Sumber daya lain seperti kunci wajib pada file, segmen memori bersama, semaphore, dll. Direklamasi.
Anda tidak dapat memberi sinyal kepada mereka karena tidak ada yang dapat bertindak atas sinyal ini. Bahkan sinyal fatal seperti KILL tidak berguna karena prosesnya telah menghentikan eksekusi. Anda dapat mencoba sendiri:
Di sini, saya memulai proses yang bercabang dan tidur sebelum menunggu anaknya. Anak itu tidak melakukan apa pun kecuali tidur sedikit. Anda dapat membunuh anak ketika sedang tidur atau tepat setelah keluar untuk melihat perbedaannya:
sumber
ruby -e "loop while fork { exit! }"
... imgur.com/SoRXErm