ฉันกำลังจะเพิ่มตัวจัดการสัญญาณพิเศษลงในแอพที่เรามีที่นี่และฉันสังเกตเห็นว่าผู้เขียนเคยsigaction()
ตั้งค่าตัวจัดการสัญญาณอื่น ๆ signal()
ฉันกำลังจะไปใช้ ในการติดตามการประชุมฉันควรใช้sigaction()
แต่ถ้าฉันเขียนตั้งแต่ต้นฉันควรเลือกแบบไหนดี?
ฉันกำลังจะเพิ่มตัวจัดการสัญญาณพิเศษลงในแอพที่เรามีที่นี่และฉันสังเกตเห็นว่าผู้เขียนเคยsigaction()
ตั้งค่าตัวจัดการสัญญาณอื่น ๆ signal()
ฉันกำลังจะไปใช้ ในการติดตามการประชุมฉันควรใช้sigaction()
แต่ถ้าฉันเขียนตั้งแต่ต้นฉันควรเลือกแบบไหนดี?
คำตอบ:
ใช้sigaction()
นอกเสียจากคุณจะมีเหตุผลที่น่าสนใจมาก ๆ
signal()
อินเตอร์เฟซที่มีสมัยโบราณ (และด้วยเหตุนี้ว่าง) ในความโปรดปรานของมันและมันถูกกำหนดไว้ในมาตรฐาน C อย่างไรก็ตามมันมีลักษณะที่ไม่พึงประสงค์จำนวนมากที่sigaction()
หลีกเลี่ยง - เว้นแต่คุณจะใช้การตั้งค่าสถานะเพื่อเพิ่มความชัดเจนsigaction()
เพื่อจำลองsignal()
พฤติกรรมเก่าโดยสุจริต
signal()
ฟังก์ชั่นไม่ได้ (จำเป็น) ปิดกั้นสัญญาณอื่น ๆ จากที่เดินทางมาถึงในขณะที่ดำเนินการในปัจจุบันมีการดำเนินการ; sigaction()
สามารถบล็อกสัญญาณอื่น ๆ จนกว่าตัวจัดการปัจจุบันจะกลับมาsignal()
ฟังก์ชั่น (ปกติ) รีเซ็ตการกระทำสัญญาณกลับไปSIG_DFL
(เริ่มต้น) เกือบสัญญาณทั้งหมด ซึ่งหมายความว่าsignal()
ตัวจัดการต้องติดตั้งตัวเองเป็นการดำเนินการครั้งแรก นอกจากนี้ยังเปิดหน้าต่างช่องโหว่ระหว่างเวลาที่ตรวจพบสัญญาณและตัวจัดการถูกติดตั้งใหม่ในระหว่างที่หากมีสัญญาณอินสแตนซ์ที่สองมาถึงพฤติกรรมเริ่มต้น (มักจะยุติsignal()
แตกต่างระหว่างระบบ - และมาตรฐานอนุญาตให้มีการเปลี่ยนแปลงเหล่านั้นเหล่านี้เป็นเหตุผลที่ดีโดยทั่วไปสำหรับใช้แทนsigaction()
signal()
อย่างไรก็ตามอินเทอร์เฟซของsigaction()
ไม่น่าเบื่อมากขึ้น
แล้วแต่จำนวนใดของทั้งสองที่คุณใช้ไม่ถูกล่อลวงโดยการเชื่อมต่อสัญญาณทางเลือกเช่น
sighold()
,
sigignore()
,
และsigpause()
sigrelse()
พวกเขาเป็นทางเลือกในนามsigaction()
แต่พวกเขาเป็นเพียงมาตรฐานแทบจะไม่และมีอยู่ใน POSIX สำหรับความเข้ากันได้ย้อนหลังมากกว่าสำหรับการใช้งานอย่างจริงจัง โปรดทราบว่ามาตรฐาน POSIX บอกว่าพฤติกรรมของพวกเขาในโปรแกรมแบบมัลติเธรดไม่ได้ถูกกำหนด
โปรแกรมและสัญญาณแบบมัลติเธรดเป็นเรื่องราวที่ซับซ้อนอื่น ๆ ทั้งหมด AFAIK ทั้งคู่signal()
และsigaction()
ใช้ได้ในแอปพลิเคชันแบบมัลติเธรด
หน้าลินุกซ์สำหรับ
signal()
พูดว่า:
ผลกระทบของ
signal()
ในกระบวนการแบบมัลติเธรดไม่ได้ระบุไว้ดังนั้นฉันคิดว่า
sigaction()
เป็นสิ่งเดียวที่สามารถใช้ได้อย่างปลอดภัยในกระบวนการแบบมัลติเธรด
นั่นดูน่าสนใจ. หน้าคู่มือ Linux มีข้อ จำกัด มากกว่า POSIX ในกรณีนี้ POSIX ระบุสำหรับsignal()
:
หากกระบวนการเป็นแบบมัลติเธรดหรือหากกระบวนการเป็นแบบเธรดเดี่ยวและตัวจัดการสัญญาณถูกดำเนินการอื่นที่ไม่ใช่ผลลัพธ์ของ:
- เรียกกระบวนการ
abort()
,raise()
,kill()
,pthread_kill()
หรือsigqueue()
เพื่อสร้างสัญญาณที่ไม่ได้ถูกบล็อก- สัญญาณที่รอดำเนินการถูกยกเลิกการปิดกั้นและถูกส่งก่อนการโทรที่ยกเลิกการปิดกั้นจะส่งคืน
พฤติกรรมจะไม่ได้กำหนดถ้าตัวจัดการสัญญาณอ้างถึงวัตถุใด ๆ นอกเหนือจากที่
errno
มีระยะเวลาการจัดเก็บแบบคงที่อื่นโดยการกำหนดค่าให้กับวัตถุที่ประกาศว่าเป็นvolatile sig_atomic_t
หรือถ้าตัวจัดการสัญญาณเรียกฟังก์ชั่นใด ๆ ที่กำหนดไว้ในมาตรฐานนี้แนวคิดการซือขาย
ดังนั้น POSIX จะระบุพฤติกรรมของsignal()
แอปพลิเคชันแบบมัลติเธรดอย่างชัดเจน
อย่างไรก็ตามsigaction()
เป็นที่ต้องการในทุกกรณี - และควรใช้มัลติเธรดแบบพกพาsigaction()
นอกเสียจากว่าจะมีเหตุผลมากมายที่ทำให้มันไม่สามารถทำได้ (เช่น "ใช้ฟังก์ชั่นที่กำหนดโดยมาตรฐาน C" เท่านั้น - และใช่รหัส C11 -threaded) ซึ่งเป็นสิ่งที่ย่อหน้าเปิดของคำตอบนี้ยังกล่าว
SA_RESETHAND
เช่นSA_NODEFER
กัน
sigaction()
คุณจำเป็นต้องใช้ข้อกำหนดมาตรฐาน C เป็นsignal()
หลัก อย่างไรก็ตามนั่นทำให้คุณมีตัวเลือกที่แย่มากสำหรับสิ่งที่คุณสามารถทำได้ คุณสามารถ: แก้ไข (ขอบเขตไฟล์) ตัวแปรประเภทvolatile sig_atomic_t
; เรียกฟังก์ชั่นหนึ่ง 'ออกอย่างรวดเร็ว' ( _Exit()
, quick_exit()
) หรือabort()
; โทรsignal()
ด้วยหมายเลขสัญญาณปัจจุบันเป็นอาร์กิวเมนต์สัญญาณ; กลับ. และนั่นคือมัน สิ่งอื่นใดไม่รับประกันว่าจะสามารถพกพาได้ มันเข้มงวดมากที่คนส่วนใหญ่ไม่สนใจกฎเหล่านั้น - แต่ผลลัพธ์ที่ได้คือหลบ
sigaction()
การสาธิตที่ยอดเยี่ยมจาก GCC ตัวเอง: gnu.org/software/libc/manual/html_node/… ; และยอดเยี่ยมsignal()
การสาธิตจาก GCC ตัวเอง: gnu.org/software/libc/manual/html_node/... โปรดสังเกตว่าในการsignal
สาธิตพวกเขาหลีกเลี่ยงการเปลี่ยนตัวจัดการจากการละเว้น ( SIG_IGN
) ถ้านั่นคือสิ่งที่เคยตั้งค่าไว้โดยเจตนา
สำหรับฉันบรรทัดด้านล่างนี้เพียงพอที่จะตัดสินใจ:
ฟังก์ชั่น sigaction () มอบกลไกที่ครอบคลุมและน่าเชื่อถือมากขึ้นสำหรับการควบคุมสัญญาณ แอปพลิเคชันใหม่ควรใช้ sigaction () มากกว่าสัญญาณ ()
http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html#tag_03_690_07
ไม่ว่าคุณจะเริ่มต้นจากศูนย์หรือดัดแปลงโปรแกรมเก่า sigaction ควรเป็นตัวเลือกที่เหมาะสม
พวกมันเป็นอินเตอร์เฟสที่แตกต่างกันสำหรับระบบอำนวยความสะดวกสัญญาณ เราควรเลือกใช้ sigaction เพื่อส่งสัญญาณถ้าเป็นไปได้เนื่องจากสัญญาณ () มีพฤติกรรมการใช้งานที่กำหนดไว้ (มักจะมีแนวโน้มการแข่งขัน) และมีพฤติกรรมแตกต่างกันไปใน Windows, OS X, Linux และระบบ UNIX อื่น ๆ
ดูหมายเหตุความปลอดภัยนี้เพื่อดูรายละเอียด
สัญญาณ () คือมาตรฐาน C, sigaction () ไม่ใช่
หากคุณสามารถใช้ (นั่นคือคุณอยู่ในระบบ POSIX) จากนั้นใช้ sigaction (); มันไม่ได้ระบุว่าสัญญาณ () รีเซ็ตตัวจัดการหมายถึงการพกพาคุณจะต้องเรียกสัญญาณ () อีกครั้งภายในตัวจัดการ สิ่งที่แย่กว่านั้นคือมีการแข่งขัน: หากคุณได้รับสัญญาณสองสัญญาณติดต่อกันอย่างรวดเร็วและสัญญาณที่สองถูกส่งก่อนที่คุณจะติดตั้งตัวจัดการใหม่คุณจะมีการดำเนินการเริ่มต้นซึ่งอาจเป็นไปได้ที่จะฆ่ากระบวนการของคุณ ในทางกลับกัน sigaction ()นั้นรับประกันว่าจะใช้ซีแมนติกสัญญาณที่“ น่าเชื่อถือ” คุณไม่จำเป็นต้องติดตั้งตัวจัดการใหม่เพราะจะไม่ถูกรีเซ็ต ด้วย SA_RESTART คุณสามารถรับสายของระบบเพื่อเริ่มต้นใหม่โดยอัตโนมัติ (ดังนั้นคุณไม่จำเป็นต้องตรวจสอบ EINTR ด้วยตนเอง) sigaction () มีตัวเลือกเพิ่มเติมและเชื่อถือได้ดังนั้นจึงสนับสนุนการใช้งาน
Psst ... อย่าบอกใครเลยฉันบอกคุณแล้ว แต่ POSIX มีฟังก์ชัน bsd_signal () ซึ่งทำหน้าที่เหมือนสัญญาณ () แต่ให้ความหมาย BSD ซึ่งหมายความว่าเชื่อถือได้ การใช้งานหลักสำหรับการย้ายแอปพลิเคชันเก่าที่สันนิษฐานว่าเป็นสัญญาณที่เชื่อถือได้และ POSIX ไม่แนะนำให้ใช้
bsd_signal()
- การใช้งาน POSIX บางอย่างอาจมีฟังก์ชั่น แต่ POSIX เองไม่มีฟังก์ชั่นดังกล่าว (ดูPOSIX )
sigaction()
เป็นสิ่งที่ดีและกำหนดไว้อย่างดี แต่เป็นฟังก์ชั่นลีนุกซ์ดังนั้นจึงสามารถใช้งานได้กับ Linux เท่านั้น signal()
ไม่ดีและมีคุณภาพต่ำ แต่เป็นฟังก์ชั่นมาตรฐานแบบ C ดังนั้นมันจึงทำงานได้ทุกอย่าง
man 2 signal
(ดูออนไลน์ได้ที่นี่ ) สถานะ:
พฤติกรรมของสัญญาณ () จะแตกต่างกันไปตามรุ่นของ UNIX และมีความหลากหลายในอดีตในเวอร์ชันต่าง ๆ ของ Linux หลีกเลี่ยงการใช้: ใช้
sigaction(2)
แทน ดูการพกพาด้านล่างความสามารถในการพกพาการใช้งานสัญญาณแบบพกพาเพียงอย่างเดียวคือการตั้งค่าการจัดการสัญญาณเป็น SIG_DFL หรือ SIG_IGN ซีแมนทิกส์เมื่อใช้สัญญาณ () เพื่อสร้างตัวจัดการสัญญาณแตกต่างกันไปตามระบบ (และ POSIX.1 อนุญาตการเปลี่ยนแปลงนี้อย่างชัดเจน); ห้ามใช้เพื่อจุดประสงค์นี้
ในคำอื่น ๆ : signal()
ไม่ได้ใช้ ใช้sigaction()
แทน!
หมายเหตุความเข้ากันได้: ดังที่กล่าวไว้ข้างต้นสำหรับ
signal
ฟังก์ชั่นนี้ควรหลีกเลี่ยงเมื่อเป็นไปได้sigaction
เป็นวิธีที่ต้องการ
ที่มา: https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
ดังนั้นหากทั้ง Linux และ GCC บอกว่าจะไม่ใช้signal()
แต่จะใช้sigaction()
แทนนั่นจะทำให้เกิดคำถาม: เราจะใช้sigaction()
สิ่งที่สับสนนี้ได้อย่างไร!
อ่านsignal()
ตัวอย่างที่ยอดเยี่ยมของ GCC ได้ที่นี่: https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
และsigaction()
ตัวอย่างที่ยอดเยี่ยมของพวกเขาที่นี่: https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html
หลังจากอ่านหน้าเหล่านั้นฉันมาด้วยเทคนิคต่อไปนี้สำหรับsigaction()
:
sigaction()
เนื่องจากเป็นวิธีที่เหมาะสมในการแนบตัวจัดการสัญญาณดังที่อธิบายไว้ข้างต้น:#include <errno.h> // errno
#include <signal.h> // sigaction()
#include <stdio.h> // printf()
#include <string.h> // strerror()
#define LOG_LOCATION __FILE__, __LINE__, __func__ // Format: const char *, unsigned int, const char *
#define LOG_FORMAT_STR "file: %s, line: %u, func: %s: "
/// @brief Callback function to handle termination signals, such as Ctrl + C
/// @param[in] signal Signal number of the signal being handled by this callback function
/// @return None
static void termination_handler(const int signal)
{
switch (signal)
{
case SIGINT:
printf("\nSIGINT (%i) (Ctrl + C) signal caught.\n", signal);
break;
case SIGTERM:
printf("\nSIGTERM (%i) (default `kill` or `killall`) signal caught.\n", signal);
break;
case SIGHUP:
printf("\nSIGHUP (%i) (\"hang-up\") signal caught.\n", signal);
break;
default:
printf("\nUnk signal (%i) caught.\n", signal);
break;
}
// DO PROGRAM CLEANUP HERE, such as freeing memory, closing files, etc.
exit(signal);
}
/// @brief Set a new signal handler action for a given signal
/// @details Only update the signals with our custom handler if they are NOT set to "signal ignore" (`SIG_IGN`),
/// which means they are currently intentionally ignored. GCC recommends this "because non-job-control
/// shells often ignore certain signals when starting children, and it is important for children
/// to respect this." See
/// https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
/// and https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html.
/// Note that termination signals can be found here:
/// https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html#Termination-Signals
/// @param[in] signal Signal to set to this action
/// @param[in] action Pointer to sigaction struct, including the callback function inside it, to attach to this signal
/// @return None
static inline void set_sigaction(int signal, const struct sigaction *action)
{
struct sigaction old_action;
// check current signal handler action to see if it's set to SIGNAL IGNORE
sigaction(signal, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
{
// set new signal handler action to what we want
int ret_code = sigaction(signal, action, NULL);
if (ret_code == -1)
{
printf(LOG_FORMAT_STR "sigaction failed when setting signal to %i;\n"
" errno = %i: %s\n", LOG_LOCATION, signal, errno, strerror(errno));
}
}
}
int main(int argc, char *argv[])
{
//...
// Register callbacks to handle kill signals; prefer the Linux function `sigaction()` over the C function
// `signal()`: "It is better to use sigaction if it is available since the results are much more reliable."
// Source: https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
// and /programming/231912/what-is-the-difference-between-sigaction-and-signal/232711#232711.
// See here for official gcc `sigaction()` demo, which this code is modeled after:
// https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html
// Set up the structure to specify the new action, per GCC's demo.
struct sigaction new_action;
new_action.sa_handler = termination_handler; // set callback function
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
// SIGINT: ie: Ctrl + C kill signal
set_sigaction(SIGINT, &new_action);
// SIGTERM: termination signal--the default generated by `kill` and `killall`
set_sigaction(SIGTERM, &new_action);
// SIGHUP: "hang-up" signal due to lost connection
set_sigaction(SIGHUP, &new_action);
//...
}
signal()
ถึงแม้ว่ามันจะไม่ใช่วิธีที่ดีในการติดตั้งตัวจัดการสัญญาณตามที่อธิบายไว้ข้างต้น แต่ก็ยังดีที่จะรู้วิธีใช้มันนี่คือการคัดลอกรหัสการสาธิตของ GCC เพราะมันใกล้เคียงกับที่ควรจะได้รับ:
#include <signal.h>
void
termination_handler (int signum)
{
struct temp_file *p;
for (p = temp_file_list; p; p = p->next)
unlink (p->name);
}
int
main (void)
{
…
if (signal (SIGINT, termination_handler) == SIG_IGN)
signal (SIGINT, SIG_IGN);
if (signal (SIGHUP, termination_handler) == SIG_IGN)
signal (SIGHUP, SIG_IGN);
if (signal (SIGTERM, termination_handler) == SIG_IGN)
signal (SIGTERM, SIG_IGN);
…
}
signal()
ตัวอย่างการใช้งานGCC อย่างเป็นทางการ: https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handlingsigaction()
ตัวอย่างการใช้GCC อย่างเป็นทางการ: https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.htmlsigemptyset()
และsigfillset()
; ฉันยังคงไม่เข้าใจสิ่งเหล่านี้อย่างแน่นอน แต่รู้ว่าพวกเขามีความสำคัญ: https://www.gnu.org/software/libc/manual/html_node/Signal-Sets.htmlจากsignal(3)
หน้าคน:
รายละเอียด
This signal() facility is a simplified interface to the more general sigaction(2) facility.
ทั้งสองใช้สิ่งอำนวยความสะดวกพื้นฐานเดียวกัน คุณน่าจะไม่จัดการกับการตอบสนองของสัญญาณเดียวที่มีทั้งคู่ แต่การผสมพวกมันไม่ควรทำให้อะไรแตก ...
ฉันขอแนะนำให้ใช้ sigaction () over signal () และต้องการเพิ่มอีกหนึ่งจุด sigaction () ให้ตัวเลือกเพิ่มเติมแก่คุณเช่น pid ของกระบวนการที่เสียชีวิต (เป็นไปได้โดยใช้ siginfo_t struct)
ฉันจะใช้สัญญาณ () เนื่องจากเป็นแบบพกพามากกว่าในทางทฤษฎีอย่างน้อย ฉันจะลงคะแนนผู้แสดงความคิดเห็นที่สามารถเกิดขึ้นกับระบบที่ทันสมัยที่ไม่มีเลเยอร์ความเข้ากันได้ POSIX และรองรับสัญญาณ ()
การอ้างอิงจากเอกสาร GLIBC :
เป็นไปได้ที่จะใช้ทั้งฟังก์ชั่นสัญญาณและ sigaction ภายในโปรแกรมเดียว แต่คุณต้องระวังเพราะมันสามารถโต้ตอบได้ในรูปแบบที่แปลก ๆ
ฟังก์ชั่น sigaction ระบุข้อมูลมากกว่าฟังก์ชั่นสัญญาณดังนั้นค่าส่งคืนจากสัญญาณไม่สามารถแสดงช่วงเต็มของความเป็นไปได้ของ sigaction ดังนั้นหากคุณใช้สัญญาณเพื่อบันทึกและสร้างการดำเนินการใหม่ในภายหลังคุณอาจไม่สามารถสร้างตัวจัดการที่สร้างขึ้นใหม่ด้วย sigaction อย่างถูกต้อง
เพื่อหลีกเลี่ยงปัญหาที่เป็นผลให้ใช้ sigaction เพื่อบันทึกและคืนค่าตัวจัดการหากโปรแกรมของคุณใช้ sigaction เลย เนื่องจาก sigaction นั้นเป็นแบบทั่วไปมากขึ้นจึงสามารถบันทึกและสร้างการดำเนินการใด ๆ อีกครั้งได้อย่างถูกต้องไม่ว่าจะสร้างด้วยสัญญาณหรือ sigaction เป็นครั้งแรกก็ตาม
ในบางระบบหากคุณสร้างการกระทำด้วยสัญญาณแล้วตรวจสอบด้วย sigaction ที่อยู่ของตัวจัดการที่คุณได้รับอาจไม่เหมือนกับสิ่งที่คุณระบุด้วยสัญญาณ อาจไม่เหมาะสำหรับใช้เป็นอาร์กิวเมนต์สำหรับการกระทำพร้อมสัญญาณ แต่คุณสามารถใช้มันเป็นอาร์กิวเมนต์ในการ sigaction ปัญหานี้ไม่เคยเกิดขึ้นในระบบ GNU
ดังนั้นคุณควรใช้กลไกหนึ่งหรือกลไกใด ๆ อย่างสม่ำเสมอภายในโปรแกรมเดียว
หมายเหตุการพกพา: ฟังก์ชั่นสัญญาณพื้นฐานคือคุณสมบัติของ ISO C ในขณะที่ sigaction เป็นส่วนหนึ่งของมาตรฐาน POSIX.1 หากคุณกังวลเกี่ยวกับการพกพาไปยังระบบที่ไม่ใช่ POSIX คุณควรใช้ฟังก์ชั่นสัญญาณแทน
ลิขสิทธิ์ (C) 1996-2008 มูลนิธิซอฟต์แวร์เสรี, Inc.
ได้รับอนุญาตให้คัดลอกแจกจ่ายและ / หรือแก้ไขเอกสารนี้ภายใต้เงื่อนไขของสัญญาอนุญาตเอกสารเสรีของ GNU, รุ่น 1.2 หรือรุ่นใด ๆ ที่เผยแพร่ในภายหลังโดยมูลนิธิซอฟต์แวร์เสรี ที่ไม่มีส่วนคงที่ไม่มีตำราปกหน้าและไม่มีตำราปกหลัง สำเนาใบอนุญาตจะรวมอยู่ในส่วนที่ชื่อว่า "GNU Free Documentation License"
สัญญาณที่ควบคุมกระบวนการอาจถูกส่งไปยังหนึ่งในเธรดใด ๆ ที่ไม่มีสัญญาณในขณะนี้ หากมีมากกว่าหนึ่งเธรดที่มีสัญญาณถูกปลดบล็อกเคอร์เนลจะเลือกเธรดที่ต้องการส่งสัญญาณ
และผมจะบอกว่าเรื่องนี้ "ปัญหา" ที่มีอยู่สำหรับสัญญาณ (2)และsigaction (2) ดังนั้นระวังด้วยสัญญาณและ pthreads
... และสัญญาณ (2)ดูเหมือนจะเรียกsigaction (2)ข้างล่างใน Linux ด้วย glibc
signal
เป็นจริงของพฤติกรรม Unix System V POSIX ช่วยให้ทั้งพฤติกรรมนี้หรือพฤติกรรม BSD มากมีสติมากขึ้นsigaction
แต่เนื่องจากคุณไม่สามารถตรวจสอบที่หนึ่งที่คุณจะได้รับก็ยังคงดีที่สุดในการใช้งาน