จะหลีกเลี่ยงการใช้ printf ในเครื่องจัดการสัญญาณได้อย่างไร?


87

เนื่องจากprintfไม่ได้รับการส่งกลับจึงไม่ควรใช้ในเครื่องจัดการสัญญาณอย่างปลอดภัย แต่ฉันเคยเห็นโค้ดตัวอย่างมากมายที่ใช้printfวิธีนี้

ดังนั้นคำถามของฉันคือเมื่อใดที่เราต้องหลีกเลี่ยงการใช้printfในเครื่องจัดการสัญญาณและมีการแนะนำให้เปลี่ยนหรือไม่


12
คำตอบที่เรียบง่ายและไม่ค่อยมีประโยชน์สำหรับคำถามในชื่อของคุณ: เห็นprintfสายนั้นในเครื่องส่งสัญญาณหรือไม่? ลบมัน.
Keith Thompson

6
สวัสดี Yu Hao! ฉันคิดว่าคุณจะพบลิงค์ที่น่าสนใจมากในการอ่าน "ใช้ฟังก์ชัน reentrant เพื่อการจัดการสัญญาณที่ปลอดภัยยิ่งขึ้น"หลังจากอ่านมานานแล้วฉันอยากจะแบ่งปันสิ่งประดิษฐ์ที่นี่กับคุณ หวังว่าคุณจะสนุก.
Grijesh Chauhan

1
jww

คำตอบ:


58

คุณสามารถใช้ตัวแปรแฟล็กตั้งค่าแฟล็กนั้นภายในตัวจัดการสัญญาณและใช้printf()ฟังก์ชันการเรียกแฟล็กใน main () หรือส่วนอื่น ๆ ของโปรแกรมในระหว่างการทำงานปกติ

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

สังเกตในตัวอย่างด้านล่างตัวจัดการสัญญาณ ding () ตั้งค่าแฟalarm_firedล็กเป็น 1 เนื่องจาก SIGALRM จับได้และในalarm_firedค่าฟังก์ชันหลักจะถูกตรวจสอบเพื่อเรียกใช้ printf ตามเงื่อนไขอย่างถูกต้อง

เอกสารอ้างอิง: Beginning Linux Programming, 4th Edition , ในหนังสือเล่มนี้มีการอธิบายโค้ดของคุณอย่างตรงประเด็น (สิ่งที่คุณต้องการ), บทที่ 11: กระบวนการและสัญญาณ, หน้า 484

นอกจากนี้คุณต้องใช้ความระมัดระวังเป็นพิเศษในการเขียนฟังก์ชันตัวจัดการเนื่องจากสามารถเรียกแบบอะซิงโครนัสได้ นั่นคือตัวจัดการอาจถูกเรียก ณ จุดใดก็ได้ในโปรแกรมโดยไม่สามารถคาดเดาได้ หากสัญญาณสองสัญญาณมาถึงในช่วงเวลาที่สั้นมากตัวจัดการหนึ่งสามารถทำงานภายในอีกเครื่องหนึ่งได้ และถือเป็นแนวทางปฏิบัติที่ดีกว่าในการประกาศvolatile sigatomic_tประเภทนี้จะเข้าถึงได้ตลอดเวลาโดยหลีกเลี่ยงความไม่แน่นอนเกี่ยวกับการขัดขวางการเข้าถึงตัวแปร (อ่าน: การเข้าถึงข้อมูลปรมาณูและการจัดการสัญญาณสำหรับการขยายรายละเอียด)

อ่านการกำหนดเครื่องจัดการสัญญาณ : เพื่อเรียนรู้วิธีการเขียนฟังก์ชันตัวจัดการสัญญาณที่สามารถสร้างขึ้นด้วยฟังก์ชันsignal()หรือ รายการฟังก์ชั่นที่ได้รับอนุญาตในหน้าคู่มือการเรียกใช้ฟังก์ชันนี้ภายในตัวจัดการสัญญาณนั้นปลอดภัยsigaction()


18
ถือเป็นการปฏิบัติที่ดีกว่าในการประกาศvolatile sigatomic_t alarm_fired;
Basile Starynkevitch


1
@GrijeshChauhan: ถ้าเราทำงานในรหัสของผลิตภัณฑ์เราจะไม่สามารถเรียกฟังก์ชันหยุดชั่วคราวได้การไหลจะอยู่ที่ใดก็ได้เมื่อมีสัญญาณเกิดขึ้นดังนั้นในกรณีนี้เราไม่รู้ว่าจะเก็บไว้ที่ไหน "if (alarm_fired) printf (" Ding! \ n ");" ในรหัส
pankaj kushwaha

