Gửi kill -9 đến một quy trình không yêu cầu sự hợp tác của quy trình (như xử lý tín hiệu), nó sẽ giết chết nó.
Bạn cho rằng bởi vì một số tín hiệu có thể bị bắt và bỏ qua chúng đều liên quan đến sự hợp tác. Nhưng theo như man 2 signal
, "các tín hiệu SIGKILL và SIGSTOP có thể bị bắt hoặc bỏ qua". SIGTERM có thể bị bắt, đó là lý do tại sao đồng bằng kill
không phải lúc nào cũng hiệu quả - nói chung điều này có nghĩa là một cái gì đó trong trình xử lý của quy trình đã bị sai lệch. 1
Nếu một quá trình không (hoặc không thể) xác định trình xử lý cho tín hiệu đã cho, thì kernel thực hiện một hành động mặc định. Trong trường hợp SIGTERM và SIGKILL, điều này là để chấm dứt quá trình (trừ khi PID của nó là 1; hạt nhân sẽ không chấm dứt init
) 2 nghĩa là các tệp xử lý của nó bị đóng, bộ nhớ của nó được trả về nhóm hệ thống, cha mẹ của nó nhận SIGCHILD, mồ côi của nó trẻ em được thừa kế bởi init, v.v., giống như nó đã được gọi exit
(xem man 2 exit
). Quá trình không còn tồn tại - trừ khi nó kết thúc dưới dạng zombie, trong trường hợp đó, nó vẫn được liệt kê trong bảng quy trình của kernel với một số thông tin; Điều đó xảy ra khi cha mẹ của nó khôngwait
và đối phó với thông tin này đúng cách. Tuy nhiên, các quá trình zombie không còn có bất kỳ bộ nhớ nào được phân bổ cho chúng và do đó không thể tiếp tục thực thi.
Có thứ gì đó giống như một bảng toàn cầu trong bộ nhớ trong đó Linux giữ các tham chiếu đến tất cả các tài nguyên được chiếm bởi một quy trình và khi tôi "giết" một quy trình, Linux chỉ đơn giản đi qua bảng đó và giải phóng từng tài nguyên một?
Tôi nghĩ đó là đủ chính xác. Bộ nhớ vật lý được theo dõi theo trang (một trang thường bằng một đoạn 4 KB) và các trang đó được lấy từ và trở về nhóm chung. Điều phức tạp hơn một chút là một số trang được giải phóng được lưu trong bộ nhớ cache trong trường hợp dữ liệu chứa trong đó được yêu cầu lại (nghĩa là dữ liệu được đọc từ một tệp vẫn còn tồn tại).
Các trang nói về "tín hiệu" nhưng chắc chắn đó chỉ là một sự trừu tượng.
Chắc chắn, tất cả các tín hiệu là một trừu tượng. Chúng là khái niệm, giống như "quy trình". Tôi đang chơi ngữ nghĩa một chút, nhưng nếu bạn muốn nói SIGKILL khác biệt về chất so với SIGTERM, thì có và không. Đúng theo nghĩa là nó không thể bị bắt, nhưng không có nghĩa là cả hai đều là tín hiệu. Theo một định nghĩa tương tự, một quả táo không phải là một quả cam mà là táo và cam, theo một định nghĩa định sẵn, cả hai quả. SIGKILL có vẻ trừu tượng hơn vì bạn không thể bắt được nó, nhưng nó vẫn là một tín hiệu. Đây là một ví dụ về xử lý SIGTERM, tôi chắc chắn bạn đã thấy những điều này trước đây:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
void sighandler (int signum, siginfo_t *info, void *context) {
fprintf (
stderr,
"Received %d from pid %u, uid %u.\n",
info->si_signo,
info->si_pid,
info->si_uid
);
}
int main (void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sighandler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &sa, NULL);
while (1) sleep(10);
return 0;
}
Quá trình này sẽ chỉ ngủ mãi mãi. Bạn có thể chạy nó trong một thiết bị đầu cuối và gửi SIGTERM với kill
. Nó phun ra những thứ như:
Received 15 from pid 25331, uid 1066.
1066 là UID của tôi. Bộ vi xử lý sẽ là lớp vỏ mà từ đó kill
được thực thi hoặc bộ lọc giết chết nếu bạn rẽ nhánh nó ( kill 25309 & echo $?
).
Một lần nữa, không có điểm nào trong việc thiết lập trình xử lý cho SIGKILL vì nó không hoạt động. 3 Nếu tôi kill -9 25309
quá trình sẽ chấm dứt. Nhưng đó vẫn là một tín hiệu; hạt nhân có thông tin về người đã gửi tín hiệu , loại tín hiệu đó là gì, v.v.
1. Nếu bạn chưa xem danh sách các tín hiệu có thể , hãy xem kill -l
.
2. Một ngoại lệ khác, như Tim Post đề cập dưới đây, áp dụng cho các quá trình trong giấc ngủ không bị gián đoạn . Chúng không thể được đánh thức cho đến khi vấn đề cơ bản được giải quyết và do đó TẤT CẢ các tín hiệu (bao gồm cả SIGKILL) được hoãn lại trong suốt thời gian. Tuy nhiên, một quá trình không thể tạo ra tình huống đó theo mục đích.
3. Điều này không có nghĩa là sử dụng kill -9
là một điều tốt hơn để làm trong thực tế. Trình xử lý ví dụ của tôi là một điều xấu theo nghĩa mà nó không dẫn đến exit()
. Mục đích thực sự của một trình xử lý SIGTERM là tạo cơ hội cho quá trình thực hiện những việc như dọn sạch các tệp tạm thời, sau đó thoát ra một cách tự nguyện. Nếu bạn sử dụng kill -9
, nó sẽ không có cơ hội này, vì vậy chỉ làm điều đó nếu phần "thoát tự nguyện" dường như đã thất bại.
kill -9
Tài liệu tham khảo bắt buộc .