Câu trả lời của @hvd về cơ bản là chính xác. Để sao lưu nhiều hơn nữa, init
trước tiên quy trình sẽ gửi SIGTERM
đến các quy trình khi bạn tắt máy tính, sau đó sẽ trì hoãn SIGKILL
nếu chúng chưa thoát. Các quy trình không thể xử lý / bỏ qua SIGKILL
.
Để cung cấp thêm một chút chi tiết, câu trả lời thực sự là bạn không có cách nào để biết chắc chắn rằng chương trình xử lý nó. SIGTERM
là tín hiệu thông thường nhất được sử dụng để yêu cầu chương trình thoát một cách lịch sự, nhưng tất cả việc xử lý tín hiệu phụ thuộc vào chương trình thực hiện điều gì đó với tín hiệu.
Nói cách khác, dựa trên các câu trả lời khác, nếu bạn có chương trình được viết bởi @Jos hoặc @AlexGreg thì có lẽ họ sẽ xử lý SIGQUIT
nhưng có thể không SIGTERM
, và do đó việc gửi SIGTERM
sẽ ít "mềm" hơn SIGQUIT
.
Tôi đã viết một số mã để bạn có thể tự chơi xung quanh nó. Lưu dưới đây signal-test.c
, sau đó biên dịch với
gcc -o signal-test signal-test.c
Sau đó, bạn có thể chạy nó ./signal-test
và xem điều gì sẽ xảy ra khi bạn gửi các tín hiệu khác nhau killall -s <signal>
.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int flag = 0;
void handle_signal(int s)
{
flag = s;
}
int main(int argc, char *argv[])
{
signal(SIGTERM, handle_signal);
signal(SIGQUIT, handle_signal);
while(flag == 0){
sleep(1);
}
printf("flag is %d\n", flag);
return flag;
}
Khi nó đứng, mã xử lý cả SIGTERM và SIGQUIT một cách duyên dáng. Bạn có thể thử nhận xét các dòng signal(SIG...
(sử dụng a //
ở đầu dòng) để loại bỏ trình xử lý tín hiệu, sau đó chạy và gửi lại các tín hiệu. Bạn sẽ có thể thấy các đầu ra khác nhau:
$ ./signal-test
Terminated
$ ./signal-test
Quit (core dumped)
$ ./signal-test
flag is 15
$ ./signal-test
flag is 3
tùy thuộc vào việc bạn xử lý các tín hiệu hay không.
Bạn cũng có thể thử bỏ qua các tín hiệu:
signal(SIGTERM, SIG_IGN);
Nếu bạn làm điều đó thì việc gửi SIGTERM
sẽ không làm gì cả, bạn sẽ phải sử dụng SIGKILL
để kết thúc quá trình.
Thêm chi tiết trong man 7 signal
. Lưu ý rằng sử dụng signal()
theo cách này được coi là không di động - mặc dù vậy nó dễ dàng hơn nhiều so với giải pháp thay thế!
Một chú thích nhỏ khác - về Solaris killall
cố gắng giết tất cả các quy trình. Tất cả bọn họ. Nếu bạn chạy nó với quyền root thì bạn có thể ngạc nhiên :)