Unix / Linux - สัญญาณและกับดัก

ในบทนี้เราจะพูดถึงรายละเอียดเกี่ยวกับสัญญาณและกับดักใน Unix

สัญญาณคือการขัดจังหวะซอฟต์แวร์ที่ส่งไปยังโปรแกรมเพื่อระบุว่ามีเหตุการณ์สำคัญเกิดขึ้น เหตุการณ์อาจแตกต่างกันไปตั้งแต่คำขอของผู้ใช้ไปจนถึงข้อผิดพลาดในการเข้าถึงหน่วยความจำที่ผิดกฎหมาย สัญญาณบางอย่างเช่นสัญญาณขัดจังหวะแสดงว่าผู้ใช้ขอให้โปรแกรมทำบางสิ่งที่ไม่อยู่ในขั้นตอนการควบคุมตามปกติ

ตารางต่อไปนี้แสดงสัญญาณทั่วไปที่คุณอาจพบและต้องการใช้ในโปรแกรมของคุณ -

ชื่อสัญญาณ หมายเลขสัญญาณ คำอธิบาย
SIGHUP 1 ตรวจพบการวางสายที่เครื่องควบคุมหรือการเสียชีวิตของกระบวนการควบคุม
ซิกนต์ 2 ออกหากผู้ใช้ส่งสัญญาณขัดจังหวะ (Ctrl + C)
SIGQUIT 3 ออกหากผู้ใช้ส่งสัญญาณออก (Ctrl + D)
SIGFPE 8 ออกหากมีการพยายามดำเนินการทางคณิตศาสตร์ที่ผิดกฎหมาย
ซิกกิล 9 หากกระบวนการได้รับสัญญาณนี้จะต้องปิดทันทีและจะไม่ดำเนินการล้างข้อมูลใด ๆ
SIGALRM 14 สัญญาณนาฬิกาปลุก (ใช้สำหรับจับเวลา)
ซิกเทอร์ม 15 สัญญาณการยุติซอฟต์แวร์ (ส่งโดย kill โดยค่าเริ่มต้น)

รายการสัญญาณ

มีวิธีง่ายๆในการแสดงรายการสัญญาณทั้งหมดที่ระบบของคุณรองรับ เพียงแค่ออกไฟล์kill -l คำสั่งและจะแสดงสัญญาณที่รองรับทั้งหมด -

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

รายการสัญญาณจริงจะแตกต่างกันไประหว่าง Solaris, HP-UX และ Linux

การดำเนินการเริ่มต้น

ทุกสัญญาณมีการดำเนินการเริ่มต้นที่เกี่ยวข้อง การดำเนินการเริ่มต้นสำหรับสัญญาณคือการกระทำที่สคริปต์หรือโปรแกรมดำเนินการเมื่อได้รับสัญญาณ

การดำเนินการเริ่มต้นบางอย่างที่เป็นไปได้คือ -

  • ยุติกระบวนการ

  • ไม่สนใจสัญญาณ

  • แกนถ่ายโอนข้อมูล สิ่งนี้จะสร้างไฟล์ชื่อcore มีภาพหน่วยความจำของกระบวนการเมื่อได้รับสัญญาณ

  • หยุดกระบวนการ

  • ดำเนินการต่อตามกระบวนการที่หยุด

การส่งสัญญาณ

มีหลายวิธีในการส่งสัญญาณไปยังโปรแกรมหรือสคริปต์ สิ่งหนึ่งที่พบบ่อยที่สุดคือการที่ผู้ใช้พิมพ์CONTROL-C หรือ INTERRUPT key ในขณะที่สคริปต์กำลังดำเนินการ

เมื่อคุณกดปุ่ม Ctrl+C คีย์ a SIGINT ถูกส่งไปยังสคริปต์และตามสคริปต์การดำเนินการเริ่มต้นที่กำหนดไว้จะสิ้นสุดลง

วิธีอื่น ๆ ทั่วไปในการส่งสัญญาณคือการใช้ kill commandซึ่งเป็นไวยากรณ์ดังต่อไปนี้ -

$ kill -signal pid

ที่นี่ signal เป็นหมายเลขหรือชื่อของสัญญาณที่จะส่งและ pidคือรหัสกระบวนการที่สัญญาณควรถูกส่งไป ตัวอย่างเช่น -

$ kill -1 1001

คำสั่งดังกล่าวจะส่งสัญญาณ HUP หรือวางสายไปยังโปรแกรมที่กำลังทำงานด้วย process ID 1001. ในการส่งสัญญาณฆ่าไปยังกระบวนการเดียวกันให้ใช้คำสั่งต่อไปนี้ -

$ kill -9 1001

สิ่งนี้จะฆ่ากระบวนการที่ทำงานด้วย process ID 1001.

ดักสัญญาณ

เมื่อคุณกดแป้น Ctrl + Cหรือ Break ที่เทอร์มินัลของคุณในระหว่างดำเนินการโปรแกรมเชลล์โดยปกติโปรแกรมนั้นจะถูกยกเลิกทันทีและพร้อมท์คำสั่งของคุณจะกลับมา สิ่งนี้อาจไม่เป็นที่ต้องการเสมอไป ตัวอย่างเช่นคุณอาจทิ้งไฟล์ชั่วคราวไว้มากมายซึ่งจะไม่ได้รับการล้างข้อมูล

