อะไรเป็นสาเหตุให้มีการส่งสัญญาณต่าง ๆ


28

บางครั้งฉันก็สับสนเล็กน้อยจากสัญญาณทั้งหมดที่กระบวนการสามารถรับได้ ขณะที่ผมเข้าใจว่ามันเป็นกระบวนการที่มีการดำเนินการเริ่มต้น ( สัญญาณจำหน่าย ) สำหรับแต่ละสัญญาณเหล่านี้ sigaction()แต่ก็สามารถให้การจัดการของตัวเองโดยการเรียก

ดังนั้นนี่คือคำถามของฉันสิ่งที่ทำให้แต่ละสัญญาณจะถูกส่ง? ฉันรู้ว่าคุณสามารถส่งสัญญาณไปยังกระบวนการที่ทำงานผ่าน-sพารามิเตอร์ด้วยตนเองได้killแต่สิ่งที่เป็นธรรมชาติภายใต้สัญญาณเหล่านี้จะถูกส่งไป? ตัวอย่างเช่นเมื่อไหร่จะSIGINTได้รับการส่ง?

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


คำตอบที่ถูกต้องสำหรับเรื่องนี้จะเป็นมหากาพย์และโดยทั่วไปแล้วทำซ้ำข้อมูลในบทความ Wikipediaเกี่ยวกับเรื่องนี้ดังนั้นฉันจะชี้ไปที่นั่น
Shawn J. Goff

@Shawn: บทความ Wikipedia มีรายการสัญญาณ แต่ไม่มีการนำเสนอที่ชัดเจนว่าใครส่งสัญญาณอะไร
Gilles 'หยุดชั่วร้าย'

คำตอบ:


41

นอกเหนือจากการเรียกโปรkill(2)เซสสัญญาณบางตัวถูกส่งโดยเคอร์เนล (หรือบางครั้งโดยโพรเซสเอง) ในสถานการณ์ต่าง ๆ :

  • ไดรเวอร์เทอร์มินัลส่งสัญญาณที่สอดคล้องกับเหตุการณ์ต่าง ๆ :
    • การแจ้งเตือนกดปุ่ม: SIGINT(โปรดกลับไปที่วงหลัก) บนCtrl+ C, SIGQUIT(โปรดเลิกทันที) บนCtrl+ \, SIGTSTP(โปรดระงับ) บน+Ctrl Zคีย์สามารถเปลี่ยนแปลงได้ด้วยsttyคำสั่ง
    • SIGTTINและSIGTTOUถูกส่งเมื่อกระบวนการเบื้องหลังพยายามอ่านหรือเขียนไปยังเทอร์มินัลการควบคุม
    • SIGWINCH ถูกส่งไปยังสัญญาณว่าขนาดของหน้าต่างเทอร์มินัลเปลี่ยนไป
    • SIGHUPจะถูกส่งไปที่ขั้วสัญญาณได้หายไป (ในอดีตเพราะโมเด็มของคุณมีชั่วโมงอึ้งขึ้นในปัจจุบันมักจะเพราะคุณได้ปิดหน้าต่างจำลอง terminal)
  • กับดักโปรเซสเซอร์บางตัวสามารถสร้างสัญญาณ รายละเอียดเป็นสถาปัตยกรรมและระบบขึ้นอยู่กับ; นี่คือตัวอย่างทั่วไป:
    • SIGBUS สำหรับหน่วยความจำเข้าถึงที่ไม่ได้จัดแนว
    • SIGSEGV สำหรับการเข้าถึงเพจที่ไม่ได้แมป
    • SIGILL สำหรับคำสั่งที่ผิดกฎหมาย (opcode ไม่ดี);
    • SIGFPEสำหรับคำสั่ง floating-point ที่มีอาร์กิวเมนต์ไม่ดี (เช่นsqrt(-1))
  • จำนวนสัญญาณแจ้งเตือนกระบวนการเป้าหมายที่เกิดเหตุการณ์ระบบบางอย่าง:
    • SIGALRMแจ้งเตือนว่าตัวจับเวลาที่ตั้งค่าโดยกระบวนการหมดอายุ จับเวลาสามารถตั้งค่าด้วยalarm, setitimerและอื่น ๆ
    • SIGCHLD แจ้งกระบวนการที่เด็กคนหนึ่งเสียชีวิต
    • SIGPIPEถูกสร้างขึ้นเมื่อกระบวนการพยายามเขียนลงในไพพ์เมื่อการอ่านสิ้นสุดลง (ความคิดคือถ้าคุณเรียกใช้foo | barและbarออก, fooถูกฆ่าโดย a SIGPIPE)
    • SIGPOLL(เรียกอีกอย่างว่าSIGIO) แจ้งกระบวนการที่เกิดเหตุการณ์ที่ก่อให้เกิดมลพิษ POSIX ระบุเหตุการณ์ pollable I_SETSIG ioctlลงทะเบียนผ่าน ระบบจำนวนมากอนุญาตให้เหตุการณ์ที่สามารถก่อให้เกิดมลพิษได้บน descriptor ไฟล์ใด ๆ ตั้งค่าผ่านทางO_ASYNC fcntlแฟล็ก สัญญาณที่เกี่ยวข้องSIGURGซึ่งแจ้งข้อมูลเร่งด่วนบนอุปกรณ์ (ลงทะเบียนผ่านทางI_SETSIG ioctl) หรือซ็อกเก็ต
    • ในบางระบบSIGPWRจะถูกส่งไปยังทุกกระบวนการเมื่อUPSส่งสัญญาณว่าไฟฟ้าขัดข้องใกล้เข้ามา

