GNU/Linux >> Belajar Linux >  >> Linux

Apa yang terjadi saat mengirim SIGKILL ke Proses Zombie di Linux?

Untuk menjawab pertanyaan itu, Anda harus memahami bagaimana sinyal dikirim ke suatu proses dan bagaimana suatu proses ada di kernel.

Setiap proses direpresentasikan sebagai task_struct di dalam kernel (definisinya ada di sched.h file header dan mulai di sini). Struktur itu menyimpan informasi tentang proses; misalnya pid. Informasi penting ada di baris 1566 tempat sinyal terkait disimpan. Ini disetel hanya jika sinyal dikirim ke proses.

Proses mati atau proses zombi masih memiliki task_struct . Struktur tetap ada, sampai proses induk (alami atau adopsi) memanggil wait() setelah menerima SIGCHLD untuk menuai proses anaknya. Saat sinyal dikirim, signal_struct diatur. Tidak masalah apakah sinyalnya dapat ditangkap atau tidak, dalam hal ini.

Sinyal dievaluasi setiap kali proses berjalan. Atau tepatnya, sebelum prosesnya akan Lari. Prosesnya kemudian di TASK_RUNNING negara. Kernel menjalankan schedule() rutin yang menentukan proses yang berjalan selanjutnya sesuai dengan algoritma penjadwalannya. Dengan asumsi proses ini adalah proses selanjutnya yang berjalan, nilai dari signal_struct dievaluasi, apakah ada sinyal menunggu untuk ditangani atau tidak. Jika penangan sinyal ditentukan secara manual (melalui signal() atau sigaction() ), fungsi terdaftar dijalankan, jika bukan tindakan default sinyal dieksekusi. Tindakan default bergantung pada sinyal yang dikirim.

Misalnya, SIGSTOP penangan default sinyal akan mengubah status proses saat ini menjadi TASK_STOPPED lalu jalankan 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 sinyal tidak dapat ditangkap, tindakan default akan selalu dijalankan.

Untuk pertanyaan Anda:

Proses yang mati atau mati tidak akan pernah ditentukan oleh penjadwal untuk berada di TASK_RUNNING negara bagian lagi. Dengan demikian kernel tidak akan pernah menjalankan penangan sinyal (default atau ditentukan) untuk sinyal yang sesuai, mana pun sinyalnya. Oleh karena itu exit_signal tidak akan pernah diatur lagi. Sinyal "dikirim" ke proses dengan menyetel signal_struct di task_struct proses, tetapi tidak ada lagi yang akan terjadi, karena proses tidak akan pernah berjalan lagi. Tidak ada kode untuk dijalankan, yang tersisa dari proses hanyalah struktur proses itu.

Namun, jika proses induk menuai anaknya dengan wait() , kode keluar yang diterimanya adalah saat proses "awalnya" mati. Tidak masalah jika ada sinyal yang menunggu untuk ditangani.


Proses zombie pada dasarnya sudah mati. Satu-satunya hal adalah belum ada yang mengakui kematiannya sehingga terus menempati entri dalam tabel proses serta blok kontrol (struktur yang dipertahankan kernel Linux untuk setiap utas dalam aktivitas). Sumber daya lain seperti kunci wajib pada file, segmen memori bersama, semafor, dll. diklaim ulang.

Anda tidak dapat memberi sinyal kepada mereka karena tidak ada yang dapat bertindak berdasarkan sinyal ini. Bahkan sinyal fatal seperti KILL tidak berguna karena proses telah menghentikan eksekusinya. Anda dapat mencoba sendiri:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
    pid_t pid = fork();

    if (pid == -1)
        exit(-1);

    if (pid > 0) {
        //parent
        printf("[parent]: I'm the parent, the pid of my child is %i\n"
            "I'll start waiting for it in 10 seconds.\n", pid);
        sleep(10);
        int status;
        wait(&status);

        if (WIFSIGNALED(status)) {
            printf("[parent]: My child has died from a signal: %i\n", WTERMSIG(status));
        } else if (WIFEXITED(status)) {
            printf("[parent]: My child has died from natural death\n");
        } else {
            printf("[parent]: I don't know what happened to my child\n");
        }
    } else {
        //child
        printf("[child]: I'm dying soon, try to kill me.\n");
        sleep(5);
        printf("[child]: Dying now!\n");
    }

    return 0;
}

Di sini, saya memulai proses yang bercabang dan tidur sebelum menunggu anaknya. Anak itu tidak melakukan apa-apa selain tidur sedikit. Anda dapat membunuh anak saat sedang tidur atau setelah keluar untuk melihat perbedaannya:

$ make zombie 
cc     zombie.c   -o zombie

$ ./zombie    
[parent]: I'm the parent, the pid of my child is 16693
I'll start waiting for it in 10 seconds.
[child]: I'm dying soon, try to kill me.
# Here, I did "kill -15 16693" in another console
[parent]: My child has died from a signal: 15

$ ./zombie
[parent]: I'm the parent, the pid of my child is 16717
I'll start waiting for it in 10 seconds.
[child]: I'm dying soon, try to kill me.
[child]: Dying now!
# Here, I did "kill -15 16717" in another console
[parent]: My child has died from natural death

Linux
  1. Cara Menemukan dan Membunuh Proses Zombie di Linux

  2. Membunuh zombie, gaya Linux

  3. Linux – Kapan Saya Tidak Harus Membunuh -9 Proses?

  1. Linux – Apa yang Harus Dilakukan Saat Desktop Linux Membeku?

  2. Linux:Temukan dan Bunuh Proses Zombie

  3. Kapan setsid() berguna, atau mengapa kita perlu mengelompokkan proses di Linux?

  1. Apa yang Dilakukan Program Saat Mengirim Sinyal Sigkill?

  2. Apa definisi sesi di linux?

  3. Apa perintah untuk menemukan prioritas proses di Linux?