खोज…


वाक्य - विन्यास

  • अहस्ताक्षरित अलार्म (अहस्ताक्षरित सेकंड);
  • int किल (pid_t pid, int sig);

पैरामीटर

फ़ंक्शन, पैरामीटर (एस), रिटर्न वैल्यू विवरण
alarm() समारोह का नाम
unsigned seconds किसी भी लंबित अलार्म को रद्द करने के लिए अलार्म या 0 जुटाने के लिए सेकंड
> = ० 0 यदि कोई अन्य अलार्म लंबित नहीं था, तो लंबित अलार्म की सेकंड की संख्या अभी भी खुली थी। यह फ़ंक्शन विफल नहीं होगा।
- -
kill() समारोह का नाम
pid_t pid
int sig 0 या सिग्नल आई.डी.
0, -1 सफलता 0 पर, -1 को EINVAL , EPERM या ESRCH को errno करने में विफलता के साथ।

डिफ़ॉल्ट क्रिया के साथ SIGALARM को उठाना

alarm का उपयोग करते हुए, उपयोगकर्ता निर्दिष्ट अंतराल के बाद उठाए जाने वाले SIGALARM सिग्नल को शेड्यूल कर सकता है। यदि उपयोगकर्ता ने इस सिग्नल के लिए स्पष्ट सिग्नल हैंडलर को अवरुद्ध, नजरअंदाज या निर्दिष्ट नहीं किया है, तो इस सिग्नल के लिए डिफ़ॉल्ट कार्रवाई आगमन पर की जाएगी। SIGALARM लिए प्रति विनिर्देश डिफ़ॉल्ट कार्रवाई प्रक्रिया को समाप्त करना है:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char** argv)
{
    printf("Hello!\n");

    // Set the alarm for five second
    alarm(5); // Per POSIX, this cannot fail

    // Now sleep for 15 seconds
    for (int i = 1; i <= 15; i++)
    {
        printf("%d\n", i);
        sleep(1);
    }

    // And print the message before successful exit
    printf("Goodbye!\n");

    return EXIT_SUCCESS;
}

यह आउटपुट:

Hello!
1
2
3
4
5
[2]    35086 alarm      ./a.out

सिगनेशन का उपयोग करके सिग्नल हैंडलर सेट करना और सिग्नल का उपयोग करके उठाना

एक निश्चित सिग्नल पर प्रतिक्रिया करने के लिए प्रोग्राम के लिए, डिफ़ॉल्ट एक्शन का उपयोग करने के अलावा, कस्टम सिग्नल हैंडलर को sigaction का उपयोग करके स्थापित किया जा सकता है। sigaction को तीन तर्क मिलते हैं - कार्य करने के लिए संकेत, sigaction_t संरचना के लिए सूचक, जो यदि NULL नहीं है, तो नए व्यवहार और सूचक को sigaction_t पर sigaction_t कर रहा है, जो नहीं तो NULL पुराने व्यवहार से भर जाएगा (इसलिए कोई इसे पुनर्स्थापित कर सकता है)। एक ही प्रक्रिया में संकेतों को ऊपर raise विधि के साथ किया जा सकता है। यदि अधिक नियंत्रण की आवश्यकता है (सिग्नल को किसी अन्य प्रक्रिया में भेजने के लिए, kill या pthread_kill का उपयोग किया जा सकता है, जो गंतव्य प्रक्रिया आईडी या थ्रेड आईडी को स्वीकार करते हैं)।

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Signals are numbered from 1, signal 0 doesn't exist
volatile sig_atomic_t last_received_signal = 0;

// Signal handler, will set the global variable
// to indicate what is the last signal received.
// There should be as less work as possible inside
// signal handler routine, and one must take care only
// to call reentrant functions (in case of signal arriving
// while program is already executing same function)
void signal_catcher(int signo, siginfo_t *info, void *context)
{
    last_received_signal = info->si_signo;
}

