2013-12-15 62 views
5

tôi tự hỏi nếu mã sau đây có thể tạo ra zombie:Mã C này có thể tạo ra các quá trình zombie không?

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

int main(){ 
    int i=1; 
    pid_t p; 
    p = fork(); 
    i++; 
    if(p!=0){ 
     waitpid(p, NULL, 0); 
    } 
    printf("%d\n",i); 
    return 0; 
} 

Vì vậy, quá trình cha mẹ gọi waitpid cho quá trình trẻ em, trong đó trả về ngay lập tức nếu đứa trẻ đã chưa kết thúc. Vì vậy, không có zombie có thể phát sinh cho đến nay. Nhưng, nếu đứa trẻ thoát ra trước khi

return 0;
lệnh này sẽ là một zombie sau đó? Tôi thực sự bối rối về nó. Nên waitpid là dòng cuối cùng của mã trước khi chương trình chấm dứt? Bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn!

+1

Điều đó có vẻ ổn nhưng bạn có thể có một sự hiểu lầm. 'Waitpid' sẽ trở lại ngay lập tức nếu đứa trẻ đã chết; nếu không nó sẽ chặn cho đến khi đứa trẻ chết. Trừ khi bạn sử dụng WNOHANG với waitpid trong trường hợp nó sẽ không chặn nhưng đó không phải là vấn đề ở đây. – Duck

+0

Sửa lỗi nếu tôi sai, nhưng tôi nghĩ rằng tham số thứ ba (số không) tương đương với WHOHANG. Dù sao, chúng ta hãy giả sử nó là WHOHANG. Vậy thì một zombie sẽ được tạo ra và làm thế nào? Và cuối cùng, nên waitpid là lệnh cuối cùng trước khi trở về 0; để đảm bảo không có zombie nào được tạo ra ?. Cảm ơn một lần nữa! – mgus

+1

Không có WNOHANG chắc chắn là không tương đương 0. Zero là mặc định và nó sẽ không có ý nghĩa bitwise-hoặc WNOHANG nếu bằng 0. Nếu đứa trẻ chết sau khi một 'waitpid' không chặn và cha mẹ đã thoát trước thì bạn sẽ có một zombie. Nhưng thông thường bạn sẽ sử dụng một 'waitpid' không chặn trong một vòng lặp và có thể kết hợp với việc nhận SIGCHLD. Waitpid chính nó có thể được bất cứ nơi nào trong mã miễn là nó xử lý con của bạn khi kêu gọi để làm như vậy. – Duck

Trả lời

6

Đứa trẻ chỉ trở thành một zombie nếu nó kết thúc phụ huynh không gọi wait*()càng lâu càng bản thân còn sống mãi.

Trong thời điểm cha mẹ cũng kết thúc đứa trẻ bị gặt hái bởi quy trình init sẽ chăm sóc gọi số wait*() trên đứa trẻ, vì vậy cuối cùng sẽ kết thúc và để trạng thái này biến mất và biến mất khỏi danh sách quy trình.

Để kích đứa trẻ được tạo ra trong ví dụ mã của bạn để trở thành một zombie thay đổi mã ví dụ như sau:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

int main(void) 
{ 
    pid_t p = fork(); 

    if (p != 0) 
    { 
     waitpid(p, NULL, 0); /* See if the child already had ended. */ 
     sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */ 
     pause(); /* Suspend main task. */ 
    } 
    else 
    { 
     sleep(3); /* Just let the child live for some tme before becoming a zombie. */ 
    } 

    return 0; 
} 

Do hai sự kiện sau đây:

  • đứa trẻ ngủ cho 3s do đó, cuộc gọi của phụ huynh đến waitpid() hầu hết có thể sẽ không thành công
  • xử lý mặc định là SIGCHLD là để bỏ qua nó.

mã trên trong thực tế cũng giống như:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

int main(void) 
{ 
    pid_t p = fork(); 

    if (p != 0) 
    { 
     pause(); /* Suspend main task. */ 
    } 
    else 
    { 
     sleep(3); /* Just let the child live for some tme before becoming a zombie. */ 
    } 

    return 0; 
} 
+0

Có gì trong mã này ngăn trẻ không trở thành zombie? Bạn có thể giải thích chi tiết hơn tại sao bạn sử dụng lệnh ngủ và tạm dừng không? Xin lỗi vì rất nhiều câu hỏi nhưng tôi không quen thuộc với các khái niệm này. – mgus

+0

@Konstantinos Konstantinidis: "* Có gì trong mã này ngăn cản đứa trẻ trở thành một zombie? *" Không có gì. Như đã nói trong câu trả lời của tôi, mã này ** không ** tạo ra một zombie. – alk

0

Tôi tìm thấy một cách đơn giản để tạo ra một quá trình zombie và kiểm tra bằng ps -e

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 

void main() 
{ 
    pid_t pid; 
    pid = fork(); 
    //parent sleeps while the child has exited 
    //not an orphan since parent still alive 
    //child will be still present in process table 
    if(pid==0) 
    {//child 
     exit(0); 
    } 
    else 
    {//parent 
     sleep(15); 
    } 
} 

chạy ps - e trong vòng 15 giây ... bạn sẽ thấy

6454 pts/2 00:00:00 a.out < không còn tồn tại>

Các vấn đề liên quan