Каково различие между sigaction и сигналом?

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

131
задан Francesco Boi 2 January 2019 в 14:31
поделиться

5 ответов

Используйте sigaction() , если у Вас нет очень неопровержимых доводов, чтобы не сделать так.

signal() интерфейс имеет старину (и следовательно доступность) в ее пользу, и это определяется в стандарте C. Тем не менее, это имеет много нежелательных характеристик, который sigaction() избегает - если Вы не используете флаги, явно добавленные к sigaction(), чтобы позволить этому искренне моделировать старое signal() поведение.

  1. Эти signal() функция не (обязательно) блокирует другие сигналы от прибытия, в то время как текущий обработчик выполняется; sigaction() может заблокировать другие сигналы до текущих возвратов обработчика.
  2. Эти signal() функция (обычно) сбрасывает действие сигнала назад к SIG_DFL (значение по умолчанию) почти для всех сигналов. Это означает, что signal() обработчик должен переустановить себя как свое первое действие. Это также открывает окно уязвимости между временем, когда сигнал обнаруживается, и обработчик переустанавливается, во время, которого если прибывает второй экземпляр сигнала, поведение по умолчанию (обычно оконечный, иногда с предубеждением - иначе дамп ядра) происходит.
  3. точное поведение [1 110] варьируется между системами —, и стандарты разрешают те изменения.

Это обычно серьезные основания для использования sigaction() вместо [1 112]. Однако интерфейс [1 113] бесспорно более труден.

, Какой бы ни из двух Вы используете, не соблазняйтесь альтернативными сигнальными интерфейсами такой как [1 138] sighold() , sigignore() , sigpause() и sigrelse() . Они - номинально альтернативы [1 118], но они только едва стандартизированы и присутствуют в POSIX для назад совместимости, а не для серьезного использования. Обратите внимание, что в стандарте POSIX говорится, что их поведение в многопоточных программах не определено.

Многопоточные программы и сигналы целая другая сложная история. AFAIK, и signal() и sigaction() в порядке в многопоточных приложениях.

Cornstalks наблюдает :

в странице справочника Linux для [1 144] signal() говорится:

   эффекты [1 170] signal() в многопоточном процессе являются неуказанными.

Таким образом, я думаю sigaction(), единственное, которое может использоваться безопасно в многопоточном процессе.

Это интересно. Страница руководства Linux более строга, чем POSIX в этом случае. POSIX указывает для [1 145] signal() :

, Если процесс является многопоточным, или если процесс является однопоточным и обработчик сигналов выполняется кроме как результат:

  • процесс, звоня abort(), raise(), kill(), pthread_kill(), или sigqueue(), чтобы сгенерировать сигнал, который не заблокирован
  • А, ожидающий разблокируемый сигнал и поставляемый перед вызовом, который разблокировал его возвраты

, поведение не определено, если обработчик сигналов относится к какому-либо объекту кроме [1 131] со статической продолжительностью хранения кроме путем присвоения значения объекту, объявленному как [1 132], или если обработчик сигналов называет какую-либо функцию, определяемую в этом стандарте кроме одной из функций перечисленной в [1 146] Понятия .

Сигнала

, Таким образом, POSIX ясно указывает поведение [1 133] в многопоточном приложении.

, Тем не менее, sigaction() должен быть предпочтен при по существу всех обстоятельствах —, и портативный многопоточный код должен использовать sigaction(), если нет подавляющая причина, почему это не может (такой как "только функции, определяемые использования по Стандарту C" —, и да, код C11 может быть многопоточным). Который является в основном, что также говорит вводный абзац этого ответа.

157
ответ дан 24 November 2019 в 00:19
поделиться

Они - различные интерфейсы для средств сигнала ОС. Нужно предпочесть использовать sigaction для передачи сигналов, если это возможно, поскольку сигнал () определил реализацией (часто склонная гонка) поведение и ведет себя по-другому в Windows, OS X, Linux и других системах UNIX.

Посмотрите этот примечание по безопасности: для деталей.

5
ответ дан 24 November 2019 в 00:19
поделиться

