ความแตกต่างระหว่าง sigaction และสัญญาณคืออะไร?


143

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

คำตอบ:


167

ใช้sigaction()นอกเสียจากคุณจะมีเหตุผลที่น่าสนใจมาก ๆ

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

  1. signal()ฟังก์ชั่นไม่ได้ (จำเป็น) ปิดกั้นสัญญาณอื่น ๆ จากที่เดินทางมาถึงในขณะที่ดำเนินการในปัจจุบันมีการดำเนินการ; sigaction()สามารถบล็อกสัญญาณอื่น ๆ จนกว่าตัวจัดการปัจจุบันจะกลับมา
  2. signal()ฟังก์ชั่น (ปกติ) รีเซ็ตการกระทำสัญญาณกลับไปSIG_DFL(เริ่มต้น) เกือบสัญญาณทั้งหมด ซึ่งหมายความว่าsignal()ตัวจัดการต้องติดตั้งตัวเองเป็นการดำเนินการครั้งแรก นอกจากนี้ยังเปิดหน้าต่างช่องโหว่ระหว่างเวลาที่ตรวจพบสัญญาณและตัวจัดการถูกติดตั้งใหม่ในระหว่างที่หากมีสัญญาณอินสแตนซ์ที่สองมาถึงพฤติกรรมเริ่มต้น (มักจะยุติ
  3. พฤติกรรมที่แน่นอนของความ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) ซึ่งเป็นสิ่งที่ย่อหน้าเปิดของคำตอบนี้ยังกล่าว


12
คำอธิบายนี้signalเป็นจริงของพฤติกรรม Unix System V POSIX ช่วยให้ทั้งพฤติกรรมนี้หรือพฤติกรรม BSD มากมีสติมากขึ้น sigactionแต่เนื่องจากคุณไม่สามารถตรวจสอบที่หนึ่งที่คุณจะได้รับก็ยังคงดีที่สุดในการใช้งาน
. GitHub หยุดช่วยน้ำแข็ง

1
ยกเว้นว่าคุณใช้ค่าสถานะที่เพิ่มเข้ามาอย่างชัดเจนเพื่อ sigaction () เพื่ออนุญาตให้จำลองพฤติกรรมสัญญาณเก่า () อย่างซื่อสัตย์ ธงเหล่านั้นจะเป็นแบบใด
ChristianCuevas

@AlexFritz: เป็นหลักSA_RESETHANDเช่นSA_NODEFERกัน
โจนาธาน Leffler

2
@BulatM หากคุณไม่สามารถใช้งานได้sigaction()คุณจำเป็นต้องใช้ข้อกำหนดมาตรฐาน C เป็นsignal()หลัก อย่างไรก็ตามนั่นทำให้คุณมีตัวเลือกที่แย่มากสำหรับสิ่งที่คุณสามารถทำได้ คุณสามารถ: แก้ไข (ขอบเขตไฟล์) ตัวแปรประเภทvolatile sig_atomic_t; เรียกฟังก์ชั่นหนึ่ง 'ออกอย่างรวดเร็ว' ( _Exit(), quick_exit()) หรือabort(); โทรsignal()ด้วยหมายเลขสัญญาณปัจจุบันเป็นอาร์กิวเมนต์สัญญาณ; กลับ. และนั่นคือมัน สิ่งอื่นใดไม่รับประกันว่าจะสามารถพกพาได้ มันเข้มงวดมากที่คนส่วนใหญ่ไม่สนใจกฎเหล่านั้น - แต่ผลลัพธ์ที่ได้คือหลบ
Jonathan Leffler

1
sigaction()การสาธิตที่ยอดเยี่ยมจาก GCC ตัวเอง: gnu.org/software/libc/manual/html_node/… ; และยอดเยี่ยมsignal()การสาธิตจาก GCC ตัวเอง: gnu.org/software/libc/manual/html_node/... โปรดสังเกตว่าในการsignalสาธิตพวกเขาหลีกเลี่ยงการเปลี่ยนตัวจัดการจากการละเว้น ( SIG_IGN) ถ้านั่นคือสิ่งที่เคยตั้งค่าไว้โดยเจตนา
Gabriel Staples

8

สำหรับฉันบรรทัดด้านล่างนี้เพียงพอที่จะตัดสินใจ:

ฟังก์ชั่น sigaction () มอบกลไกที่ครอบคลุมและน่าเชื่อถือมากขึ้นสำหรับการควบคุมสัญญาณ แอปพลิเคชันใหม่ควรใช้ sigaction () มากกว่าสัญญาณ ()

http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html#tag_03_690_07

ไม่ว่าคุณจะเริ่มต้นจากศูนย์หรือดัดแปลงโปรแกรมเก่า sigaction ควรเป็นตัวเลือกที่เหมาะสม


