Попросили младшие курсы помочь с лабами по операционным системам... Кинули мне мой же исходник с претензиями, что работает криво. Сам я уже не помню насколько прога была рабочая, времени прошло уже 3 года.
Но проблема действительно есть: Первый вызов alarm() устанавливает таймер, в назначенное время приходит сигнал, обрабатывается, все довольны. Обработчик сигнала устанавливается обратно, снова вызывается alarm()... и все. На этом месте начинается бесконечный цикл, прерываемый только ^C.
Суть проги в кратце: компьютер играет сам с собой в кости. Визуализуется бросок крутящейся в терминале палочкой, длительность броска задается вышеозначенным алармом. Принимает два аргумента - время в секундах для каждого из 2 игроков.
Код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
unsigned int i;
jmp_buf pos;
char *who[] = {"Com1: ", "Com2: "};
char *ind[] = {"|\b", "/\b", "-\b", "\\\b"};
char digit[] = {"1\n"};
void handler()
{
static int j=0;
digit[0] = '1' + i%6;
write(1, digit, 2);
longjmp(pos, ++j);
}
int main(int argc, char **argv)
{
int time[2], j=0;
if (argc<3 || (time[0] = atoi(argv[1]))<1 || (time[1] = atoi(argv[2]))<1) {
write(1, "Usage: lab6_19 time1 time2\nTimes must be > 0\n", 45);
exit(-1);
}
struct sigaction s;
memset(&s, 0, sizeof(struct sigaction));
s.sa_handler = handler;
if ((j = setjmp(pos)) < 2) {
sigaction(SIGALRM, &s, 0);
alarm(time[j]);
write(1, who[j], 6);
}
for (i=getpid()%6; j<2; i++) {
write(1, ind[i%4], 2);
usleep(250000);
}
exit(0);
}
Результат strace, наглядно иллюстрирующий, что сигнал повторно не приходит:
rt_sigaction(SIGALRM, {0x8048584, [], SA_RESETHAND}, NULL, 8) = 0
alarm(1) = 0
write(1, "Com1: "..., 6Com1: ) = 6
getpid() = 29333
write(1, "/\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "-\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "\\\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "|\10"..., 2) = 2
nanosleep({0, 250000000}, 0) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, "3\n"..., 23
) = 2
alarm(1) = 0
write(1, "Com2: "..., 6Com2: ) = 6
write(1, "/\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "-\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "\\\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "|\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "/\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "-\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "\\\10"..., 2) = 2
nanosleep({0, 250000000}, NULL) = 0
write(1, "|\10"..., 2) = 2
... и далее до бесконечности
Куча write вместо printf и иже с ним - условие лаб.