int main (int argc, char** argv)
{
    // Setup a signal handler for SIGUSR1 and SIGUSR2
    struct sigaction act;
    memset(&act, 0, sizeof act);

    // sigact structure holding old configuration
    // (will be filled by sigaction):
    struct sigaction old_1;
    memset(&old_1, 0, sizeof old_1);
    struct sigaction old_2;
    memset(&old_2, 0, sizeof old_2);

    act.sa_sigaction = signal_catcher;
    // When passing sa_sigaction, SA_SIGINFO flag
    // must be specified. Otherwise, function pointed
    // by act.sa_handler will be invoked
    act.sa_flags = SA_SIGINFO;

    if (0 != sigaction(SIGUSR1, &act, &old_1))
    {
        perror("sigaction () failed installing SIGUSR1 handler");
        return EXIT_FAILURE;
    }

    if (0 != sigaction(SIGUSR2, &act, &old_2))
    {
        perror("sigaction() failed installing SIGUSR2 handler");
        return EXIT_FAILURE;
    }

    // Main body of "work" during which two signals
    // will be raised, after 5 and 10 seconds, and which
    // will print last received signal
    for (int i = 1; i <= 15; i++)
    {
        if (i == 5)
        {
            if (0 != raise(SIGUSR1))
            {
                perror("Can't raise SIGUSR1");
                return EXIT_FAILURE;
            }
        }

        if (i == 10)
        {
            if (0 != raise(SIGUSR2))
            {
                perror("Can't raise SIGUSR2");
                return EXIT_FAILURE;
            }
        }

        printf("Tick #%d, last caught signal: %d\n",
            i, last_received_signal);

        sleep(1);
    }

    // Restore old signal handlers
    if (0 != sigaction(SIGUSR1, &old_1, NULL))
    {
        perror("sigaction() failed restoring SIGUSR1 handler");
        return EXIT_FAILURE;
    }

    if (0 != sigaction(SIGUSR2, &old_2, NULL))
    {
        perror("sigaction() failed restoring SIGUSR2 handler");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

यह आउटपुट:

Tick #1, last caught signal: 0
Tick #2, last caught signal: 0
Tick #3, last caught signal: 0
Tick #4, last caught signal: 0
Tick #5, last caught signal: 30
Tick #6, last caught signal: 30
Tick #7, last caught signal: 30
Tick #8, last caught signal: 30
Tick #9, last caught signal: 30
Tick #10, last caught signal: 31
Tick #11, last caught signal: 31
Tick #12, last caught signal: 31
Tick #13, last caught signal: 31
Tick #14, last caught signal: 31
Tick #15, last caught signal: 31

हत्या का उपयोग कर आत्महत्या करने की प्रक्रिया ()

एक प्रक्रिया किसी भी अन्य प्रक्रिया को kill() फ़ंक्शन का उपयोग करके एक संकेत भेज सकती है (कोशिश कर सकती है kill()

ऐसा करने के लिए, भेजने की प्रक्रिया को प्राप्त करने की प्रक्रिया को जानना होगा 'पीआईडी। जैसा कि, एक दौड़ शुरू किए बिना, एक प्रक्रिया केवल अपने स्वयं के पीआईडी (और अपने बच्चों के पीआईडी) के बारे में सुनिश्चित कर सकती है कि kill() के उपयोग को प्रदर्शित करने के लिए सबसे सरल उदाहरण है kill() एक प्रक्रिया को स्वयं एक संकेत भेजना है।

एक प्रक्रिया के एक उदाहरण के नीचे खुद को मार-संकेत ( SIGKILL ) भेजकर अपनी समाप्ति की शुरुआत की:

#define _POSIX_C_SOURCE 1

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>


int main (void)
{
  pid_t pid = getpid(); /* Get my iown process ID. */

  kill(pid, SIGKILL); /* Send myself a KILL signal. */

  puts("Signal delivery initiated.");  /* Although not guaranteed, 
                                  practically the program never gets here. */

  pause(); /* Wait to die. */

  puts("This never gets printed.");
}

आउटपुट:

Killed

(... या एक जैसे, कार्यान्वयन पर निर्भर करता है)

थ्रेड-सुरक्षित तरीके से लिखकर () द्वारा निर्मित हैंडल साइनिप

जब नाम write() एक नामित या अनाम पाइप या स्ट्रीम सॉकेट के लिए बुलाया जाता है जिसका रीडिंग एंड बंद होता है, तो दो चीजें होती हैं:

POSIX.1-2001
  1. SIGPIPE सिग्नल उस प्रक्रिया को भेजा जाता है जिसे write() कहा जाता है write()
POSIX.1-2004
  1. SIGPIPE सिग्नल को थ्रेड को भेजा जाता है जिसे write() कहा जाता है
  1. EPIPE त्रुटि write() से वापस आ जाती है write()

SIGPIPE से निपटने के कई तरीके हैं:

  • सॉकेट के लिए, SIGPIPE की तरह मंच-विशिष्ट विकल्प की स्थापना द्वारा निष्क्रिय किया जा सकता MSG_NOSIGNAL लिनक्स में और SO_NOSIGPIPE (केवल के लिए काम करता बीएसडी में send , लेकिन के लिए नहीं write )। यह पोर्टेबल नहीं है।
  • FIFOs (नामित पाइप) के लिए, SIGPIPE यदि लेखक का उपयोग करता है उत्पन्न नहीं की जाएगी O_RDWR के बजाय O_WRONLY , ताकि पढ़ने अंत हमेशा खोला जाता है। हालाँकि, यह EPIPE भी निष्क्रिय कर देता है।
  • हम SIGPIPE को अनदेखा कर सकते हैं या वैश्विक हैंडलर सेट कर सकते हैं। यह एक अच्छा समाधान है, लेकिन यह स्वीकार्य नहीं है यदि आप पूरे आवेदन को नियंत्रित नहीं करते हैं (उदाहरण के लिए आप एक पुस्तकालय लिख रहे हैं)।
  • हाल के POSIX संस्करणों के साथ, हम इस तथ्य का उपयोग कर सकते हैं कि SIGPIPE थ्रेड को भेजा जाता है जिसे write() कहा जाता है और इसे सिंक्रोनस सिग्नल हैंडलिंग तकनीक का उपयोग करके संभालना है।

नीचे कोड POSIX.1-2004 और बाद के लिए थ्रेड-सुरक्षित SIGPIPE हैंडलिंग प्रदर्शित करता है।

यह इस पोस्ट से प्रेरित है:

  • सबसे पहले, SIGPIPE को pthread_sigmask() का उपयोग करके वर्तमान थ्रेड के सिग्नल मास्क में जोड़ें।
  • अगर वहाँ पहले से ही लंबित है की जाँच करें SIGPIPE का उपयोग कर sigpending()
  • कॉल write() । यदि रीडिंग एंड बंद है, तो SIGPIPE को लंबित सिग्नल मास्क में जोड़ा जाएगा और EPIPE को लौटा दिया जाएगा।
  • यदि write() वापस EPIPE , और SIGPIPE write() से पहले ही लंबित नहीं था write() , इसे sigtimedwait() का उपयोग करके लंबित सिग्नल मास्क से हटा दें।
  • pthread_sigmask() का उपयोग करके मूल सिग्नल मास्क को पुनर्स्थापित करें।

सोर्स कोड:

#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <sys/signal.h>

ssize_t safe_write(int fd, const void* buf, size_t bufsz)
{
    sigset_t sig_block, sig_restore, sig_pending;

    sigemptyset(&sig_block);
    sigaddset(&sig_block, SIGPIPE);

    /* Block SIGPIPE for this thread.
     *
     * This works since kernel sends SIGPIPE to the thread that called write(),
     * not to the whole process.
     */
    if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0) {
        return -1;
    }

    /* Check if SIGPIPE is already pending.
     */
    int sigpipe_pending = -1;
    if (sigpending(&sig_pending) != -1) {
        sigpipe_pending = sigismember(&sig_pending, SIGPIPE);
    }

    if (sigpipe_pending == -1) {
        pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
        return -1;
    }

    ssize_t ret;
    while ((ret = write(fd, buf, bufsz)) == -1) {
        if (errno != EINTR)
            break;
    }

    /* Fetch generated SIGPIPE if write() failed with EPIPE.
     *
     * However, if SIGPIPE was already pending before calling write(), it was
     * also generated and blocked by caller, and caller may expect that it can
     * fetch it later. Since signals are not queued, we don't fetch it in this
     * case.
     */
    if (ret == -1 && errno == EPIPE && sigpipe_pending == 0) {
        struct timespec ts;
        ts.tv_sec = 0;
        ts.tv_nsec = 0;

        int sig;
        while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1) {
            if (errno != EINTR)
                break;
        }
    }

    pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
    return ret;
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow