Các quy trình có thể chọn:
- bỏ qua tín hiệu SIGINT thường được gửi khi nhấn Ctrl-C(như với
trap '' INT
vỏ) hoặc có trình xử lý riêng để quyết định không chấm dứt (hoặc không kết thúc kịp thời).
- nói với thiết bị đầu cuối rằng ký tự khiến SIGINT được gửi đến công việc nền trước là một cái gì đó khác (như với
stty int '^K'
vỏ)
- yêu cầu thiết bị đầu cuối không gửi bất kỳ tín hiệu nào (như với
stty -isig
vỏ).
Hoặc, chúng có thể không bị gián đoạn, như khi ở giữa một cuộc gọi hệ thống không thể bị gián đoạn.
Trên Linux (với một hạt nhân tương đối gần đây), bạn có thể biết liệu một quy trình có bỏ qua và / hoặc xử lý SIGINT hay không bằng cách xem kết quả đầu ra của
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT là 2. Bit thứ hai của SigIgn ở trên là 1, có nghĩa là SIGINT bị bỏ qua.
Bạn có thể tự động hóa điều đó với:
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
Để kiểm tra intr
ký tự hiện tại là gì hoặc nếu isig
được bật cho một thiết bị đầu cuối cụ thể:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(phía trên intr
ký tự là ^C
(ký tự thường được gửi bởi thiết bị đầu cuối (trình giả lập) của bạn khi nhấn CTRL-Cvà tín hiệu đầu vào không bị tắt.
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
( intr
ký tự được ^K
và isig
bị vô hiệu hóa /dev/pts/1
).
Để hoàn thiện, có hai cách khác mà một quy trình có thể làm một cái gì đó để ngừng nhận SIGINT mặc dù đó không phải là thứ bạn thường thấy.
Khi đó Ctrl+C, tín hiệu SIGINT được gửi đến tất cả các quy trình trong nhóm quy trình nền trước của thiết bị đầu cuối . Nó thường vỏ rằng các quá trình diễn ra trong nhóm quá trình (ánh xạ tới vỏ công việc ) và nói với các thiết bị đầu cuối là foreground một.
Bây giờ một quá trình có thể:
Rời khỏi nhóm quá trình của nó. Nếu nó di chuyển sang nhóm quy trình khác (bất kỳ nhóm quy trình nào ngoại trừ nhóm quy trình trước ), thì nó sẽ không còn nhận được SIGINT theo Ctrl-C(cũng như các tín hiệu liên quan đến bàn phím khác như SIGTSTP, SIGQUIT). Tuy nhiên, nó có thể bị treo nếu nó cố đọc (có thể viết tùy thuộc vào cài đặt thiết bị đầu cuối) từ thiết bị đầu cuối (như các quá trình nền làm).
Ví dụ:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
không thể bị gián đoạn với Ctrl-C. Ở trên perl
sẽ cố gắng tham gia nhóm quy trình có ID giống với ID quy trình mẹ của nó. Nói chung, không có gì đảm bảo rằng có một nhóm quy trình như vậy với id đó. Nhưng ở đây, trong trường hợp perl
lệnh đó tự chạy theo dấu nhắc của trình bao tương tác, ppid sẽ là quy trình của trình bao và trình bao thường sẽ được bắt đầu trong nhóm quy trình riêng của nó.
Nếu lệnh chưa phải là một người lãnh đạo nhóm quy trình (người lãnh đạo của nhóm quy trình tiền cảnh đó), thì nó bắt đầu một nhóm quy trình mới sẽ có tác dụng tương tự.
Ví dụ, tùy thuộc vào vỏ,
$ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
PID PGID SID TTY TIME CMD
21435 21435 21435 pts/12 00:00:00 zsh
21441 21441 21435 pts/12 00:00:00 ps
21442 21441 21435 pts/12 00:00:00 perl
sẽ có tác dụng tương tự. ps
và perl
được bắt đầu trong nhóm quy trình tiền cảnh, nhưng trên hầu hết các shell, ps
sẽ là người lãnh đạo của nhóm đó (như được thấy trong ps
đầu ra ở trên nơi pgid của cả hai ps
và perl
là pid của ps
), vì vậy perl
có thể bắt đầu nhóm quy trình riêng của mình.
Hoặc nó có thể thay đổi nhóm quá trình tiền cảnh. Về cơ bản hãy nói với thiết bị tty để gửi SIGINT cho một số nhóm quy trình khác khiCtrl+C
perl -MPOSIX -e 'tcsetpgrp (0, getppid) hoặc chết $!; ngủ 5 '
Ở đó, perl
vẫn nằm trong cùng một nhóm quy trình nhưng thay vào đó là nói với thiết bị đầu cuối rằng nhóm quy trình tiền cảnh là nhóm có ID giống với ID tiến trình mẹ của nó (xem ghi chú ở trên về điều đó).
kill -9 %
để giết nó. Tín hiệu 9 không thể bỏ qua, cũng không thể bỏ qua tín hiệu. Trình tự bàn phím CTRL + Z có thể bị bỏ qua trong lý thuyết - nhưng thực tế không phải vậy.