Tại sao một zombie chờ đợi đứa con của nó?


11

Tôi đang đào qua các nguồn khác nhau, nhưng không thể tìm thấy một mô tả hay về giải phẫu của việc gặt hái trẻ em. Đây là một trường hợp đơn giản về những gì tôi muốn hiểu.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

Tại sao zombie chờ đợi đứa trẻ?

Bạn có thể giải thích điều này? Tôi có cần biết C và đọc mã nguồn Bash để hiểu rõ hơn về điều này hay có tài liệu nào không? Tôi đã tham khảo ý kiến:

GNU bash, phiên bản 4.3.42 (1) -release (x86_64-pc-linux-gnu)

Linux 4.4.0-31-chung # 50-Ubuntu SMP Thứ tư ngày 13 tháng 7 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
Cần lưu ý rằng điều này thực sự không liên quan gì đến bash (ngoài thực tế là nếu bạn chọn sử dụng bash làm vỏ của mình, rất nhiều quy trình sẽ được bắt đầu bởi nó). Các shell khác (tcsh, ksh, zsh, & c) đều bắt đầu các tiến trình và chạy về cơ bản cùng các chức năng HĐH để xử lý chúng.
jamesqf

@jamesqf Thú vị. Nếu bạn muốn mở rộng nhận xét của mình thành một câu trả lời đầy đủ, điều đó sẽ rất tuyệt.

1
Ngoại trừ việc nó không thực sự là một câu trả lời, chỉ cần chỉ ra rằng bạn đã tìm kiếm câu trả lời sai :-) Bất kỳ cuốn sách hay nào về lập trình hệ thống * nix sẽ cung cấp một câu trả lời tốt hơn nhiều so với tôi có thể viết.
jamesqf

Câu trả lời:


17

Thây ma không đợi con của nó. Giống như bất kỳ quá trình zombie nào, nó tồn tại xung quanh cho đến khi cha mẹ của nó thu thập nó.

Bạn nên hiển thị tất cả các quy trình liên quan để hiểu những gì đang diễn ra và cũng xem xét PPID. Sử dụng dòng lệnh này:

ps -t $(tty) -O ppid,pgid

Cha mẹ của quá trình bạn đang giết là cat. Điều gì xảy ra là bash chạy lệnh nền cat <( sleep 100 & wait )trong một lớp con. Vì điều duy nhất mà lớp con này làm là thiết lập một số chuyển hướng và sau đó chạy một lệnh bên ngoài, nên lớp con này được thay thế bằng lệnh bên ngoài. Đây là danh sách:

  • Bash ban đầu (12126) gọi forkđể thực thi lệnh nền cat <( sleep 100 & wait )trong một đứa trẻ (14247).
    • Đứa trẻ (14247) gọi pipeđể tạo một đường ống, sau đó forktạo ra một đứa trẻ để chạy thay thế quá trình sleep 100 & wait.
      • Các cháu (14248) gọi forkđể chạy sleep 100trong nền. Vì cháu không tương tác, quá trình nền không chạy trong một nhóm quy trình riêng biệt. Sau đó, cháu chờ đợi sleepđể thoát ra.
    • Đứa trẻ (14247) gọi setpgid(đó là một công việc nền trong lớp vỏ tương tác để nó có được nhóm quy trình riêng), sau đó execvechạy cat. (Tôi hơi ngạc nhiên khi sự thay thế quá trình không xảy ra trong nhóm quy trình nền.)
  • Bạn giết cháu (14248). Cha mẹ của nó đang chạy cat, không biết gì về bất kỳ quy trình con nào và không có cuộc gọi kinh doanh wait. Vì cha mẹ của đứa cháu không gặt hái được, nên đứa cháu ở lại như một thây ma.
  • Cuối cùng, catthoát - hoặc vì bạn giết nó, hoặc vì sleeptrả lại và đóng đường ống để catthấy sự kết thúc của đầu vào. Vào thời điểm đó, cha mẹ của zombie chết, vì vậy zombie được thu thập bởi init và init gặt hái nó.

Nếu bạn thay đổi lệnh thành

{ cat <( sleep 100 & wait ); echo done; } &

sau đó catchạy trong một quy trình riêng biệt, không phải trong đứa trẻ của quy trình bash ban đầu: đứa trẻ đầu tiên phải ở lại để chạy echo done. Trong trường hợp này, nếu bạn giết cháu, nó sẽ không tồn tại như một thây ma, bởi vì đứa trẻ (vẫn đang chạy bash vào thời điểm đó) gặt hái nó.

Xem thêm Làm thế nào để linux xử lý quá trình zombiezombie có thể có trẻ mồ côi không? Những đứa trẻ mồ côi sẽ bị quấy rầy bằng cách gặt hái zombie?


Tôi đã ngạc nhiên về điều quá trình nhóm quá. Có vẻ như đó là một lỗi và hiện đã được sửa trong nhánh bash master.
PSkocik

"Bash ban đầu chờ đợi đứa con của nó (14247)." Tại sao hay theo cách nào? Đứa trẻ được cho là chạy trong nền và không có cuộc gọi rõ ràng. Có gì khác biệt giữa bash ban đầu (14246) đang chờ 14247 và 14247 (đang chạy cat) không chờ đợi 14248 (chờ sleep)? Có một số ký ức về những người chờ đợi ai, mà đứa trẻ (14247) đã mất và bash ban đầu (14246) không, hoặc có thể là một danh sách các tín hiệu như SIGCHLD của những người nên được gọi và 14247 (hiện đang chạy bash) không đăng ký với Liên quan đến 14248?

1
@tomas Ý tôi là bash ban đầu gọi waitcon của nó, tức là nó gặt nó. Tôi có thể thấy điều này sẽ gây nhầm lẫn như thế nào, tôi đã loại bỏ câu đó thậm chí không đúng thời điểm nói theo trình tự thời gian. Thông tin mà một quá trình đã chết được gửi đến cha mẹ của quá trình đó, một quá trình không thể đăng ký thành công để nhận thông tin về cái chết của một quá trình khác.
Gilles 'SO- ngừng trở nên xấu xa'

6

Zombie không chờ đợi đứa trẻ. Thay vào đó, zombie là các quá trình đó đã chết (bằng cách riêng của mình, hoặc bị giết - như trong ví dụ của bạn), có mã của nó, dữ liệu và ngăn xếp deallocated, và bây giờ chỉ chứa mã lối ra của nó, chờ đợi mẹ gọi wait(2)để lấy nó (và do đó cuối cùng làm sạch quá trình nhập hoàn toàn từ bảng quy trình)

Trong ví dụ của bạn, khi giấc ngủ kết thúc (hoặc bị giết), cha mẹ sẽ đọc các trạng thái thoát và gặt hái zombie. Xem ở trên wait(2)để biết chi tiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.