@pankajkushwaha ใช่คุณถูกต้องมันเป็นทุกข์จากสภาพการแข่งขัน
Grijesh Chauhan

@GrijeshChauhan มีสองสิ่งที่ฉันไม่เข้าใจ 1. คุณรู้ได้อย่างไรว่าเมื่อใดควรตรวจสอบธง? ดังนั้นจะมีจุดตรวจสอบหลายจุดในรหัสเกือบทุกจุดที่จะพิมพ์ 2. จะมีเงื่อนไขการแข่งขันที่แน่นอนซึ่งสัญญาณอาจถูกเรียกก่อนการลงทะเบียนสัญญาณหรือสัญญาณอาจเกิดขึ้นหลังจากจุดตรวจสอบ ฉันคิดว่านี่จะช่วยการพิมพ์ในบางเงื่อนไขเท่านั้น แต่ไม่สามารถแก้ปัญหาได้อย่างสมบูรณ์
Darshan b

55

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

มาตรฐาน C คำนึงถึงสิ่งที่คุณสามารถทำได้ในเครื่องจัดการสัญญาณอย่างระมัดระวัง:

ISO / IEC 9899: 2011 §7.14.1.1 signalฟังก์ชัน

¶5หากสัญญาณเกิดขึ้นนอกเหนือจากผลของการเรียกใช้abortหรือraiseฟังก์ชันลักษณะการทำงานจะไม่ถูกกำหนดหากตัวจัดการสัญญาณอ้างถึงวัตถุใด ๆ ที่มีระยะเวลาการจัดเก็บแบบคงที่หรือเธรดที่ไม่ใช่วัตถุอะตอมที่ไม่มีการล็อคนอกเหนือจากการกำหนดค่า ไปยังวัตถุที่ประกาศเป็นvolatile sig_atomic_tหรือตัวจัดการสัญญาณเรียกใช้ฟังก์ชันใด ๆ ในไลบรารีมาตรฐานนอกเหนือจากabortฟังก์ชัน_Exitฟังก์ชัน quick_exitฟังก์ชันหรือsignalฟังก์ชันที่มีอาร์กิวเมนต์แรกเท่ากับหมายเลขสัญญาณที่ตรงกับสัญญาณที่ทำให้เกิดการเรียกใช้ ตัวจัดการ. นอกจากนี้หากการเรียกใช้signalฟังก์ชันดังกล่าวSIG_ERRส่งผลกลับค่าของerrnoจะไม่แน่นอน 252)

252)หากสัญญาณใด ๆ ถูกสร้างขึ้นโดยตัวจัดการสัญญาณแบบอะซิงโครนัสพฤติกรรมนั้นจะไม่ได้กำหนดไว้

POSIX มีความใจกว้างมากขึ้นเกี่ยวกับสิ่งที่คุณสามารถทำได้ในเครื่องจัดการสัญญาณ

แนวคิดสัญญาณในรุ่น POSIX 2008 กล่าวว่า:

หากกระบวนการเป็นแบบมัลติเธรดหรือหากกระบวนการเป็นเธรดเดียวและตัวจัดการสัญญาณถูกดำเนินการนอกเหนือจากผลลัพธ์ของ:

  • เรียกกระบวนการabort(), raise(), kill(), pthread_kill()หรือsigqueue()เพื่อสร้างสัญญาณที่ไม่ได้ถูกบล็อก

  • สัญญาณที่รอดำเนินการถูกยกเลิกการปิดกั้นและถูกส่งก่อนการโทรที่ยกเลิกการปิดกั้นจะกลับมา

ลักษณะการทำงานไม่ได้กำหนดไว้หากตัวจัดการสัญญาณอ้างถึงวัตถุใด ๆ นอกเหนือerrnoจากระยะเวลาการจัดเก็บแบบคงที่นอกเหนือจากการกำหนดค่าให้กับวัตถุที่ประกาศเป็นvolatile sig_atomic_tหรือหากตัวจัดการสัญญาณเรียกใช้ฟังก์ชันใด ๆ ที่กำหนดไว้ในมาตรฐานนี้นอกเหนือจากฟังก์ชันใดฟังก์ชันหนึ่งที่ระบุไว้ใน ตารางต่อไปนี้

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

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

การดำเนินการที่ได้รับมูลค่าerrnoและการดำเนินการที่กำหนดค่าให้errnoจะต้องปลอดภัยแบบ async-signal

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

อย่างไรก็ตามprintf()ตระกูลของฟังก์ชันนั้นขาดหายไปจากรายการนั้นและอาจไม่ถูกเรียกอย่างปลอดภัยจากเครื่องจัดการสัญญาณ