การดักจับสัญญาณเหล่านี้ค่อนข้างง่ายและคำสั่ง trap มีไวยากรณ์ต่อไปนี้ -

$ trap commands signals

คำสั่งที่นี่อาจเป็นคำสั่ง Unix ที่ถูกต้องหรือแม้แต่ฟังก์ชันที่ผู้ใช้กำหนดเองและสัญญาณสามารถเป็นรายการสัญญาณจำนวนเท่าใดก็ได้ที่คุณต้องการดักจับ

มีสองการใช้งานทั่วไปสำหรับกับดักในเชลล์สคริปต์ -

  • ล้างไฟล์ชั่วคราว
  • ไม่สนใจสัญญาณ

การล้างไฟล์ชั่วคราว

ดังตัวอย่างของคำสั่ง trap ต่อไปนี้จะแสดงวิธีลบไฟล์บางไฟล์แล้วออกหากมีคนพยายามยกเลิกโปรแกรมจากเทอร์มินัล -

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

จากจุดในโปรแกรมเชลล์ว่ากับดักนี้ถูกเรียกใช้ทั้งสองไฟล์ work1$$ และ dataout$$ จะถูกลบออกโดยอัตโนมัติหากโปรแกรมได้รับสัญญาณหมายเลข 2

ดังนั้นหากผู้ใช้ขัดขวางการทำงานของโปรแกรมหลังจากที่เรียกใช้กับดักนี้คุณสามารถมั่นใจได้ว่าไฟล์ทั้งสองนี้จะถูกล้าง exit คำสั่งที่เป็นไปตาม rm เป็นสิ่งที่จำเป็นเพราะหากไม่มีมันการดำเนินการจะดำเนินต่อไปในโปรแกรม ณ จุดที่ทิ้งไว้เมื่อได้รับสัญญาณ

สัญญาณหมายเลข 1 ถูกสร้างขึ้นสำหรับ hangup. อาจมีคนวางสายโดยเจตนาหรือสายหลุดโดยไม่ได้ตั้งใจ

คุณสามารถแก้ไขกับดักก่อนหน้านี้เพื่อลบไฟล์ที่ระบุสองไฟล์ในกรณีนี้โดยเพิ่มสัญญาณหมายเลข 1 ในรายการสัญญาณ -

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

ตอนนี้ไฟล์เหล่านี้จะถูกลบออกหากสายที่ได้รับการแขวนขึ้นหรือถ้าCtrl + Cที่สำคัญได้รับการกด

คำสั่งที่ระบุเพื่อดักต้องอยู่ในเครื่องหมายคำพูดหากมีคำสั่งมากกว่าหนึ่งคำสั่ง นอกจากนี้โปรดทราบว่าเชลล์จะสแกนบรรทัดคำสั่งในเวลาที่คำสั่ง trap ถูกเรียกใช้งานและเมื่อได้รับสัญญาณรายการใดรายการหนึ่ง

ดังนั้นในตัวอย่างก่อนหน้านี้ค่าของ WORKDIR และ $$จะถูกแทนที่เมื่อคำสั่งกับดักถูกเรียกใช้งาน หากคุณต้องการให้การแทนที่นี้เกิดขึ้นในเวลาที่ได้รับสัญญาณ 1 หรือ 2 คุณสามารถใส่คำสั่งไว้ในเครื่องหมายคำพูดเดี่ยว -

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

ไม่สนใจสัญญาณ

หากคำสั่งที่แสดงรายการสำหรับ trap เป็นโมฆะสัญญาณที่ระบุจะถูกละเว้นเมื่อได้รับ ตัวอย่างเช่นคำสั่ง -

$ trap '' 2

สิ่งนี้ระบุว่าสัญญาณขัดจังหวะจะถูกละเว้น คุณอาจต้องการละเว้นสัญญาณบางอย่างเมื่อดำเนินการที่คุณไม่ต้องการถูกขัดจังหวะ คุณสามารถระบุสัญญาณหลายรายการที่จะละเว้นได้ดังนี้ -

$ trap '' 1 2 3 15

โปรดทราบว่าต้องระบุอาร์กิวเมนต์แรกเพื่อให้สัญญาณถูกละเว้นและไม่เทียบเท่ากับการเขียนสิ่งต่อไปนี้ซึ่งมีความหมายแยกต่างหาก -

$ trap  2

หากคุณเพิกเฉยต่อสัญญาณซับเชลล์ทั้งหมดจะไม่สนใจสัญญาณนั้นด้วย อย่างไรก็ตามหากคุณระบุการดำเนินการที่จะต้องดำเนินการกับการรับสัญญาณซับเชลล์ทั้งหมดจะยังคงดำเนินการตามค่าเริ่มต้นเมื่อได้รับสัญญาณนั้น

การรีเซ็ตกับดัก

หลังจากที่คุณเปลี่ยนการดำเนินการเริ่มต้นที่จะดำเนินการเมื่อได้รับสัญญาณแล้วคุณสามารถเปลี่ยนกลับอีกครั้งโดยใช้กับดักถ้าคุณเพียงแค่ละเว้นอาร์กิวเมนต์แรก ดังนั้น -

$ trap 1 2

การดำเนินการนี้จะรีเซ็ตการดำเนินการในการรับสัญญาณ 1 หรือ 2 กลับไปเป็นค่าเริ่มต้น