กระบวนการสามารถเลือก:
- ไม่สนใจสัญญาณ SIGINT ที่มักจะส่งเมื่อกดCtrl-C(เช่นเดียวกับ
trap '' INT
ในเชลล์) หรือมีตัวจัดการของมันเองซึ่งจะไม่ตัดสินใจยุติ (หรือล้มเหลวในการยุติในเวลาที่เหมาะสม)
- บอกอุปกรณ์ปลายทางว่าตัวอักษรที่ทำให้ SIGINT ถูกส่งไปยังงานเบื้องหน้าเป็นอย่างอื่น (เช่น
stty int '^K'
ในเชลล์)
- บอกให้เครื่องปลายทางไม่ส่งสัญญาณใด ๆ (เหมือน
stty -isig
ในเปลือก)
หรือพวกเขาสามารถ uninterruptible เช่นเมื่ออยู่ในช่วงกลางของการเรียกระบบที่ไม่สามารถถูกขัดจังหวะ
บน Linux (ที่มีเคอร์เนลค่อนข้างล่าสุด) คุณสามารถบอกได้ว่ากระบวนการกำลังเพิกเฉยและ / หรือจัดการ SIGINT โดยดูที่ผลลัพธ์ของ
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT คือ 2 บิตที่สองของ SigIgn ด้านบนคือ 1 ซึ่งหมายความว่า SIGINT จะถูกละเว้น
คุณสามารถทำให้เป็นอัตโนมัติด้วย:
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
วิธีตรวจสอบintr
อักขระปัจจุบันคืออะไรหรือหากisig
เปิดใช้งานเทอร์มินัลที่กำหนด:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(เหนือintr
ตัวละครคือ^C
(ตัวละครมักส่งโดยเทอร์มินัลของคุณ (อีมูเลเตอร์) เมื่อกดCTRL-Cและสัญญาณอินพุตจะไม่ถูกปิดใช้งาน
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
( intr
ตัวละครเป็น^K
และisig
ถูกปิดการใช้งานสำหรับ/dev/pts/1
)
เพื่อความสมบูรณ์มีสองวิธีที่กระบวนการอาจทำบางสิ่งเพื่อหยุดรับ SIGINT แม้ว่าจะไม่ใช่สิ่งที่คุณมักจะเห็น
เมื่อCtrl+Cสัญญาณ SIGINT ถูกส่งไปยังกระบวนการทั้งหมดในกลุ่มกระบวนการเบื้องหน้าของอาคาร มันมักจะเป็นเปลือกว่ากระบวนการที่เกิดขึ้นในกระบวนการกลุ่ม (แมปไปยังเปลือกงาน ) และบอกอุปกรณ์ปลายทางซึ่งเป็นเบื้องหน้าหนึ่ง
ตอนนี้กระบวนการสามารถ:
ออกจากกลุ่มกระบวนการ หากมันย้ายไปยังกลุ่มกระบวนการอื่น (กลุ่มกระบวนการใด ๆ แต่กลุ่มที่เป็นส่วนหน้า ) ก็จะไม่ได้รับ SIGINT เมื่อCtrl-C(หรือสัญญาณอื่น ๆ ที่เกี่ยวข้องกับคีย์บอร์ดเช่น SIGTSTP, SIGQUIT) อย่างไรก็ตามอาจถูกระงับหากพยายามอ่าน (อาจเขียนได้เช่นกันขึ้นอยู่กับการตั้งค่าอุปกรณ์เทอร์มินัล) จากอุปกรณ์เทอร์มินัล (ตามกระบวนการพื้นหลัง)
ตัวอย่างเช่น:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
ไม่อาจจะ Interruptible Ctrl-Cกับ ด้านบนperl
จะพยายามเข้าร่วมกลุ่มกระบวนการที่มี ID เหมือนกับ ID กระบวนการหลัก โดยทั่วไปไม่รับประกันว่าจะมีกลุ่มกระบวนการที่มีรหัสนั้น แต่ที่นี่ในกรณีที่perl
คำสั่งนั้นรันด้วยตัวเองที่พร้อมต์ของเชลล์แบบโต้ตอบ ppid จะเป็นกระบวนการของเชลล์และโดยทั่วไปเชลล์จะเริ่มต้นในกลุ่มกระบวนการของตัวเอง
หากคำสั่งยังไม่ได้เป็นหัวหน้ากลุ่มกระบวนการ (ผู้นำของกลุ่มกระบวนการเบื้องหน้านั้น) จากนั้นคำสั่งนั้นเริ่มต้นกลุ่มกระบวนการใหม่จะมีผลเหมือนกัน
ยกตัวอย่างเช่นขึ้นอยู่กับเปลือก
$ 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
จะมีผลเช่นเดียวกัน ps
และperl
เริ่มต้นในกลุ่มกระบวนการพื้นหน้า แต่บนเชลล์ส่วนใหญ่ps
จะเป็นผู้นำของกลุ่มนั้น (ดังที่เห็นในps
เอาต์พุตด้านบนโดยที่ pgid ของทั้งสองps
และperl
เป็น pid ของps
) ดังนั้นจึงperl
สามารถเริ่มกลุ่มกระบวนการของตัวเองได้
หรืออาจเปลี่ยนกลุ่มกระบวนการพื้นหน้า บอกอุปกรณ์ tty โดยทั่วไปให้ส่ง SIGINT ไปยังกลุ่มกระบวนการอื่น ๆCtrl+C
perl -MPOSIX -e 'tcsetpgrp (0, getppid) หรือตาย $ !; หลับ 5 '
ที่นั่นperl
ยังคงอยู่ในกลุ่มกระบวนการเดียวกัน แต่บอกอุปกรณ์เทอร์มินัลว่ากลุ่มกระบวนการพื้นหน้าเป็นอุปกรณ์ที่มี ID เหมือนกับ ID กระบวนการหลัก (ดูหมายเหตุด้านบนเกี่ยวกับเรื่องนั้น)
kill -9 %
เพื่อฆ่ามัน สัญญาณที่ 9 ไม่สามารถเพิกเฉยได้และไม่สามารถระงับสัญญาณได้ ลำดับของแป้นพิมพ์ CTRL + Z สามารถละเว้นได้ในทางทฤษฎี แต่ไม่สามารถใช้งานได้จริง