การอัปเดตPOSIX 2016ขยายรายการฟังก์ชันที่ปลอดภัยเพื่อรวมไว้โดยเฉพาะฟังก์ชันจำนวนมาก<string.h>ซึ่งเป็นส่วนเพิ่มเติมที่มีคุณค่าอย่างยิ่ง (หรือเป็นการกำกับดูแลที่น่าหงุดหงิดโดยเฉพาะ) รายการตอนนี้:

ด้วยเหตุนี้คุณอาจใช้งานwrite()โดยไม่ได้รับการสนับสนุนการจัดรูปแบบโดยprintf()et al หรือคุณจะตั้งค่าสถานะที่คุณทดสอบ (เป็นระยะ ๆ ) ในตำแหน่งที่เหมาะสมในโค้ดของคุณ เทคนิคนี้จะแสดงให้เห็นถึงความสามารถในคำตอบโดยGrijesh ชัวฮาน


ฟังก์ชันมาตรฐาน C และความปลอดภัยของสัญญาณ

chqrlie ถามคำถามที่น่าสนใจซึ่งฉันมีคำตอบไม่เกินบางส่วน:

ฟังก์ชันสตริงส่วนใหญ่มาจากฟังก์ชัน<string.h>คลาสอักขระ<ctype.h>และฟังก์ชันไลบรารีมาตรฐาน C อื่น ๆ อีกมากมายไม่อยู่ในรายการด้านบนได้อย่างไร การนำไปใช้งานจะต้องมีเจตนาชั่วร้ายที่จะทำให้strlen()ไม่ปลอดภัยในการโทรจากตัวจัดการสัญญาณ

หลายฟังก์ชั่นใน<string.h>มันเป็นเรื่องยากที่จะเห็นว่าทำไมพวกเขาไม่ได้ประกาศปลอดภัย async สัญญาณและฉันยอมรับstrlen()เป็นตัวอย่างที่สำคัญพร้อมกับstrchr(), strstr()ฯลฯ บนมืออื่น ๆ , ฟังก์ชั่นอื่น ๆ เช่นstrtok(), strcoll()และstrxfrm()ค่อนข้างซับซ้อนและไม่น่าจะปลอดภัยแบบ async-signal เนื่องจากstrtok()ยังคงสถานะระหว่างการโทรและตัวจัดการสัญญาณไม่สามารถบอกได้อย่างง่ายดายว่าบางส่วนของรหัสที่ใช้strtok()จะยุ่งเหยิงหรือไม่ strcoll()และstrxfrm()ฟังก์ชั่นการทำงานกับข้อมูลสถานที่สำคัญและสถานที่เกิดเหตุโหลดเกี่ยวข้องกับทุกประเภทของการตั้งค่าของรัฐ

ฟังก์ชั่น (มาโคร) จาก<ctype.h>ที่มีทั้งหมดสถานที่สำคัญและดังนั้นจึงสามารถใช้เป็นประเด็นเดียวกับและstrcoll()strxfrm()

ฉันพบว่ามันยากที่จะเห็นว่าเหตุใดฟังก์ชันทางคณิตศาสตร์จาก<math.h>จึงไม่ปลอดภัยแบบ async-signal เว้นแต่จะเป็นเพราะอาจได้รับผลกระทบจาก SIGFPE (ข้อยกเว้นจุดลอยตัว) แม้ว่าในช่วงเวลาเดียวที่ฉันเห็นว่าหนึ่งในวันนี้เป็นจำนวนเต็มการหารด้วยศูนย์. ความไม่แน่นอนที่คล้ายกันเกิดขึ้นจาก<complex.h>, และ<fenv.h><tgmath.h>

บางฟังก์ชันใน<stdlib.h>อาจได้รับการยกเว้น - abs()ตัวอย่างเช่น คนอื่น ๆ มีปัญหาโดยเฉพาะ: malloc()และครอบครัวเป็นตัวอย่างที่สำคัญ