รายการเหล่านี้ไม่ครบถ้วนสมบูรณ์ signal.hสัญญาณมาตรฐานที่กำหนดไว้ใน

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

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

สุดท้ายให้ฉันพูดถึงบางสิ่งที่ไม่ใช่สัญญาณ เมื่อคุณกดCtrl+ Dที่จุดเริ่มต้นของบรรทัดในโปรแกรมที่อ่านอินพุตจากเทอร์มินัลสิ่งนี้จะบอกโปรแกรมว่าถึงจุดสิ้นสุดของไฟล์อินพุต นี่ไม่ใช่สัญญาณ: มันถูกส่งผ่าน input / output API ชอบCtrl+ Cและเพื่อน ๆ sttyที่สำคัญสามารถกำหนดค่าด้วย


และ SIGHUP โมเด็มของคุณวางสาย :-)
Keith

1
อีกสิ่งที่ควรทราบ: SIGFPEค่อนข้างไม่ได้ตั้งใจจะถูกส่งสัญญาณด้วยจำนวนเต็มหารด้วยศูนย์และบางครั้งก็เป็นจำนวนเต็มล้นลงนาม
ephemient

18

เพื่อที่จะตอบคำถามที่สองครั้งแรกของคุณ: SIGSTOPและSIGKILLไม่สามารถจับโดยการประยุกต์ใช้ แต่ทุกสัญญาณอื่น ๆ SIGSEGVแม้ คุณสมบัตินี้มีประโยชน์สำหรับการดีบักตัวอย่างเช่นด้วยการสนับสนุนSIGSEGVไลบรารี่ที่ถูกต้องคุณสามารถฟังและสร้าง backtrace สแต็กเพื่อแสดงตำแหน่งที่ segfault นั้นเกิดขึ้น

คำอย่างเป็นทางการ (สำหรับ Linux อยู่แล้ว) ในสิ่งที่แต่ละสัญญาณมีให้โดยพิมพ์man 7 signalจากบรรทัดคำสั่ง Linux http://linux.die.net/man/7/signalมีข้อมูลเหมือนกัน แต่ตารางอ่านยาก

อย่างไรก็ตามไม่มีประสบการณ์เกี่ยวกับสัญญาณมันยากที่จะรู้จากคำอธิบายสั้น ๆ ว่าพวกเขาทำอะไรในทางปฏิบัติดังนั้นนี่คือการตีความของฉัน:

ถูกกระตุ้นจากแป้นพิมพ์

  • SIGINTCTRL+Cที่เกิดขึ้นเมื่อคุณกด
  • SIGQUITถูกกระตุ้นโดยCTRL+\และทิ้งแกน
  • SIGTSTPCTRL+Zระงับโปรแกรมของคุณเมื่อคุณกด ซึ่งแตกต่างจากSIGSTOPมันจับได้ซึ่งให้โปรแกรมเช่นviโอกาสที่จะรีเซ็ต terminal เป็นสถานะที่ปลอดภัยก่อนที่จะระงับตัวเอง