5

พวกมันเป็นอินเตอร์เฟสที่แตกต่างกันสำหรับระบบอำนวยความสะดวกสัญญาณ เราควรเลือกใช้ sigaction เพื่อส่งสัญญาณถ้าเป็นไปได้เนื่องจากสัญญาณ () มีพฤติกรรมการใช้งานที่กำหนดไว้ (มักจะมีแนวโน้มการแข่งขัน) และมีพฤติกรรมแตกต่างกันไปใน Windows, OS X, Linux และระบบ UNIX อื่น ๆ

ดูหมายเหตุความปลอดภัยนี้เพื่อดูรายละเอียด


1
ฉันเพิ่งดูซอร์สโค้ด glibc และสัญญาณ () เพียงแค่เรียกใช้ sigaction () ดูด้านบนที่ที่หน้า Man ของ MacOS อ้างว่าเหมือนกัน
bmdhacks

นั่นเป็นเรื่องดีที่จะรู้ ฉันเคยเห็นเครื่องมือจัดการสัญญาณที่ใช้ในการปิดสิ่งต่าง ๆ อย่างเรียบร้อยก่อนที่จะออกดังนั้นฉันมักจะไม่พึ่งพาพฤติกรรมในการติดตั้งตัวจัดการ
Matthew Smith

5

สัญญาณ () คือมาตรฐาน C, sigaction () ไม่ใช่

หากคุณสามารถใช้ (นั่นคือคุณอยู่ในระบบ POSIX) จากนั้นใช้ sigaction (); มันไม่ได้ระบุว่าสัญญาณ () รีเซ็ตตัวจัดการหมายถึงการพกพาคุณจะต้องเรียกสัญญาณ () อีกครั้งภายในตัวจัดการ สิ่งที่แย่กว่านั้นคือมีการแข่งขัน: หากคุณได้รับสัญญาณสองสัญญาณติดต่อกันอย่างรวดเร็วและสัญญาณที่สองถูกส่งก่อนที่คุณจะติดตั้งตัวจัดการใหม่คุณจะมีการดำเนินการเริ่มต้นซึ่งอาจเป็นไปได้ที่จะฆ่ากระบวนการของคุณ ในทางกลับกัน sigaction ()นั้นรับประกันว่าจะใช้ซีแมนติกสัญญาณที่“ น่าเชื่อถือ” คุณไม่จำเป็นต้องติดตั้งตัวจัดการใหม่เพราะจะไม่ถูกรีเซ็ต ด้วย SA_RESTART คุณสามารถรับสายของระบบเพื่อเริ่มต้นใหม่โดยอัตโนมัติ (ดังนั้นคุณไม่จำเป็นต้องตรวจสอบ EINTR ด้วยตนเอง) sigaction () มีตัวเลือกเพิ่มเติมและเชื่อถือได้ดังนั้นจึงสนับสนุนการใช้งาน

Psst ... อย่าบอกใครเลยฉันบอกคุณแล้ว แต่ POSIX มีฟังก์ชัน bsd_signal () ซึ่งทำหน้าที่เหมือนสัญญาณ () แต่ให้ความหมาย BSD ซึ่งหมายความว่าเชื่อถือได้ การใช้งานหลักสำหรับการย้ายแอปพลิเคชันเก่าที่สันนิษฐานว่าเป็นสัญญาณที่เชื่อถือได้และ POSIX ไม่แนะนำให้ใช้


POSIX ไม่มีฟังก์ชั่นbsd_signal()- การใช้งาน POSIX บางอย่างอาจมีฟังก์ชั่น แต่ POSIX เองไม่มีฟังก์ชั่นดังกล่าว (ดูPOSIX )
Jonathan Leffler

4

ในระยะสั้น:

sigaction()เป็นสิ่งที่ดีและกำหนดไว้อย่างดี แต่เป็นฟังก์ชั่นลีนุกซ์ดังนั้นจึงสามารถใช้งานได้กับ Linux เท่านั้น signal()ไม่ดีและมีคุณภาพต่ำ แต่เป็นฟังก์ชั่นมาตรฐานแบบ C ดังนั้นมันจึงทำงานได้ทุกอย่าง

หน้า man ของ Linux ต้องพูดถึงอะไร?

man 2 signal(ดูออนไลน์ได้ที่นี่ ) สถานะ:

พฤติกรรมของสัญญาณ () จะแตกต่างกันไปตามรุ่นของ UNIX และมีความหลากหลายในอดีตในเวอร์ชันต่าง ๆ ของ Linux หลีกเลี่ยงการใช้: ใช้sigaction(2)แทน ดูการพกพาด้านล่าง

