Сигналы и переходы 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
|