การโต้ตอบกับเทอร์มินัล

  • SIGHUP ("hangup") คือสิ่งที่เกิดขึ้นเมื่อคุณปิด xterm (หรือยกเลิกการเชื่อมต่อเทอร์มินัล) ในขณะที่โปรแกรมกำลังทำงาน
  • SIGTTINและSIGTTOUหยุดโปรแกรมชั่วคราวหากพยายามอ่านหรือเขียนลงในเทอร์มินัลขณะที่ทำงานในพื้นหลัง เพื่อที่SIGTTOUจะเกิดขึ้นฉันคิดว่าโปรแกรมต้องเขียนถึง/dev/ttyไม่ใช่แค่ stdout เริ่มต้นเท่านั้น

ถูกเรียกโดยข้อยกเว้นซีพียู

สิ่งเหล่านี้หมายถึงโปรแกรมของคุณพยายามทำสิ่งผิดปกติ

  • SIGILLหมายถึงคำสั่งโปรเซสเซอร์ที่ผิดกฎหมายหรือไม่รู้จัก สิ่งนี้อาจเกิดขึ้นหากคุณพยายามเข้าถึงพอร์ต I / O ของโปรเซสเซอร์โดยตรง
  • SIGFPEหมายความว่ามีข้อผิดพลาดทางคณิตศาสตร์ฮาร์ดแวร์ โปรแกรมส่วนใหญ่พยายามที่จะหารด้วยศูนย์
  • SIGSEGV หมายถึงโปรแกรมของคุณพยายามเข้าถึงพื้นที่หน่วยความจำที่ไม่ได้แมป
  • SIGBUSหมายถึงโปรแกรมเข้าถึงหน่วยความจำไม่ถูกต้องด้วยวิธีอื่น ฉันจะไม่ลงรายละเอียดสำหรับการสรุปนี้

ปฏิสัมพันธ์ของกระบวนการ

  • SIGPIPEเกิดขึ้นหากคุณพยายามที่จะเขียนไปยังท่อหลังจากที่ผู้อ่านของท่อปิดท้ายพวกเขา man 7 pipeดู
  • SIGCHLDเกิดขึ้นเมื่อกระบวนการลูกที่คุณสร้างออกจากหรือถูกระงับ (โดยSIGSTOPหรือคล้ายกัน)

มีประโยชน์สำหรับการส่งสัญญาณด้วยตนเอง

  • SIGABRTมักเกิดจากโปรแกรมที่เรียกใช้abort()ฟังก์ชันและทำให้การถ่ายโอนข้อมูลหลักโดยค่าเริ่มต้น จัดเรียงของ "ปุ่มตกใจ"
  • SIGALRMเกิดจากการalarm()เรียกของระบบซึ่งจะทำให้เคอร์เนลเพื่อส่งมอบSIGALRMให้กับโปรแกรมหลังจากจำนวนวินาทีที่ระบุ ดูและman 2 alarmman 2 sleep
  • SIGUSR1และSIGUSR2มีการใช้อย่างไรก็ตามโปรแกรมที่ชอบ อาจมีประโยชน์สำหรับการส่งสัญญาณระหว่างกระบวนการ

ส่งโดยผู้ดูแลระบบ

สัญญาณเหล่านี้มักจะถูกส่งจากพร้อมรับคำสั่งผ่านทางkillคำสั่งหรือfgหรือในกรณีของbgSIGCONT

  • SIGKILLและSIGSTOPเป็นสัญญาณที่ไม่ปิดกั้น ครั้งแรกมักจะยุติกระบวนการทันที ขั้นตอนที่สองจะระงับกระบวนการ
  • SIGCONT ดำเนินการต่อกระบวนการที่ถูกระงับ
  • SIGTERMเป็นรุ่น catchable SIGKILLของ

สัญญาณใดถูกส่งเมื่อใช้shutdownคำสั่ง?
Nathan Osman

ขึ้นอยู่กับสคริปต์การปิดระบบ โดยปกติแล้วจะถูกส่งไปก่อนตามด้วยความล่าช้าตามมาด้วยSIGTERM SIGKILLโดยหลักการแล้วสำหรับการปิดเครื่องอย่างหนักในทันทีเคอร์เนลไม่จำเป็นต้องส่งสัญญาณเลย มันสามารถหยุดกระบวนการทำงานได้
Jander
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.