От signal(3) страница справочника:

ОПИСАНИЕ

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

Оба вызывают то же базовое средство. Вы не должны, по-видимому, управлять ответом, одиночный сигнал с обоими, но смешивание их не должен заставлять ничего повреждаться...

2
ответ дан 24 November 2019 в 00:19
поделиться

Я использовал бы сигнал (), так как это более портативно в теории, по крайней мере. Я проголосую за любого комментатора, который может придумать современную систему, которая не имеет слоя совместимости POSIX и поддерживает сигнал ().

Заключение в кавычки от документация GLIBC :

возможно использовать и сигнал и функции sigaction в рамках единственной программы, но необходимо быть осторожными, потому что они могут взаимодействовать немного странными способами.

функция sigaction указывает больше информации, чем функция сигнала, таким образом, возвращаемое значение от сигнала не может выразить полного спектра sigaction возможностей. Поэтому при использовании сигнала сохранить и позже восстановить действие он не может восстанавливать правильно обработчик, который был установлен с sigaction.

, Чтобы постараться не иметь проблемы в результате всегда используют sigaction, чтобы сохранить и восстановить обработчик, если Ваша программа использует sigaction вообще. Так как sigaction является более общим, он может правильно сохранить и восстановить любое действие, независимо от того, был ли он установлен первоначально с сигналом или sigaction.

В некоторых системах, если Вы устанавливаете действие с сигналом и затем исследуете его с sigaction, адрес обработчика, что Вы добираетесь, не может совпасть с тем, что Вы указали с сигналом. Это даже не может подойти для использования в качестве спора действия с сигналом. Но можно полагаться на использование его как аргумент sigaction. Этой проблемы никогда не происходит в системе GNU.

Так, Вы - более обеспеченное использование того или других из механизмов последовательно в рамках единственной программы.

Примечание Мобильности: функция базового сигнала является функцией ISO C, в то время как sigaction является частью стандарта POSIX.1. Если Вы обеспокоены мобильностью к системам неPOSIX, то необходимо использовать функцию сигнала вместо этого.

Copyright (C) 1996-2008 Free Software Foundation, Inc.

Разрешение дано, чтобы скопировать, распределить и/или изменить этот документ в соответствии с Лицензией свободной документации GNU, Версией 1.2 или любой более поздней версией, опубликованной Free Software Foundation; без Инвариантных Разделов, без текстов Передней крышки, и без текстов На задней обложке. Копия лицензии включена в раздел, наделенный правом "Лицензия свободной документации GNU".

0
ответ дан 24 November 2019 в 00:19
поделиться

Короче говоря:

sigaction() хорошо и четко определен, но функция Linux и таким образом, она работает только над Linux. signal() плохо и плохо определяется, но стандартная функция C и таким образом, она работает над чем-либо.

, Что страницы справочника 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() вещь!?

Примеры Использования:

GCC's Чтения, ПРЕВОСХОДНЫЙ signal() пример здесь: 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

После того, чтобы читать те страницы, я придумал следующую технику для [1 115]:

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


    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 https://stackoverflow.com/questions/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. И для [1 117], даже при том, что не хороший способ присоединить обработчик сигналов, как описано выше, все еще хорошо знать, как использовать его.

Вот демонстрационный вставляемый копией код 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. , включая официальный пример GCC signal() использования: https://пример GCC sigaction() использования Чиновника www.gnu.org/software/libc/manual/html_node/Basic-Signal-Handling.html#Basic-Signal-Handling
  3. : https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html
  4. наборы Сигнала, включая [1 120] и sigfillset(); я все еще не понимаю их точно, но знаю, что они важны: https://www.gnu.org/software/libc/manual/html_node/Signal-Sets.html

Видит также:

  1. TutorialsPoint Обработка Сигнала C++ [с превосходным демонстрационным кодом]: https://www.tutorialspoint.com/cplusplus/cpp_signal_handling.htm
  2. https://www.tutorialspoint.com/c_standard_library/signal_h.htm
0
ответ дан 24 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: