apue的第十章的习题10.5 仅使用一个计时器(alarm或较高精度的setitimer),构造一组函数,使得进程可以设置任一数目的计时器。
设计下面两个函数
int settimer(int seconds, void (*proc)(int));
int canceltimer(int id);
settimer的返回值是计时器的id(>=0),出错时返回-1.
设计下面这个构造体,
struct timer_t
{
char isused; // 是否有效
int seconds; // 剩余秒数
void (*proc)(int); // 超时调用函数指针
};
实现简单起见,用下面的数组表示多个定时器。
#define TIMERS_MAX 100
struct timer_t timers[TIMERS_MAX];
int curtimer_id; // 当前的定时器ID
具体看代码吧,有考虑不到的情况,请多多指教。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include <unistd.h>
- int opentimer();
- void closetimer();
- int settimer(int seconds, void (*proc)(int));
- int canceltimer(int id);
- struct timer_t
- {
- char isused;
- int seconds;
- void (*proc)(int);
- };
- #define TIMERS_MAX 100
- struct timer_t timers[TIMERS_MAX];
- int curtimer_id;
- void (*old_sig_proc)(int);
- sigset_t old_sigset;
- static int getid()
- {
- int id = -1;
- for (id = 0; id < TIMERS_MAX; id++)
- {
- if (timers[id].isused == 0)
- {
- break;
- }
- }
- return id;
- }
- static int getnexttimer(int cur_id)
- {
- int id;
- int surplus_seconds = 0;
- if (cur_id < 0)
- {
- for (id = 0; id < TIMERS_MAX; id++)
- {
- if (timers[id].isused == 1)
- {
- cur_id = id;
- break;
- }
- }
- }
- if (cur_id < 0)
- {
- return cur_id;
- }
- surplus_seconds = timers[cur_id].seconds;
- for (id = 0; id < TIMERS_MAX; id++)
- {
- if (timers[id].isused == 1 && surplus_seconds > timers[id].seconds)
- {
- surplus_seconds = timers[id].seconds;
- cur_id = id;
- }
- }
- return cur_id;
- }
- static void resetseconds(int over_seconds)
- {
- int id = 0;
- for (id = 0; id < TIMERS_MAX; id++)
- {
- if (timers[id].isused == 1)
- {
- timers[id].seconds -= over_seconds;
- }
- }
- return;
- }
- static void alarm_proc(int signo)
- {
- void (*cur_proc)(int);
- int cur_id;
- resetseconds(timers[curtimer_id].seconds);
- timers[curtimer_id].isused = 0;
- cur_proc = timers[curtimer_id].proc;
- cur_id = curtimer_id;
- curtimer_id = getnexttimer(-1);
- if (signal(SIGALRM, alarm_proc) == SIG_ERR)
- {
- exit(-1);
- }
- alarm(timers[curtimer_id].seconds);
- cur_proc(cur_id);
- }
- int opentimer()
- {
- sigset_t new_sigset;
- curtimer_id = -1;
- memset(timers, 0, sizeof(timers));
- // cancel previous alarm
- alarm(0);
- old_sig_proc = signal(SIGALRM, NULL);
- // UNBLOCK SIGALRM
- sigemptyset(&new_sigset);
- sigaddset(&new_sigset, SIGALRM);
- if (sigprocmask(SIG_UNBLOCK, &new_sigset, &old_sigset) < 0)
- {
- return -1;
- }
- return 0;
- }
- void closetimer()
- {
- alarm(0);
- curtimer_id = -1;
- memset(timers, 0, sizeof(timers));
- if (sigprocmask(SIG_SETMASK, &old_sigset, NULL) < 0)
- {
- exit(1);
- }
- }
- int settimer(int seconds, void (*proc)(int))
- {
- int id = -1;
- int surplus_seconds = 0;
- int over_seconds = 0;
- void (*retfunc)(int);
- id = getid();
- if (id < 0)
- {
- return id;
- }
- timers[id].seconds = seconds;
- timers[id].proc = proc;
- timers[id].isused = 1;
- surplus_seconds = alarm(0);
- if (surplus_seconds > 0)
- {
- over_seconds = timers[curtimer_id].seconds - surplus_seconds;
- resetseconds(over_seconds);
- }
- curtimer_id = getnexttimer(id);
- if (signal(SIGALRM, alarm_proc) == SIG_ERR)
- {
- return -1;
- }
- alarm(timers[curtimer_id].seconds);
- return id;
- }
- int canceltimer(int cancel_id)
- {
- int surplus_seconds = 0;
- int over_seconds;
- if (timers[cancel_id].isused == 0)
- {
- return 0;
- }
- if (cancel_id != curtimer_id)
- {
- timers[cancel_id].isused = 0;
- timers[cancel_id].seconds = 0;
- timers[cancel_id].proc = NULL;
- return 0;
- }
- surplus_seconds = alarm(0);
- over_seconds = timers[curtimer_id].seconds - surplus_seconds;
- resetseconds(over_seconds);
- timers[cancel_id].isused = 0;
- timers[cancel_id].seconds = 0;
- timers[cancel_id].proc = NULL;
- curtimer_id = getnexttimer(-1);
- if (signal(SIGALRM, alarm_proc) == SIG_ERR)
- {
- return -1;
- }
- alarm(timers[curtimer_id].seconds);
- return 0;
- }
- void proc1(int id)
- {
- printf("proc1 id:%d\n", id);
- //settimer(5, proc1);
- return;
- }
- void proc2(int id)
- {
- printf("proc2 id:%d\n", id);
- return;
- }
- void proc3(int id)
- {
- printf("proc3 id:%d\n", id);
- return;
- }
- int main(int argc, char *argv[ ])
- {
- int id1, id2, id3;
- id1 = settimer(10, proc1);
- id2 = settimer(5, proc2);
- id3 = settimer(8, proc3);
- canceltimer(id3);
- id3 = settimer(15, proc3);
- while (1)
- pause();
- }
阅读(2801) | 评论(0) | 转发(0) |