Как ждать сигнал только определенное время на C языке? - PullRequest
1 голос
/ 25 февраля 2020

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

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

Как заставить второй процесс ждать определенного времени или, скажем, период времени?

В течение этого периода, если первый процесс предоставляет данные и отправляет сигнал второму, все все в порядке. В противном случае, если он не получит никакого сигнала от первого в течение этого периода, он будет делать другое.

Как я могу заставить второй процесс реагировать на эту потребность?

Какие алгоритмы и сигналы, которые я должен использовать, чтобы реализовать это?

Ответы [ 3 ]

2 голосов
/ 25 февраля 2020

POSIX определяет функцию именно для вашей цели: sigtimedwait(). Он будет приостанавливать выполнение вызывающего процесса до тех пор, пока или один из сигналов в указанном наборе не станет ожидающим, или истечет указанное время ожидания. Его возвращаемое значение указывает, какие из них произошли.

В течение этого периода, если первый процесс предоставляет данные и отправляет сигнал второму, все в порядке. В противном случае, если он не получит никакого сигнала от первого в течение этого периода, он будет делать другое.

Как я могу заставить второй процесс ответить на эту потребность?

Второй процесс устанавливает аргументы для sigtimedwait. Затем он блокирует ожидаемый сигнал (через sigprocmask), так что расположение по умолчанию не происходит при получении этого сигнала, а затем вызывает sigtimedwait. Возвращаемое значение последнего указывает, был ли получен один из указанных сигналов (и если да, то какой), или же функция вернулась по какой-то другой причине - обычно из-за истечения времени ожидания. В последнем случае можно проверить переменную errno, чтобы определить, действительно ли это был тайм-аут. На странице руководства, ссылка на которую приведена выше, содержатся некоторые дополнительные примечания по использованию.

В частности, вам нужно два основных аргумента:

  • a sigset_t, определяющих сигналы для блокировки и ожидания после , В разделе «См. Также» в конце страницы руководства приведена документация по связанным и аналогичным функциям, включая sigsetops(3), в которой рассказывается о том, как управлять такими объектами. Например,

    #include <signal.h>
    
    // ...
    
    sigset_t sigs;
    sigemptyset(&sigs);
    sigaddset(&sigs, SIGUSER2);
    
  • a struct timespec, чье определение приведено на странице руководства. Это определение должно быть достаточным для того, чтобы вы получили что-то вроде

    struct timespec timeout = { .tv_sec = 10 };
    

Для документов вы можете указать второй аргумент sigtimedwait как NULL, если вы этого не сделаете Вам нужна информация, которая в противном случае могла бы быть передана вам тем или иным способом, а вы - нет.

Вы можете использовать уже подготовленный набор сигналов, как описано выше, для настройки блокировки сигналов, например:

sigprocmask(SIG_BLOCK, &sigs, NULL);

Это может показаться немного нелогичным, поскольку вы действительно хотите получить сигнал, но эффект состоит в том, чтобы заблокировать любое расположение, установленное для возникновения сигнала, что отличается от пути обработки его через sigtimedwait.

На этом этапе вы готовы сделать вызов sigtimedwait():

int sig_num = sigtimedwait(&sigs, NULL, &timeout);

Результатом будет номер сигнала, если один из указанных сигналов (только SIGUSER2 в этом примере) принимается в течение указанного времени или -1 в противном случае. Следовательно,

if (sig_num == SIGUSER2) {
    // I received the signal
    // do something ...
} else {
    // assert(sig_num == -1);
    // I did not receive the signal within the alotted time
    // do something else ...
}

Вы можете предположить, что тайм-аут произошел в случае, когда сигнал не получен, но наиболее надежный код проверяет errno, чтобы убедиться, что:

    if (errno == EAGAIN) {
        // it was a timeout
    } else if (errno = EINTR) {
        // a signal outside the set was received
        // ... might want to calculate how much wait time is left and try again
        //     (left as an exercise)
    } else {
        // some other error occurred
        // ... aborting with an error might be best:
        perror("signal wait failed unexpectedly");
        exit(1);
    }
1 голос
/ 25 февраля 2020

Звоните спать до 10 секунд или сигнал будет:

struct timeval t = {10, 0};
int rc = select(0, NULL, NULL, NULL, &t);
if (rc == 0) {
    // timeout
} else if (errno == EINTR) {
    // signal
} else {
    // some error
0 голосов
/ 25 февраля 2020

Вы можете включить первый процесс вашего кода в бесконечное время l oop (например, while (1) {}) и, как только данные, вычисленные первым процессом, используют функции для отправки данных во второй процесс. Во втором процессе используйте функцию sleep (). Например;


main()
{
   printf("Sleep for 10 milisecond to exit.\n");
   sleep(0.10);
   return ;
}
you may change the time.
...