Khi tôi từng killall -9 name
giết một chương trình, nhà nước trở thành zombie. Vài phút sau, nó dừng lại thực sự. Vì vậy, những gì xảy ra trong những phút đó?
Khi tôi từng killall -9 name
giết một chương trình, nhà nước trở thành zombie. Vài phút sau, nó dừng lại thực sự. Vì vậy, những gì xảy ra trong những phút đó?
Câu trả lời:
Chương trình thực sự không bao giờ nhận được tín hiệu SIGKILL, vì SIGKILL được xử lý hoàn toàn bởi hệ điều hành / kernel.
Khi SIGKILL cho một quy trình cụ thể được gửi, bộ lập lịch của kernel ngay lập tức dừng cung cấp cho quá trình đó thêm bất kỳ thời gian CPU nào để chạy mã không gian người dùng. Nếu quy trình có bất kỳ luồng nào thực thi mã không gian người dùng trên các CPU / lõi khác tại thời điểm bộ lập lịch đưa ra quyết định này, các luồng đó cũng sẽ bị dừng. (Trong các hệ thống lõi đơn, điều này thường đơn giản hơn nhiều: nếu lõi CPU duy nhất trong hệ thống đang chạy bộ lập lịch, thì theo định nghĩa, nó không chạy quy trình cùng một lúc!)
Nếu tiến trình / luồng đang thực thi mã hạt nhân (ví dụ: cuộc gọi hệ thống hoặc thao tác I / O được liên kết với tệp ánh xạ bộ nhớ) tại thời điểm SIGKILL, thì sẽ khó khăn hơn một chút: chỉ một số cuộc gọi hệ thống bị gián đoạn, do đó, kernel bên trong đánh dấu quá trình ở trạng thái "chết" đặc biệt cho đến khi hệ thống gọi hoặc thao tác I / O được giải quyết. Thời gian CPU để giải quyết chúng sẽ được lên lịch như bình thường. Các cuộc gọi hệ thống gián đoạn hoặc các hoạt động I / O sẽ kiểm tra xem quy trình gọi chúng có bị chết tại bất kỳ điểm dừng phù hợp nào không và sẽ thoát sớm trong trường hợp đó. Các hoạt động không bị gián đoạn sẽ chạy vào hoàn thành và sẽ kiểm tra trạng thái "sắp chết" ngay trước khi quay lại mã không gian người dùng.
Khi bất kỳ thói quen kernel trong tiến trình nào được giải quyết, trạng thái quá trình được thay đổi từ "chết" thành "chết" và kernel bắt đầu dọn dẹp nó, tương tự như khi chương trình thoát ra bình thường. Khi quá trình dọn dẹp hoàn tất, mã kết quả lớn hơn 128 sẽ được chỉ định (để chỉ ra rằng quá trình đã bị giết bởi tín hiệu; xem câu trả lời này để biết chi tiết lộn xộn ) và quá trình sẽ chuyển sang trạng thái "zombie" . Cha mẹ của quá trình bị giết sẽ được thông báo bằng tín hiệu SIGCHLD.
Kết quả là, quá trình tự nó sẽ không bao giờ có cơ hội thực sự xử lý thông tin mà nó đã nhận được SIGKILL.
Khi một tiến trình ở trạng thái "zombie", điều đó có nghĩa là quá trình đã chết, nhưng quá trình mẹ của nó vẫn chưa thừa nhận điều này bằng cách đọc mã thoát của quy trình chết bằng cách sử dụng lệnh wait(2)
gọi hệ thống. Về cơ bản, tài nguyên duy nhất mà một quá trình zombie đang tiêu thụ nữa là một vị trí trong bảng quy trình chứa PID, mã thoát và một số "thống kê quan trọng" khác của quy trình tại thời điểm nó chết.
Nếu quy trình cha mẹ chết trước khi con của nó, các quy trình con mồ côi sẽ tự động được áp dụng bởi PID # 1, có nhiệm vụ đặc biệt là tiếp tục gọi wait(2)
để bất kỳ quy trình mồ côi nào không dính vào zombie.
Nếu phải mất vài phút để một quá trình zombie hoàn thành, nó gợi ý rằng quá trình cha mẹ của zombie đang gặp khó khăn hoặc không thực hiện đúng công việc của nó.
Có một mô tả chi tiết về những việc cần làm trong trường hợp có vấn đề về zombie trong các hệ điều hành giống Unix: "Bạn không thể làm bất cứ điều gì cho chính zombie, vì chúng đã chết. Thay vào đó, hãy tiêu diệt tên chủ zombie độc ác! " (tức là quá trình cha mẹ của những thây ma rắc rối)
ps
: 'S' dành cho I / O chờ rằng hạt nhân có thể hủy để phát tín hiệu và 'D' cho những trạng thái không thể.