การบังคับให้ฟังก์ชันสิ้นสุดโดยใช้ SIGALRM ใน C

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

ฉันลืมพูดถึง: ในฟังก์ชั่นที่ต้องถูกฆ่ามันจะรอใน scanf() และฟังก์ชั่นนั้นจะต้องตายแม้ว่า scanf() จะยังไม่กลับมาก็ตาม


person ThatQuestionGuy    schedule 11.02.2011    source แหล่งที่มา
comment
อาจเพิ่มแฟล็กในฟังก์ชันที่จะถูกฆ่าของคุณ และตรวจสอบว่าตั้งค่าแฟล็กแล้ว จากนั้นจึงกลับมา เห็นได้ชัดว่าเมื่อคุณหมดเวลาแล้วคุณจะต้องตั้งค่าสถานะนั้น   -  person Peyman    schedule 11.02.2011
comment
ทำการแก้ไข ฉันต้องหาทางยุติ scanf() ในฟังก์ชันเพื่อทำให้มันปิด   -  person ThatQuestionGuy    schedule 11.02.2011


คำตอบ (5)


แนวทางหนึ่งที่อาจคุ้มค่าแก่การพิจารณาคือการใช้ select เพื่อสำรวจความคิดเห็น stdin และดูว่ามีข้อมูลใดๆ หรือไม่ พร้อมแล้ว select ช่วยให้คุณรอตัวอธิบายไฟล์เป็นระยะเวลาหนึ่ง ควบคุมว่าเมื่อใดที่คุณจะถูกขัดจังหวะและทำอะไร และดูเหมือนว่าจะสมบูรณ์แบบที่นี่ คุณสามารถนั่งเป็นวงกลมเพื่อรอเป็นเวลาหนึ่งวินาที จากนั้นจะล้มเหลวอย่างสวยงามหากไม่มีข้อมูล ด้วยวิธีนี้ SIGALRM จะไม่จำเป็นต้องปิดฟังก์ชัน มันจะดูแลเรื่องนั้นทั้งหมดด้วยตัวเอง

person templatetypedef    schedule 11.02.2011

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

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

ฉันได้ทำบางอย่างที่ฉันเชื่อว่าคล้ายกัน ฉันมีแอปพลิเคชันแบบมัลติเธรดซึ่งมีโครงสร้างซึ่งมีข้อมูลเกี่ยวกับเธรดที่ฉันต้องการตรวจสอบ โครงสร้างมีตัวแปรสมาชิก "startTime" ฟังก์ชันการตรวจสอบของฉัน (SIGALARM) สามารถเข้าถึงรายการเธรดได้ เมื่อมอนิเตอร์ตื่นขึ้น มันจะสำรวจรายการ เปรียบเทียบเวลาปัจจุบันกับ startTime ของเธรดแต่ละรายการ และส่งข้อความไปยังฟังก์ชันหากเกินรันไทม์ที่อนุญาต

สิ่งนี้ช่วยได้หรือไม่?

person halm    schedule 11.02.2011
comment
ฟังก์ชั่นอยู่ในกระบวนการเดียวกัน ตรวจสอบการแก้ไขของฉันด้วย ฉันต้องแก้ไข scanf() ที่ทำงานอยู่ในฟังก์ชันที่ต้องถูกฆ่า นี่ไม่ใช่แอปพลิเคชันแบบมัลติเธรด - person ThatQuestionGuy; 11.02.2011

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

มีบางอย่างบรรทัดนี้:

volatile int worker_expired = 0;

void worker() {
   while (!worker_expired) {
      // ...
   }
}

void sig_alrm() {
   worker_expired = 1;
}
person sth    schedule 11.02.2011
comment
ฉันทำการแก้ไข OP ปัญหาคือฟังก์ชันนี้จำเป็นต้อง die wait บน scanf() และจำเป็นต้องตายในเวลาที่หมดเวลาพอดี - person ThatQuestionGuy; 11.02.2011

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

หากคุณใช้ฟังก์ชัน file-descriptor IO เช่น read คุณควรได้รับเอฟเฟกต์ที่ต้องการแล้ว

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

person R.. GitHub STOP HELPING ICE    schedule 11.02.2011

ดังนั้น ... ย้ำอีกครั้งเล็กน้อย: มันไม่ได้มีอะไรมากจนคุณต้องการฆ่าฟังก์ชันตามที่คุณต้องการให้ i/o ที่ค้างอยู่ยุติและฟังก์ชันออก

ฉันจะ:

  1. ใช้ select() เพื่อปลุกเป็นระยะๆ และตรวจสอบแฟล็กที่กำหนดโดยตัวจัดการสัญญาณ หากไม่ได้ตั้งค่าสถานะและไม่มีอินพุตที่ค้างอยู่ ให้วนซ้ำและโทร select() อีกครั้ง

  2. ฉันสงสัยว่าตัวจัดการ SIGALARM ของคุณกำลังทำมากกว่าการตรวจสอบตัวจับเวลานี้เพียงครั้งเดียว ดังนั้นการใช้ pselect() เพื่อตรวจสอบ i/o หรือ SIGALARM อาจไม่ใช่ตัวเลือกสำหรับคุณ ฉันสงสัยว่าคุณสามารถคว้าสัญญาณที่ผู้ใช้กำหนดและส่งผ่านใน pselect ได้หรือไม่ จากนั้นตัวจัดการสัญญาณเตือนของคุณจะส่งสัญญาณที่ผู้ใช้กำหนดนั้น

สำหรับตัวเลือกที่ 1 หาก SIGALARM ตื่นทุกวินาที คุณสามารถปรับเวลาที่ select() พักเครื่องให้อยู่ภายในเวลาแฝงของข้อผิดพลาดสูงสุดได้ กล่าวอีกนัยหนึ่งสมมติว่าการหมดเวลาเกิดขึ้นทันทีหลังจากการเรียกเพื่อเลือก () จากนั้นจะใช้เวลาจนกว่าการเลือก () จะกลับมาทำงานอีกครั้งเพื่อตรวจจับการตั้งค่าสถานะโดยตัวจัดการ SIGALARM ดังนั้นหาก select() เริ่มทำงาน 10 ครั้งต่อวินาที อาจต้องใช้เวลาถึง 1/10 วินาทีในการตรวจจับการตั้งค่าของแฟล็ก "ยอมแพ้" (กำหนดโดยตัวจัดการ SIGALARM)

person halm    schedule 07.04.2011