Salah satu hal yang menarik saat kemarin kuliah IF4038 Pemrograman Sistem adalah tentang zombie process. Zombie process adalah sebuah proses pada sistem operasi yang telah menyelesaikan eksekusinya tetapi terdapat pada entry process. Di dalam sistem operasi UNIX terdapat sebuah konsep parent process dan child process. Dengan menggunakan system call fork. Sebuah process dapat menciptakan sebuah process lain yang menduplikasikan seluruh image dari process tersebut. /* fork1.c */ #include <stdio.h> int main(int argc, char * argv[]) { fork(); puts("Hello World!"); }
/* fork2.c */ #include <stdio .h> #include <sys /types.h> int main(int argc, char * argv[]) { pid_t childpid = fork(); if (childpid == 0) /* Child proces */ printf("I am the child. My PID is %d. My Parent ID is %d\n", getpid(), getppid()); else if (childpid > 0) /* Parent process */ printf("I am the parent. My PID is %d. My Child ID is %d\n", getpid(), childpid); else /* Failed */ puts("Failed to fork"); } Hasilnya bisa dilihat, [email protected]:~/IF4038$ ./fork2 I am the child. My PID is 5463. My Parent ID is 5462 I am the parent. My PID is 5462. My Child ID is 5463 Mari kita coba-coba lihat pada process table untuk kode di bawah ini /* fork3.c */ #include <stdio.h> #include <sys/types.h> int main(int argc, char * argv[]) { pid_t childpid = fork(); if (childpid == 0) /* Child proces */ for( ; ; ) printf("C [%d]\n", getpid()); else if (childpid > 0) /* Parent process */ for( ; ; ) printf("P [%d]\n", getpid()); else /* Failed */ puts("Failed to fork"); } Process tablenya jika kode dieksekusi [email protected]:~/IF4038$ ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 5420 6006 6006 5420 pts/1 6006 R+ 1000 0:00 ./fork3 6006 6007 6006 5420 pts/1 6006 R+ 1000 0:00 ./fork3 5470 6010 6010 5470 pts/2 6010 R+ 1000 0:00 ps axj Zombie process akan terjadi kalau PID 6007 kita beri signal kill [email protected]:~/IF4038$ kill -9 6007 [email protected]:~/IF4038$ ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 5420 6006 6006 5420 pts/1 6006 R+ 1000 0:53 ./fork3 6006 6007 6006 5420 pts/1 6006 Z+ 1000 0:49 [fork3] <defunct> 5470 6053 6053 5470 pts/2 6053 R+ 1000 0:00 ps aj Bisa dilihat 6007 tetap berada pada process table hanya saja ditandai dengan <defunct> Process ini lah yang disebut dengan zombie process. Sebenarnya process ini sudah berhenti dieksekusikan oleh CPU. Ketika process ini berhenti dieksekusi process ini akan mengirimkan signal SIGCHLD ke parent process. Ketika parent process tidak menghandle signal tersebut maka child process akan seakan-akan tetap hidup. [email protected]:~/IF4038$ ./fork3 [email protected]:~/IF4038$ ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 5420 6104 6104 5420 pts/1 6104 R+ 1000 0:01 ./fork3 6104 6105 6104 5420 pts/1 6104 R+ 1000 0:01 ./fork3 5470 6107 6107 5470 pts/2 6107 R+ 1000 0:00 ps aj [email protected]:~/IF4038$ kill -9 6104 [email protected]:~/IF4038$ ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1 6105 6104 5420 pts/1 5420 R 1000 0:12 ./fork3 5470 6115 6115 5470 pts/2 6115 R+ 1000 0:00 ps aj Child process akan diadopsi oleh process dengan PID 1 yakni init. Sepertinya parent process tidak perlu memberitahu child process saat berhenti eksekusi. /* fork4.c */ #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char * argv[]) { int stat; pid_t childpid = fork(); if (childpid == 0) /* Child proces */ for( ; ; ) printf("C [%d]\n", getpid()); else if (childpid > 0) /* Parent process */ { printf("Waiting....\n"); wait(&stat); printf("Child end result %d\n", stat); } else /* Failed */ puts("Failed to fork"); } Moral dari cerita ini adalah,
Akan tetapi agak sedikit rancu, bagaimana kalau si Bapaknya yang ngusir? Sebagai contoh /* fork5.c */ #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char * argv[]) { int stat; pid_t childpid = fork(); if (childpid == 0) /* Child proces */ for( ; ; ) printf("C [%d]\n", getpid()); else if (childpid > 0) /* Parent process */ { int i; for (i = 0; i < 5; i++) { sleep(1); } kill(childpid, SIGKILL); for ( ; ; ); } else /* Failed */ puts("Failed to fork"); } Pada kode di atas, setelah 5 detik, parent process akan mengirimkan signal SIGKILL kepada child process kemudian masuk ke infinite loop. /* fork2.c */ #include <stdio .h> #include <sys /types.h> int main(int argc, char * argv[]) { pid_t childpid = fork(); if (childpid == 0) /* Child proces */ printf("I am the child. My PID is %d. My Parent ID is %d\n", getpid(), getppid()); else if (childpid > 0) /* Parent process */ printf("I am the parent. My PID is %d. My Child ID is %d\n", getpid(), childpid); else /* Failed */ puts("Failed to fork"); }0 setelah detik ke 5 /* fork2.c */ #include <stdio .h> #include <sys /types.h> int main(int argc, char * argv[]) { pid_t childpid = fork(); if (childpid == 0) /* Child proces */ printf("I am the child. My PID is %d. My Parent ID is %d\n", getpid(), getppid()); else if (childpid > 0) /* Parent process */ printf("I am the parent. My PID is %d. My Child ID is %d\n", getpid(), childpid); else /* Failed */ puts("Failed to fork"); }1 Salah satu solusinya ya jelas dengan menambahkan syscall wait() setelah kill()
Ada satu hal lagi yang masih belum diklarifikasikan. Bagaimana kalau child process yang memberi signal SIGKILL kepada parent process? |