ความสามารถในการพกพาการใช้งานสัญญาณแบบพกพาเพียงอย่างเดียวคือการตั้งค่าการจัดการสัญญาณเป็น SIG_DFL หรือ SIG_IGN ซีแมนทิกส์เมื่อใช้สัญญาณ () เพื่อสร้างตัวจัดการสัญญาณแตกต่างกันไปตามระบบ (และ POSIX.1 อนุญาตการเปลี่ยนแปลงนี้อย่างชัดเจน); ห้ามใช้เพื่อจุดประสงค์นี้

ในคำอื่น ๆ : signal()ไม่ได้ใช้ ใช้sigaction()แทน!

GCC คิดอย่างไร

หมายเหตุความเข้ากันได้: ดังที่กล่าวไว้ข้างต้นสำหรับ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():

1. 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);

    //...
}

2. และ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);
  
}

ลิงก์หลักที่ควรระวัง:

  1. สัญญาณมาตรฐาน: https://www.gnu.org/software/libc/manual/html_node/Standard-Signals.html#Standard-Signals
    1. สัญญาณการสิ้นสุด: https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html#Termination-Signals
  2. การจัดการสัญญาณพื้นฐานรวมถึงsignal()ตัวอย่างการใช้งานGCC อย่างเป็นทางการ: https://www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
  3. sigaction()ตัวอย่างการใช้GCC อย่างเป็นทางการ: https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html
  4. ชุดสัญญาณรวมถึงsigemptyset()และsigfillset(); ฉันยังคงไม่เข้าใจสิ่งเหล่านี้อย่างแน่นอน แต่รู้ว่าพวกเขามีความสำคัญ: https://www.gnu.org/software/libc/manual/html_node/Signal-Sets.html

ดูสิ่งนี้ด้วย:

  1. บทเรียนการจัดการสัญญาณ C ++ [ด้วยรหัสตัวอย่างที่ยอดเยี่ยม]: https://www.tutorialspoint.com/cplusplus/cpp_signal_handling.htm
  2. https://www.tutorialspoint.com/c_standard_library/signal_h.htm

2

จากsignal(3)หน้าคน:

รายละเอียด

 This signal() facility is a simplified interface to the more
 general sigaction(2) facility.

ทั้งสองใช้สิ่งอำนวยความสะดวกพื้นฐานเดียวกัน คุณน่าจะไม่จัดการกับการตอบสนองของสัญญาณเดียวที่มีทั้งคู่ แต่การผสมพวกมันไม่ควรทำให้อะไรแตก ...


นั่นไม่ได้อยู่ในหน้าคนของฉัน! ทั้งหมดที่ฉันได้รับคือ "คำอธิบายการเรียกของสัญญาณ () ระบบจะติดตั้งตัวจัดการสัญญาณใหม่สำหรับสัญญาณที่มีหมายเลข signum" ฉันต้องอัปเกรดเป็นแพ็กเกจ man page ที่มีประโยชน์
Matthew Smith

1
ที่อยู่นอกหน้า Mac OS X 10.5
dmckee --- ผู้ดูแลอดีตลูกแมว

ตรวจสอบจากซอร์สโค้ดของ glibc ด้วยเช่นกัน สัญญาณ () เพียงแค่เรียก sigaction ()
bmdhacks

2
อย่างไรก็ตามนี่ไม่เป็นความจริงสำหรับการใช้งานสัญญาณทั้งหมด หากคุณต้องการมอบอำนาจพฤติกรรม "sigaction" อย่าพึ่งพาสมมติฐานนี้
Ben Burns

1

ฉันขอแนะนำให้ใช้ sigaction () over signal () และต้องการเพิ่มอีกหนึ่งจุด sigaction () ให้ตัวเลือกเพิ่มเติมแก่คุณเช่น pid ของกระบวนการที่เสียชีวิต (เป็นไปได้โดยใช้ siginfo_t struct)


0

ฉันจะใช้สัญญาณ () เนื่องจากเป็นแบบพกพามากกว่าในทางทฤษฎีอย่างน้อย ฉันจะลงคะแนนผู้แสดงความคิดเห็นที่สามารถเกิดขึ้นกับระบบที่ทันสมัยที่ไม่มีเลเยอร์ความเข้ากันได้ 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"


0

จากสัญญาณหน้าคน(7)

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

และผมจะบอกว่าเรื่องนี้ "ปัญหา" ที่มีอยู่สำหรับสัญญาณ (2)และsigaction (2) ดังนั้นระวังด้วยสัญญาณและ pthreads

... และสัญญาณ (2)ดูเหมือนจะเรียกsigaction (2)ข้างล่างใน Linux ด้วย glibc

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