สามารถทำการประเมินที่คล้ายกันสำหรับส่วนหัวอื่น ๆ ใน Standard C (2011) ที่ใช้ในสภาพแวดล้อม POSIX (มาตรฐาน C มีข้อ จำกัด มากดังนั้นจึงไม่มีความสนใจในการวิเคราะห์ในสภาพแวดล้อม Standard C ที่บริสุทธิ์) สิ่งที่ทำเครื่องหมาย 'ขึ้นอยู่กับสถานที่' ไม่ปลอดภัยเนื่องจากการจัดการโลแคลอาจต้องมีการจัดสรรหน่วยความจำเป็นต้น

  • <assert.h>- อาจไม่ปลอดภัย
  • <complex.h>- อาจปลอดภัย
  • <ctype.h> - ไม่ปลอดภัย
  • <errno.h> - ปลอดภัย
  • <fenv.h>- อาจไม่ปลอดภัย
  • <float.h> - ไม่มีฟังก์ชั่น
  • <inttypes.h> - ฟังก์ชั่นที่ไวต่อสถานที่ (ไม่ปลอดภัย)
  • <iso646.h> - ไม่มีฟังก์ชั่น
  • <limits.h> - ไม่มีฟังก์ชั่น
  • <locale.h> - ฟังก์ชั่นที่ไวต่อสถานที่ (ไม่ปลอดภัย)
  • <math.h>- อาจปลอดภัย
  • <setjmp.h> - ไม่ปลอดภัย
  • <signal.h> - อนุญาต
  • <stdalign.h> - ไม่มีฟังก์ชั่น
  • <stdarg.h> - ไม่มีฟังก์ชั่น
  • <stdatomic.h>- อาจจะปลอดภัยอาจไม่ปลอดภัย
  • <stdbool.h> - ไม่มีฟังก์ชั่น
  • <stddef.h> - ไม่มีฟังก์ชั่น
  • <stdint.h> - ไม่มีฟังก์ชั่น
  • <stdio.h> - ไม่ปลอดภัย
  • <stdlib.h> - ไม่ปลอดภัยทั้งหมด (บางคนได้รับอนุญาตคนอื่นไม่ได้)
  • <stdnoreturn.h> - ไม่มีฟังก์ชั่น
  • <string.h> - ไม่ปลอดภัยทั้งหมด
  • <tgmath.h>- อาจปลอดภัย
  • <threads.h>- อาจไม่ปลอดภัย
  • <time.h>- ขึ้นอยู่กับสถานที่ (แต่time()ได้รับอนุญาตอย่างชัดเจน)
  • <uchar.h> - ขึ้นอยู่กับสถานที่
  • <wchar.h> - ขึ้นอยู่กับสถานที่
  • <wctype.h> - ขึ้นอยู่กับสถานที่

การวิเคราะห์ส่วนหัว POSIX น่าจะ ... ยากกว่าเนื่องจากมีจำนวนมากและบางฟังก์ชันอาจปลอดภัย แต่หลายฟังก์ชันจะไม่เป็นเช่นนั้น ... แต่ก็ง่ายกว่าด้วยเพราะ POSIX บอกว่าฟังก์ชันใดปลอดภัยแบบไม่ซิงค์สัญญาณ (มีไม่มากนัก) โปรดทราบว่าส่วนหัวเช่น<pthread.h>มีฟังก์ชันปลอดภัยสามฟังก์ชันและฟังก์ชันที่ไม่ปลอดภัยมากมาย

หมายเหตุ:การประเมินฟังก์ชันและส่วนหัว C เกือบทั้งหมดในสภาพแวดล้อม POSIX เป็นการคาดเดาแบบกึ่งการศึกษา ไม่มีความรู้สึกว่าเป็นคำกล่าวที่ชัดเจนจากร่างมาตรฐาน


ฟังก์ชันสตริงส่วนใหญ่มาจากฟังก์ชัน<string.h>คลาสอักขระ<ctype.h>และฟังก์ชันไลบรารีมาตรฐาน C อื่น ๆ อีกมากมายไม่อยู่ในรายการด้านบนได้อย่างไร การนำไปใช้งานจะต้องมีเจตนาชั่วร้ายที่จะทำให้strlen()ไม่ปลอดภัยในการโทรจากตัวจัดการสัญญาณ
chqrlie

@chqrlie: คำถามที่น่าสนใจ - ดูการอัปเดต (ไม่มีวิธีใดที่จะเข้ากับความคิดเห็นได้อย่างสมเหตุสมผล)
Jonathan Leffler

ขอบคุณสำหรับการวิเคราะห์เชิงลึก เกี่ยวกับ<ctype.h>สิ่งต่างๆนั้นเป็นภาษาเฉพาะและอาจทำให้เกิดปัญหาได้หากสัญญาณขัดจังหวะฟังก์ชันการตั้งค่าโลแคล แต่เมื่อโหลดโลแคลแล้วการใช้ควรปลอดภัย ฉันเดาว่าในสถานการณ์ที่ซับซ้อนบางอย่างการโหลดข้อมูลโลแคลสามารถทำได้ทีละน้อยดังนั้นจึงทำให้ฟังก์ชัน<ctype.h>ไม่ปลอดภัย ข้อสรุปยังคงอยู่: หากมีข้อสงสัยให้งดเว้น
chqrlie

