The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Сигналы и переходы jmp, !*! horse315, 04-Ноя-10, 18:11  [смотреть все]
Вашему вниманию несчастное универское задание:

---
# Составить программу, которая заданное число раз (для определенности 5) через определенный временной интервал (5 сек.) повторяет на экране запрос, ожидающий стандартный ввод. Процесс должен завершаться в случае корректного ответа на запрос или после исчерпывания заданного числа запросов. При написании программы рекомендуется использовать средства обработки сигнала от таймера и средства нелокального перехода.

Рекомендуется использовать системные вызовы alarm, signal, read и функции setjmp и localjmp.
---

И вот приблизительное решение, которое напрашивается. по идее должно бесконечно задавать вопрос, делая перерывы по 5 сек:

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

jmp_buf jmp;

void pauser(int sig){
    printf("no time no time...\n");
    sleep(5);
    longjmp(jmp,2);
}

int main(){
    char buf[128];
    const char ask[] = "Ioann IV sobriquet?\n";
    const char ans[] = "Grozniy\n";
    setjmp(jmp);
    signal(SIGALRM, pauser);
    alarm(5);
    do{
        write(1, ask, strlen(ask));
        read(0,buf,128);
    }while(strcmp(ans, buf)!=0);
    exit(1);
}

Но вот незадача, первый раз аларм сработал, снова выводится предложение ответить на вопрос и все, тишина) setjmp и alarm не дружат?
Типа:
Ioann IV sobriquet?_
no time no time...
Ioann IV sobriquet?_

  • Сигналы и переходы jmp, !*! ACCA, 10:28 , 05-Ноя-10 (1)
    Так работает:

    void pauser(int sig){
        printf("no time no time...\n");
        siglongjmp(jmp,1);
    }

    int main(){
        char buf[128];
        const char ask[] = "Ioann IV sobriquet?\n";
        const char ans[] = "Grozniy\n";
        signal(SIGALRM, pauser);
        sigsetjmp(jmp, SIGALRM);
        alarm(5);
        do{
            write(1, ask, strlen(ask));
            read(0,buf,128);
        }while(strcmp(ans, buf)!=0);
        exit(1);
    }

    Поиграйся ещё, обобщи что существенно и напиши здесь, pls.

    Неприлично мешать printf и write, выбери что-то одно. Ещё - выбрось \n, используй puts, так считается кошернее, читай с помощью fgets. При этом gets не годится, так как позволяет buffer overflow.

    • Сигналы и переходы jmp, !*! horse315, 11:13 , 05-Ноя-10 (2)
      >[оверквотинг удален]
      >     do{
      >         write(1, ask, strlen(ask));
      >         read(0,buf,128);
      >     }while(strcmp(ans, buf)!=0);
      >     exit(1);
      > }
      > Поиграйся ещё, обобщи что существенно и напиши здесь, pls.
      > Неприлично мешать printf и write, выбери что-то одно. Ещё - выбрось \n,
      > используй puts, так считается кошернее, читай с помощью fgets. При этом
      > gets не годится, так как позволяет buffer overflow.

      ОО все роскошно, спасибо! снова я man не внимательно прочитал((

  • Сигналы и переходы jmp, !*! guest, 16:15 , 06-Ноя-10 (3)
    > Рекомендуется использовать системные вызовы alarm, signal, read и функции setjmp и localjmp.

    Вам плохое рекомендуют.
    Про longjmp из обработчика лучше забыть (он не восстановит статические переменные libc на момент вызова setjmp), в не учебных программах это может стать причиной больших и трудно отлавливаемых проблем.
    Вместо signal лучше посмотрите на sigaction(2) вполне себе POSIX и не надо каждый раз заново переустанавливать обработчик.
    printf(3) в обработчике использовать нельзя т.к. это не signal-safe функция. На некоторых *nix можно (v)s(n)printf() и syslog_r, а вот printf я не видел нигде. Список/Ссылка на него функций разрешенных к вызову из обработчика сигнала должен быть в man signal(2)

    >     char buf[128];
    >         read(0,buf,128);

    корректнее все-таки читать sizeof(buf)-1 байт.


    > Но вот незадача, первый раз аларм сработал, снова выводится предложение ответить на
    > вопрос и все, тишина) setjmp и alarm не дружат?

    setjmp не сохраняет маску сигналов (это верно не для всех систем, но например линукс ведет себя именно так), т.е. из обработчика ваш код вываливается с заблокированным SIGALRM и вам надо либо явно разрешить его (sigprocmask(SIG_UNBLOCk,...), либо использовать sigsetjmp




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру