Chương trình sẽ làm gì khi gửi tín hiệu SIGKILL?


39

Khi tôi từng killall -9 namegiế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:


66

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)


5
Điều gì xảy ra nếu quá trình trong một cuộc gọi kernel (ví dụ: thực hiện I / O) khi SIGKILL được gửi?
gidds

9
@gidds Hoặc I / O sẽ bị hủy để thực thi SIGKILL hoặc SIGKILL sẽ bị trì hoãn cho đến khi I / O hoàn thành. Đây là sự khác biệt giữa trạng thái ngủ 'S' và 'D' trong 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ể.
zwol

6
Nó không hoàn toàn chính xác để nói rằng lịch trình ngay lập tức dừng lại cho quá trình CPU thời gian. Phía hạt nhân của việc xử lý tín hiệu vẫn được thực thi bởi quy trình đó, nhưng quá trình sẽ chỉ thực thi mã hạt nhân để bạn nói đúng khi bạn nói chương trình không bao giờ nhận được tín hiệu. Quá trình sẽ thực thi mã hạt nhân chịu trách nhiệm cho hầu hết việc dọn dẹp tài nguyên (mở tệp, bộ nhớ ảo, v.v.) Các bước cuối cùng của mã dọn dẹp này là thay đổi trạng thái quy trình thành zombie và gọi trình lập lịch biểu. Sau đó, nó sẽ không bao giờ được lên lịch lại.
kasperd

4
@gidds Có ít nhất bốn trạng thái khác nhau mà quá trình có thể xảy ra. Nó có thể đang chạy mã hạt nhân tại thời điểm này hoặc nó có thể ngủ ở một trong ba trạng thái ngủ khác nhau. Các trạng thái ngủ có thể bị gián đoạn, không bị gián đoạn hoặc không bị gián đoạn trừ các tín hiệu chết người. Nếu nó ở trong giấc ngủ không bị gián đoạn, nó sẽ được ngủ miễn là nó cần và chỉ khi nó thức dậy, nó sẽ có cơ hội chết. Nếu nó ở một trong hai trạng thái ngủ khác, nó sẽ được đánh thức ngay lập tức và được lên lịch ngay khi có sẵn CPU.
kasperd

2
@gidds Điều gì xảy ra tiếp theo phụ thuộc vào mã kernel mà nó đang chạy. Bất kể nó đã chạy hay trước tiên phải được đánh thức và sau đó có thể bắt đầu chạy mã hạt nhân mà nó đã có tại thời điểm đó sẽ được phép tiếp tục. Và mã hạt nhân đó có trách nhiệm nhận thấy rằng quá trình này đã được thông báo là chết và hành động tương ứng. Hầu hết thời gian, cách thích hợp để xử lý vấn đề đó trong mã kernel là chỉ trả về lỗi từ bất kỳ chức năng nào mà nó đang thực thi. Khi ngăn xếp cuộc gọi kernel đã được mở ra, mã xử lý tín hiệu có thể tiếp quản ngay trước khi trở về chế độ người dùng.
kasperd
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.