@chqrlie: ผมยอมรับว่าคุณธรรมของเรื่องที่ควรจะเป็นเมื่อสงสัยงดออกเสียง นั่นเป็นบทสรุปที่ดี
Jonathan Leffler

13

จะหลีกเลี่ยงการใช้printfในเครื่องจัดการสัญญาณได้อย่างไร?

  1. หลีกเลี่ยงเสมอจะพูดว่า: อย่าใช้printf()ในเครื่องจัดการสัญญาณ

  2. อย่างน้อยในระบบที่สอดคล้องกับ POSIX คุณสามารถใช้write(STDOUT_FILENO, ...)แทนprintf(). การจัดรูปแบบอาจไม่ใช่เรื่องง่ายอย่างไรก็ตามพิมพ์ int จากตัวจัดการสัญญาณโดยใช้ฟังก์ชันเขียนหรือไม่ปลอดภัย


1
Alk Always avoid it.หมายถึง? หลีกเลี่ยงprintf()?
Grijesh Chauhan

2
@GrijeshChauhan: ใช่เนื่องจาก OP กำลังถามว่าเมื่อใดควรหลีกเลี่ยงการใช้printf()ในตัวจัดการสัญญาณ
alk

Alk +1 สำหรับ2จุดตรวจสอบ OP ขอวิธีหลีกเลี่ยงการใช้printf()ในตัวจัดการสัญญาณ?
Grijesh Chauhan

7

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

รหัสที่มาเป็นบน GitHub มันทำงานโดยการโอเวอร์โหลดsignal/sigactionจากนั้นจี้PLTรายการของฟังก์ชันที่ไม่ปลอดภัยชั่วคราว สิ่งนี้ทำให้การเรียกใช้ฟังก์ชันที่ไม่ปลอดภัยถูกเปลี่ยนเส้นทางไปยัง wrapper



1

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

ถ้าคุณดูแลซึ่งส่งสัญญาณว่ามันเป็นแล้วไบต์ลงท่อสามารถเป็นตัวเลขสัญญาณ


1

ใช้ async-signal-safe ของคุณเองsnprintf("%dและใช้งานwrite

มันไม่แย่อย่างที่คิดวิธีการแปลง int เป็น string ใน C? มีการใช้งานหลายอย่าง

เนื่องจากมีข้อมูลที่น่าสนใจเพียงสองประเภทที่ผู้จัดการสัญญาณสามารถเข้าถึงได้:

  • sig_atomic_t ลูกโลก
  • int อาร์กิวเมนต์สัญญาณ

โดยพื้นฐานแล้วจะครอบคลุมกรณีการใช้งานที่น่าสนใจทั้งหมด

ความจริงที่ว่าstrcpyสัญญาณยังปลอดภัยทำให้สิ่งต่างๆดียิ่งขึ้น

โปรแกรม POSIX ด้านล่างจะพิมพ์เป็นจำนวนครั้งที่ได้รับ SIGINT จนถึงตอนนี้ซึ่งคุณสามารถทริกเกอร์ได้Ctrl + Cและ ID สัญญาณ

คุณสามารถออกจากโปรแกรมด้วยCtrl + \(SIGQUIT)

main.c:

รวบรวมและเรียกใช้:

หลังจากกด Ctrl + C สิบห้าครั้งเทอร์มินัลจะแสดง:

ซึ่งเป็นจำนวนสัญญาณสำหรับ2SIGINT

ทดสอบบน Ubuntu 18.04 GitHub อัปสตรี


0

นอกจากนี้คุณยังสามารถใช้write()โดยตรงซึ่งเป็นฟังก์ชันปลอดภัยแบบไม่ซิงค์สัญญาณ


-1

คุณสามารถใช้ printf ในตัวจัดการสัญญาณได้หากคุณใช้ไลบรารี pthread unix / posix ระบุว่า printf เป็น atomic สำหรับเธรด cf Dave Butenhof ตอบกลับที่นี่: https://groups.google.com/forum/#!topic/comp.programming.threads/1-bU71nYgqw โปรดทราบว่าเพื่อให้ได้ภาพที่ชัดเจนขึ้น ของเอาต์พุต printf คุณควรเรียกใช้แอปพลิเคชันของคุณในคอนโซล (บน linux ใช้ ctl + alt + f1 เพื่อเริ่มคอนโซล 1) แทนที่จะเป็น pseudo-tty ที่สร้างโดย GUI


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